Initial symbol table

This commit is contained in:
mars 2022-03-03 12:14:39 -07:00
parent dba171eb53
commit 0a0838ac9c
4 changed files with 173 additions and 11 deletions

View File

@ -8,3 +8,4 @@ license = "GPL-3.0-or-later"
[dependencies]
console = "0.15.0"
logos = "0.12.0"
strum = { version="0.24", features=["derive"] }

View File

@ -3,8 +3,9 @@
use console::Style;
pub mod parse;
pub mod symbols;
pub mod lexer;
pub mod parse;
use lexer::Token;

View File

@ -5,12 +5,12 @@ use crate::lexer::{Lexer, Token};
#[derive(Debug)]
pub struct ParseTree<'a> {
pub declarations: Vec<Definition<'a>>,
pub defs: Vec<Definition<'a>>,
}
impl<'a> ParseTree<'a> {
pub fn build(lexer: &mut Lexer<'a>) -> Self {
let mut declarations = Vec::new();
let mut defs = Vec::new();
let mut associated_struct = None;
while let Some(tok) = lexer.next() {
if let Some(struct_name) = associated_struct {
@ -22,7 +22,7 @@ impl<'a> ParseTree<'a> {
lexer.panic_message("Expected fn or mut");
}
declarations.push(Definition::build_function(
defs.push(Definition::build_function(
mutable,
Some(struct_name),
lexer,
@ -31,19 +31,17 @@ impl<'a> ParseTree<'a> {
associated_struct = None;
} else {
match tok {
Token::Struct => declarations.push(Definition::build_structure(lexer)),
Token::Function => {
declarations.push(Definition::build_function(false, None, lexer))
}
Token::Interface => declarations.push(Definition::build_interface(lexer)),
Token::Impl => declarations.push(Definition::build_impl(lexer)),
Token::Struct => defs.push(Definition::build_structure(lexer)),
Token::Function => defs.push(Definition::build_function(false, None, lexer)),
Token::Interface => defs.push(Definition::build_interface(lexer)),
Token::Impl => defs.push(Definition::build_impl(lexer)),
Token::Identifier => associated_struct = Some(lexer.slice()),
_ => lexer.panic_message("Expected function, struct, impl block, or interface"),
}
}
}
Self { declarations }
Self { defs }
}
}

162
src/symbols.rs Normal file
View File

@ -0,0 +1,162 @@
use crate::parse;
use std::collections::HashMap;
type SymbolMap<T> = HashMap<String, T>;
#[rustfmt::skip]
#[derive(strum::Display, strum::EnumString)]
pub enum PrimitiveType {
#[strum(serialize="i64")] I64,
#[strum(serialize="u64")] U64,
#[strum(serialize="i32")] I32,
#[strum(serialize="u32")] U32,
#[strum(serialize="i16")] I16,
#[strum(serialize="u16")] U16,
#[strum(serialize="i8")] I8,
#[strum(serialize="u8")] U8,
#[strum(serialize="f64")] F64,
#[strum(serialize="f32")] F32,
#[strum(serialize="string")] String,
#[strum(serialize="bool")] Bool,
}
#[derive(Clone, Debug)]
pub struct SymbolTable {
pub structures: SymbolMap<StructDef>,
pub interfaces: SymbolMap<IfaceDef>,
pub functions: SymbolMap<FnDef>,
}
impl SymbolTable {
pub fn from_parse_tree<'a>(pt: &parse::ParseTree<'a>) -> Self {
let mut structures = SymbolMap::new();
for def in pt.defs.iter() {
if let parse::Definition::Struct { name, members } = def {
structures.insert(
name.to_string(),
StructDef {
members: members
.iter()
.map(|member| MemberDef {
member_name: member.name.to_string(),
type_name: member.type_name.to_string(),
})
.collect(),
interfaces: Vec::new(),
functions: Vec::new(),
},
);
}
}
let mut interfaces = SymbolMap::new();
for def in pt.defs.iter() {
if let parse::Definition::Interface { name, functions } = def {
interfaces.insert(
name.to_string(),
IfaceDef {
functions: functions.iter().map(|f| f.into()).collect(),
},
);
}
}
let mut functions = SymbolMap::new();
for def in pt.defs.iter() {
if let parse::Definition::Function {
associated_struct,
implementation,
} = def
{
let def: FnDef = (&implementation.def).into();
if let Some(associated_struct) = associated_struct {
structures
.get_mut(&associated_struct.to_string())
.unwrap()
.functions
.push(def);
} else {
functions.insert(def.name.to_owned(), def);
}
}
}
Self {
structures,
interfaces,
functions,
}
}
}
#[derive(Clone, Debug)]
pub struct StructDef {
pub members: Vec<MemberDef>,
pub functions: Vec<FnDef>,
pub interfaces: Vec<String>,
}
#[derive(Clone, Debug)]
pub struct MemberDef {
pub member_name: String,
pub type_name: String,
}
#[derive(Clone, Debug)]
pub struct IfaceDef {
pub functions: Vec<FnDef>,
}
#[derive(Clone, Debug)]
pub struct FnDef {
pub mutable: bool,
pub name: String,
pub args: Vec<FnArg>,
pub return_type: Option<String>,
}
impl<'a> From<&parse::FnDef<'a>> for FnDef {
fn from(def: &parse::FnDef<'a>) -> Self {
Self {
mutable: def.mutable,
name: def.name.to_string(),
args: def
.signature
.args
.iter()
.map(|arg| FnArg {
arg_name: arg.name.map(|n| n.to_string()),
type_name: arg.type_name.to_string(),
})
.collect(),
return_type: def.signature.return_type.map(|t| t.to_string()),
}
}
}
#[derive(Clone, Debug)]
pub struct FnArg {
pub arg_name: Option<String>,
pub type_name: String,
}
#[cfg(test)]
mod tests {
use super::*;
fn from_source(source: &str) -> SymbolTable {
let mut lex = crate::lexer::Lexer::new(source);
let pt = parse::ParseTree::build(&mut lex);
let symtab = SymbolTable::from_parse_tree(&pt);
println!("{:#?}", symtab);
symtab
}
#[test]
fn from_clock() {
from_source(include_str!("test/clock.fae"));
}
}