Simple type checking in the symbol table

master
Araozu 2023-01-23 08:34:24 -05:00
parent 1c90ee293b
commit 418be5dc17
3 changed files with 51 additions and 8 deletions

View File

@ -13,7 +13,7 @@ fn compile(input: &String) {
Ok(tokens) => { Ok(tokens) => {
let mut ast = syntax::construct_ast(&tokens).unwrap(); let mut ast = syntax::construct_ast(&tokens).unwrap();
let mut table = SymbolTable::new(); let mut table = SymbolTable::new();
let new_ast = semantic::check_ast(&mut ast, &mut table); semantic::check_ast(&mut ast, &mut table);
}, },
Err(error) => { Err(error) => {
eprintln!("Error scanning.\n{} at pos {}", error.reason, error.position) eprintln!("Error scanning.\n{} at pos {}", error.reason, error.position)

View File

@ -1,14 +1,23 @@
use crate::symbol_table; use super::symbol_table::{SymbolTable, _NUMBER};
use super::ast_types::{ModuleAST, Binding};
use super::symbol_table::SymbolTable; /// Checks the ast. In the future should return a list of errors.
use super::ast_types::ModuleAST; pub fn check_ast<'a>(ast: &'a mut ModuleAST, symbol_table: &'a mut SymbolTable) {
for binding in &ast.bindings {
pub fn check_ast<'a>(ast: &'a mut ModuleAST, symbol_table: &'a mut SymbolTable) -> Option<ModuleAST<'a>> { match binding {
None Binding::Val(val_binding) => {
// TODO: create a function to get the datatype, instead of a hardcoded value
symbol_table.add(val_binding.identifier, _NUMBER);
}
}
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::syntax;
use crate::lexic;
use super::*; use super::*;
/* /*
@ -31,4 +40,16 @@ mod tests {
identifier: Num identifier: Num
} }
*/ */
#[test]
fn should_update_symbol_table() {
let tokens = lexic::get_tokens(&String::from("val identifier = 20")).unwrap();
let mut table = SymbolTable::new();
let mut ast = syntax::construct_ast(&tokens).unwrap();
check_ast(&mut ast, &mut table);
let result = table.test("identifier");
assert_eq!(true, result);
}
} }

View File

@ -11,7 +11,7 @@ pub struct SymbolTable {
impl SymbolTable { impl SymbolTable {
pub fn new() -> SymbolTable { pub fn new() -> SymbolTable {
let mut symbol_table = HashMap::<String, String>::new(); let symbol_table = HashMap::<String, String>::new();
SymbolTable { SymbolTable {
table: symbol_table, table: symbol_table,
@ -25,6 +25,20 @@ impl SymbolTable {
pub fn test(&self, identifier: &str) -> bool { pub fn test(&self, identifier: &str) -> bool {
return self.table.contains_key::<String>(&String::from(identifier)); return self.table.contains_key::<String>(&String::from(identifier));
} }
pub fn check_type(&self, identifier: &str, datatype: &str) -> bool {
self.table
.get_key_value(&String::from(identifier))
.and_then(|(_, value)| {
if value == &String::from(datatype) {
Some(true)
}
else {
Some(false)
}
})
.unwrap_or(false)
}
} }
@ -43,4 +57,12 @@ mod tests {
table.add("identifier", _NUMBER); table.add("identifier", _NUMBER);
assert_eq!(true, table.test("identifier")) assert_eq!(true, table.test("identifier"))
} }
#[test]
fn should_check_type() {
let mut table = SymbolTable::new();
table.add("firstNumber", _NUMBER);
assert!(table.check_type("firstNumber", _NUMBER));
}
} }