Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions inputs/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ init {
#+ Ejemplo de una variable mal declarada +#
#+ fecha : date +#
#+ h : foat +#

#+ Ejemplo de error por redeclaracion de variable +#
#+ a1: int +#
}

a1 := -125
b2 := -125
b2 := a1

c33 := 5.34
Expand Down
107 changes: 105 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use std::{
cell::RefCell,
fmt::Display,
fs::{File, OpenOptions, read_to_string},
io::{self, Read, Seek, Write},
ops::Range,
path::PathBuf,
};
use thiserror::Error;

use crate::{
grammar_actions::{DataType, TokenFloatLiteral, TokenIntLiteral, TokenStringLiteral},
grammar_lexer::log_error,
};

#[derive(Debug, Error)]
pub enum CompilerError {
#[error("Parser internal error: {0:?}")]
Expand All @@ -25,6 +32,7 @@ thread_local! {
pub static LEXER_FILE: RefCell<Option<File>> = const { RefCell::new(None) };
pub static PARSER_FILE: RefCell<Option<File>> = const { RefCell::new(None) };
pub static SYMBOL_TABLE_FILE: RefCell<Option<File>> = const { RefCell::new(None) };
pub static SYMBOL_TABLE: RefCell<Vec<SymbolTableElement>> = const { RefCell::new(Vec::new())}
}

pub fn set_source_file_path(path: PathBuf) {
Expand Down Expand Up @@ -95,15 +103,34 @@ pub fn open_symbol_table_file() -> Result<(), io::Error> {
})
}

pub fn write_to_symbol_table_file(line: &str) -> Result<(), io::Error> {
pub fn dump_symbol_table_to_file() -> Result<(), io::Error> {
SYMBOL_TABLE_FILE.with(|f| {
if let Some(mut file) = f.borrow_mut().as_ref() {
writeln!(file, "{line}")?;
for symbol in SYMBOL_TABLE.take() {
writeln!(file, "{symbol}")?;
}
}
Ok(())
})
}

pub fn log_error_and_exit(
pos: Range<usize>,
error: CompilerError,
offset: usize,
trace: bool,
) -> ! {
dump_symbol_table_to_file().expect("Failed to write symbol table");
log_error(
pos,
error,
offset,
&read_source_to_string().expect("Failed to print error location"),
trace,
);
std::process::exit(1)
}

pub fn read_source_to_string() -> Result<String, CompilerError> {
SOURCE_CODE_PATH.with(|f| {
if let Some(path) = f.borrow().as_ref() {
Expand Down Expand Up @@ -134,3 +161,79 @@ pub fn read_parser_file_to_string() -> Result<String, CompilerError> {
}
})
}

#[derive(Clone, Debug)]
pub enum SymbolTableElement {
VarDeclaration(String, DataType, usize),
IntLiteral(TokenIntLiteral),
FloatLiteral(TokenFloatLiteral),
StringLiteral(TokenStringLiteral),
}

impl Display for SymbolTableElement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::FloatLiteral(float) => write!(
f,
"{}|CONST_FLOAT|{}|{}",
float.original,
float.original,
float.original.len()
)?,
Self::IntLiteral(int) => {
write!(f, "{}|CONST_INT|{}|{}", int, int, int.to_string().len())?
}
Self::StringLiteral(string) => {
write!(f, "{}|CONST_STRING|{}|{}", string, string, string.len())?
}
Self::VarDeclaration(token, r#type, length) => {
write!(f, "{}|{}|-|{}", token, r#type, length)?
}
};
Ok(())
}
}

impl PartialEq for SymbolTableElement {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::FloatLiteral(token0), Self::FloatLiteral(token1)) => token0 == token1,
(Self::IntLiteral(token0), Self::IntLiteral(token1)) => token0 == token1,
(Self::StringLiteral(token0), Self::StringLiteral(token1)) => token0 == token1,
(Self::VarDeclaration(token0, _, _), Self::VarDeclaration(token1, _, _)) => {
token0 == token1
}
_ => false,
}
}
}

impl From<TokenIntLiteral> for SymbolTableElement {
fn from(value: TokenIntLiteral) -> Self {
Self::IntLiteral(value)
}
}

impl From<TokenFloatLiteral> for SymbolTableElement {
fn from(value: TokenFloatLiteral) -> Self {
Self::FloatLiteral(value)
}
}

impl From<TokenStringLiteral> for SymbolTableElement {
fn from(value: TokenStringLiteral) -> Self {
Self::StringLiteral(value)
}
}
pub fn push_to_symbol_table(item: SymbolTableElement) {
SYMBOL_TABLE.with(|table| {
// Avoid pushing duplicate symbols to the symbol table
if !symbol_exists(&item) {
table.borrow_mut().push(item);
}
})
}

pub fn symbol_exists(item: &SymbolTableElement) -> bool {
SYMBOL_TABLE.with(|table| table.borrow().contains(item))
}
Loading