From 0a0838ac9c530eb1d23c073c0dc2f0cefde02abd Mon Sep 17 00:00:00 2001 From: mars Date: Thu, 3 Mar 2022 12:14:39 -0700 Subject: [PATCH] Initial symbol table --- Cargo.toml | 1 + src/lib.rs | 3 +- src/parse.rs | 18 +++--- src/symbols.rs | 162 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 src/symbols.rs diff --git a/Cargo.toml b/Cargo.toml index e76c448..7756446 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/src/lib.rs b/src/lib.rs index 6d1f52d..7af9e36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,8 +3,9 @@ use console::Style; -pub mod parse; +pub mod symbols; pub mod lexer; +pub mod parse; use lexer::Token; diff --git a/src/parse.rs b/src/parse.rs index db18cf6..f1fff3f 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -5,12 +5,12 @@ use crate::lexer::{Lexer, Token}; #[derive(Debug)] pub struct ParseTree<'a> { - pub declarations: Vec>, + pub defs: Vec>, } 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 } } } diff --git a/src/symbols.rs b/src/symbols.rs new file mode 100644 index 0000000..73270eb --- /dev/null +++ b/src/symbols.rs @@ -0,0 +1,162 @@ +use crate::parse; +use std::collections::HashMap; + +type SymbolMap = HashMap; + +#[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, + pub interfaces: SymbolMap, + pub functions: SymbolMap, +} + +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, + pub functions: Vec, + pub interfaces: Vec, +} + +#[derive(Clone, Debug)] +pub struct MemberDef { + pub member_name: String, + pub type_name: String, +} + +#[derive(Clone, Debug)] +pub struct IfaceDef { + pub functions: Vec, +} + +#[derive(Clone, Debug)] +pub struct FnDef { + pub mutable: bool, + pub name: String, + pub args: Vec, + pub return_type: Option, +} + +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, + 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")); + } +}