Initial symbol table
This commit is contained in:
parent
dba171eb53
commit
0a0838ac9c
|
@ -8,3 +8,4 @@ license = "GPL-3.0-or-later"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
console = "0.15.0"
|
console = "0.15.0"
|
||||||
logos = "0.12.0"
|
logos = "0.12.0"
|
||||||
|
strum = { version="0.24", features=["derive"] }
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
use console::Style;
|
use console::Style;
|
||||||
|
|
||||||
pub mod parse;
|
pub mod symbols;
|
||||||
pub mod lexer;
|
pub mod lexer;
|
||||||
|
pub mod parse;
|
||||||
|
|
||||||
use lexer::Token;
|
use lexer::Token;
|
||||||
|
|
||||||
|
|
18
src/parse.rs
18
src/parse.rs
|
@ -5,12 +5,12 @@ use crate::lexer::{Lexer, Token};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseTree<'a> {
|
pub struct ParseTree<'a> {
|
||||||
pub declarations: Vec<Definition<'a>>,
|
pub defs: Vec<Definition<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParseTree<'a> {
|
impl<'a> ParseTree<'a> {
|
||||||
pub fn build(lexer: &mut Lexer<'a>) -> Self {
|
pub fn build(lexer: &mut Lexer<'a>) -> Self {
|
||||||
let mut declarations = Vec::new();
|
let mut defs = Vec::new();
|
||||||
let mut associated_struct = None;
|
let mut associated_struct = None;
|
||||||
while let Some(tok) = lexer.next() {
|
while let Some(tok) = lexer.next() {
|
||||||
if let Some(struct_name) = associated_struct {
|
if let Some(struct_name) = associated_struct {
|
||||||
|
@ -22,7 +22,7 @@ impl<'a> ParseTree<'a> {
|
||||||
lexer.panic_message("Expected fn or mut");
|
lexer.panic_message("Expected fn or mut");
|
||||||
}
|
}
|
||||||
|
|
||||||
declarations.push(Definition::build_function(
|
defs.push(Definition::build_function(
|
||||||
mutable,
|
mutable,
|
||||||
Some(struct_name),
|
Some(struct_name),
|
||||||
lexer,
|
lexer,
|
||||||
|
@ -31,19 +31,17 @@ impl<'a> ParseTree<'a> {
|
||||||
associated_struct = None;
|
associated_struct = None;
|
||||||
} else {
|
} else {
|
||||||
match tok {
|
match tok {
|
||||||
Token::Struct => declarations.push(Definition::build_structure(lexer)),
|
Token::Struct => defs.push(Definition::build_structure(lexer)),
|
||||||
Token::Function => {
|
Token::Function => defs.push(Definition::build_function(false, None, lexer)),
|
||||||
declarations.push(Definition::build_function(false, None, lexer))
|
Token::Interface => defs.push(Definition::build_interface(lexer)),
|
||||||
}
|
Token::Impl => defs.push(Definition::build_impl(lexer)),
|
||||||
Token::Interface => declarations.push(Definition::build_interface(lexer)),
|
|
||||||
Token::Impl => declarations.push(Definition::build_impl(lexer)),
|
|
||||||
Token::Identifier => associated_struct = Some(lexer.slice()),
|
Token::Identifier => associated_struct = Some(lexer.slice()),
|
||||||
_ => lexer.panic_message("Expected function, struct, impl block, or interface"),
|
_ => 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