--- layout: default title: Symbol Table --- ## Design The symbol table is used to store extra data about a parsed node. A parsed node usually represents exactly one lex symbol. So its corresponding symtab entry stores the symbol's immediate value. Note, this is only for 'declarations and definitions' of a class or struct. Not a variable. A variable can be assigned a value. That value should be predefined. ```rust struct Symbol { identifer: &'static str, parent_scope: ScopeType value: V } enum ScopeType { Fn, Class, Data, Trait, Mod } struct ScopeTable { scope_type: ScopeType, child_tables: ScopeTable } // or serialised struct Symbol { identifer: &'static str, bytes: Vec, } ``` Type inference from `mut` or `const` like v and rust. What about variabes like `mut x = 1`? Should that go into the symtab? Apparently yes... So the `ReiType` are mostly scopes right? And `mut, const, static` are the actual symbol declarations. What about modifiers like `const`, `static` and `mut`?? Maybe just treat them the same for now. ## Removed Designs So here is one: ```rust // Symbols // local vars should be pushed onto the stack. Their size is known at runtime right as you push // ident : attr // Symbols also store comment or metacode info. Reidoc simply takes all hash comment lines and associates them with symbols. I guess I can also go for multiline hash comments // Remember to derive serde for all structures // ? Can change this to SymbolTable #[derive(Debug, PartialEq, Serialize, Deserialize)] pub enum SymbolType { Function, Class, Data, Variables, } /// The basic foundation for a complex program /// Can be used to "trickle up" for parse nodes /// A symbol is associated with a token (lexed) and is non trivial. E.g., not an operator or keyword. An identifier, number, float, double quoted string, single quoted string, enhanced string, document comments #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Symbol { symbol_type: SymbolType, lex_val: String, } impl Symbol { pub fn new(symbol_type: SymbolType, lex_val: String) -> Self { Self { symbol_type, lex_val, } } } type Identifier = String; #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct Namespace { elements: HashMap, } impl Namespace { pub fn new(elements: HashMap) -> Self { Self { elements } } pub fn get_symbol(&mut self, identifier: &str) -> &mut Symbol { self.elements .get_mut(identifier) .unwrap_or_else(|| panic!("Symbol doesnt exist")) } pub fn add_symbol( &mut self, identifier: &str, symbol_type: SymbolType, lex_val: &str, ) -> Result<&Symbol, &'static str> { // check if symbol already exists in the namespace match self.elements.get(identifier) { Some(_) => Err("Symbol already exists"), None => { let r = Symbol::new(symbol_type, lex_val.to_owned()); self.elements.insert(identifier.to_owned(), r); let res = self.elements.get(identifier).unwrap(); Ok(res) } } } } impl Default for Namespace { fn default() -> Self { Self { elements: Default::default(), } } } /// Symbol table is filled in by the lexer automatically /// As callbacks for each token pub struct SymbolTable { // a symbol must be uniquely identified within its scope namespaces: HashMap, } impl SymbolTable { pub fn new(namespaces: HashMap) -> Self { Self { namespaces } } // I think parser or lexer needs to add the namespaces properly. Or just have a generic enum SymbolTable. Then gets serialised as usual pub fn add_namespace(&mut self, name: &str) { match self .namespaces .insert(name.to_owned(), Namespace::default()) { Some(ns) => panic!( "Namespace {} already exists, are you sure it was at the right level?", name ), None => {} } } pub fn insert_value( &mut self, namespace: &str, identifier: &str, symbol_type: SymbolType, lex_val: &str, ) -> &Symbol { match self.namespaces.get_mut(namespace) { Some(ns) => match ns.add_symbol(identifier, symbol_type, lex_val) { Ok(symbol) => symbol, Err(msg) => panic!("{} in namespace {}", msg, namespace), }, None => panic!("Namespace doesnt exist, did you make it first?"), } } } impl Default for SymbolTable { fn default() -> Self { Self { namespaces: Default::default(), } } } lazy_static! { static ref SYMTAB: Mutex = Mutex::new(SymbolTable::default()); } ```