N2T/jack_compiler/src/symbol_table.rs

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);
}
}