Initial symbol table
This commit is contained in:
parent
dba171eb53
commit
0a0838ac9c
|
@ -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"] }
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
|
||||
use console::Style;
|
||||
|
||||
pub mod parse;
|
||||
pub mod symbols;
|
||||
pub mod lexer;
|
||||
pub mod parse;
|
||||
|
||||
use lexer::Token;
|
||||
|
||||
|
|
18
src/parse.rs
18
src/parse.rs
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue