94 lines
2.1 KiB
Rust
94 lines
2.1 KiB
Rust
use std::collections::HashMap;
|
|
use crate::tokenizer::Keyword;
|
|
use crate::tokenizer::Token;
|
|
|
|
#[derive(Debug)]
|
|
struct Symbol {
|
|
name: String,
|
|
symbol_type: Token,
|
|
kind: Keyword,
|
|
index: usize,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct SymbolTable {
|
|
count: HashMap<Keyword, usize>,
|
|
fields: HashMap<String, Symbol>,
|
|
}
|
|
|
|
pub fn get_empty_symbol_table() -> SymbolTable {
|
|
let mut count = HashMap::new();
|
|
count.insert(Keyword::Static, 0);
|
|
count.insert(Keyword::Field, 0);
|
|
count.insert(Keyword::Argument, 0);
|
|
count.insert(Keyword::Local, 0);
|
|
|
|
SymbolTable {
|
|
count: count,
|
|
fields: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
impl SymbolTable {
|
|
|
|
pub fn kind_of(&self, name: &String) -> Keyword {
|
|
match self.fields.get(name) {
|
|
Some(symbol) => symbol.kind,
|
|
None => panic!("Symbol {} does not exist", name),
|
|
}
|
|
}
|
|
|
|
pub fn index_of(&self, name: &String) -> usize {
|
|
match self.fields.get(name) {
|
|
Some(s) => s.index,
|
|
None => panic!("Symbol {} does not exist", name),
|
|
}
|
|
}
|
|
|
|
pub fn get_token(&self, name: &String) -> Token {
|
|
match self.fields.get(name) {
|
|
Some(s) => s.symbol_type.clone(),
|
|
None => panic!("Symbol {} does not exist", name),
|
|
}
|
|
}
|
|
|
|
pub fn get_count(&self, symbol_kind: Keyword) -> usize {
|
|
match self.count.get(&symbol_kind) {
|
|
Some(s) => *s,
|
|
None => 0,
|
|
}
|
|
}
|
|
|
|
pub fn has_symbol(&self, name: &String) -> bool {
|
|
self.fields.contains_key(name)
|
|
}
|
|
|
|
pub fn remove_subroutine_symbols(&mut self) {
|
|
let mut to_remove: Vec<String> = vec![];
|
|
for (key, symbol) in self.fields.iter() {
|
|
match symbol.kind {
|
|
Keyword::Argument => to_remove.push(key.to_string()),
|
|
Keyword::Local => to_remove.push(key.to_string()),
|
|
_ => (),
|
|
}
|
|
}
|
|
for key in to_remove {
|
|
self.fields.remove(&key);
|
|
}
|
|
self.count.insert(Keyword::Argument, 0);
|
|
self.count.insert(Keyword::Local, 0);
|
|
}
|
|
|
|
pub fn define_symbol(&mut self, name: String, symbol_type: Token, kind: Keyword) {
|
|
let index: usize = *self.count.get(&kind).unwrap();
|
|
let s = Symbol {
|
|
name: name.to_string(),
|
|
symbol_type: symbol_type,
|
|
kind: kind,
|
|
index: index,
|
|
};
|
|
self.count.insert(kind, index + 1);
|
|
self.fields.insert(name, s);
|
|
}
|
|
}
|