diff --git a/dev/aldi.bnf b/dev/aldi.bnf new file mode 100644 index 0000000..671a304 --- /dev/null +++ b/dev/aldi.bnf @@ -0,0 +1,25 @@ + + +declarations ::= +declaration ::= | | | + + ::= "type" ";" + +enum_decl ::= "enum" "{" "}" + | "enum" "{" "}" + + +enum_members ::= ["," ]+ [","] + +enum_member ::= "=" + + +struct_decl ::= "struct" "{" "}" + | "struct" "{" "}" + +struct_members ::= + | "," + | "," + | "," + +// TODO protocol_decl diff --git a/dev/src/idl/mod.rs b/dev/src/idl/mod.rs index 4b14ee3..fa3eba7 100644 --- a/dev/src/idl/mod.rs +++ b/dev/src/idl/mod.rs @@ -78,7 +78,7 @@ pub fn build_idl(name: String) { } } - println!("{:?}", parse(tokens)); + println!("{:#?}", parse(tokens)); } fn build(a: Vec) { diff --git a/dev/src/idl/parser.rs b/dev/src/idl/parser.rs index ccf5392..acdbb20 100644 --- a/dev/src/idl/parser.rs +++ b/dev/src/idl/parser.rs @@ -1,16 +1,15 @@ use std::{iter::Peekable, slice::Iter}; - use super::Token; #[derive(Debug, Clone, PartialEq)] -pub struct AST(Vec); -#[derive(Debug, Clone, PartialEq)] -struct DecoratedDeclaration(Option, Declaration); +pub struct AST(Vec); + #[derive(Debug, Clone, PartialEq)] struct Decorator(String); + #[derive(Debug, Clone, PartialEq)] enum Declaration{ - EnumDeclaration, + EnumDeclaration(EnumDeclaration), StructDeclaration(StructDeclaration), ProtocolDeclaration, } @@ -25,105 +24,167 @@ struct StructMember { type_name : String, } - -fn parse_decorated_declarations(tokens : &mut Peekable>) -> Vec{ - let mut declarations : Vec = Vec::new(); - loop { - match tokens.peek() { - Some(_) => { - let decoration = parse_decoration(tokens); - assert!(decoration == None, "NO DECORATIONS!!!"); - let declaration = parse_declaration(tokens); - - declarations.push(DecoratedDeclaration(decoration, declaration)); - }, - None => break, - } - } - return declarations +#[derive(Debug, Clone, PartialEq)] +struct EnumDeclaration { + name : String, + members : Vec, +} +#[derive(Debug, Clone, PartialEq)] +struct EnumMember { + name : String, + number: u64, } -fn parse_decoration(tokens : &mut Peekable>) -> Option { - match tokens.peek().unwrap() { - Token::Decorator(s) => { - tokens.next(); - Some(Decorator(s.to_string())) - }, - Token::DecoratorOption(s) => { - tokens.next(); - Some(Decorator(s.to_string())) - }, - _ => None, - } -} -fn parse_declaration(tokens : &mut Peekable>) -> Declaration { - match tokens.next().expect("Expected a statement, got end of tokens") { - Token::Enum => { - Declaration::EnumDeclaration - }, - Token::Struct => { - Declaration::StructDeclaration(parse_struct_declaration(tokens)) - }, - Token::Protocol => { - Declaration::ProtocolDeclaration - }, - _ => panic!("Expected a enumeration, struct or protocol") - } -} -fn parse_struct_declaration(tokens : &mut Peekable>) -> StructDeclaration{ - if let Token::Identifier(identifier) = tokens.next().unwrap() { - let mut members : Vec = Vec::new(); - - assert!(tokens.next().expect("expected a {{, got end of token list") == &Token::LBrace, "expected a {{ after identifier in struct declaration"); - - loop { - match tokens.peek().expect("expected }} or struct members") { - &Token::RBrace => break, - _ => { - // if we're in this branch then there MUST a struct member here - members.push(parse_struct_member(tokens)); - // is there a comma here? - // nightmare - if **(tokens.peek().unwrap()) == Token::Comma { - // consume comma - tokens.next(); - } - // if there isn't a comma nor a right brace after the struct member - else if **(tokens.peek().unwrap()) != Token::RBrace { - panic!("expected a comma to separate struct members"); - } - } - } +/// Consume's a token that's expected. If the token that's consumed is not +/// the given expected token then panic +fn consume(tokens : &mut Peekable>, token : Token) { + let a = tokens.next(); + match a { + None => panic!("Expected {:?}, Got End Of File", token), + Some(a) => if *a != token { + panic!("Expected {:?}, Got {:?}", token, *a); } - tokens.next(); // consume closing bracket - return StructDeclaration{ - name : identifier.to_string(), - members, - } - } - else { - panic!("Expected an identifier after 'struct'") - } -} - -fn parse_struct_member(tokens : &mut Peekable>) -> StructMember { - if let Token::Identifier(name) = tokens.next().unwrap(){ - assert!(tokens.next().unwrap() == &Token::Colon, "expected colon after struct member name"); - if let Token::Identifier(type_name) = tokens.next().unwrap(){ - StructMember{name: name.to_string(), type_name: type_name.to_string()} - } - else{ - panic!("Expected type name in Struct Member"); - } - } - else { - panic!("Expected identifier in Struct Member"); } } pub fn parse(tokens : Vec) -> AST{ let mut tokens_iter = tokens.iter().peekable(); - AST(parse_decorated_declarations(&mut tokens_iter)) + AST(declarations(&mut tokens_iter)) } +fn declarations(tokens : &mut Peekable>) -> Vec { + let mut decls : Vec = Vec::new(); + loop { + match declaration(tokens) { + Some(x) => decls.push(x), + None => break, + } + } + decls +} + +fn declaration(tokens : &mut Peekable>) -> Option { + match tokens.peek(){ + None => None, + Some(tok) => match tok { + Token::Enum => Some(enum_decl(tokens)), + Token::Struct => Some(struct_decl(tokens)), + _ => None, + } + } +} + +fn enum_decl(tokens : &mut Peekable>) -> Declaration { + consume(tokens, Token::Enum); + let name = identifier(tokens).expect("Expected Identifier after `enum`"); + consume(tokens, Token::LBrace); + let mut members = Vec::new(); + + match tokens.peek().expect("Unexpected EOF after LBrace") { + Token::RBrace => {}, // skip checking for enum_members if empty + _ => { + enum_members(tokens, &mut members); + }, + } + + consume(tokens, Token::RBrace); + + Declaration::EnumDeclaration(EnumDeclaration{name, members}) +} + +fn enum_members(tokens : &mut Peekable>, members: &mut Vec) { + members.push(enum_member(tokens).unwrap()); + loop { + match tokens.peek().expect("Unexpected EOF inside enum declaration") { + Token::Comma => { + consume(tokens, Token::Comma); + if let Some(member) = enum_member(tokens) { + members.push(member); + } else { + break; + } + }, + _ => {}, + } + } +} + +fn enum_member(tokens : &mut Peekable>) -> Option { + let name = identifier(tokens); + if let Some(name) = name { + consume(tokens, Token::Equal); + let number = parse_number(tokens).expect("Expected Number after `=`"); + Some(EnumMember{name, number}) + } else { + None + } +} + +fn struct_decl(tokens : &mut Peekable>) -> Declaration { + consume(tokens, Token::Struct); + let name = identifier(tokens).expect("Expected Identifier after `struct`"); + consume(tokens, Token::LBrace); + let mut members = Vec::new(); + + match tokens.peek().expect("Unexpected EOF after LBrace") { + Token::RBrace => {}, // skip checking for struct_members if empty + _ => { + struct_members(tokens, &mut members); + }, + } + + consume(tokens, Token::RBrace); + + Declaration::StructDeclaration(StructDeclaration{name, members}) +} + +fn struct_members(tokens : &mut Peekable>, members: &mut Vec) { + members.push(struct_member(tokens).unwrap()); + loop { + match tokens.peek().expect("Unexpected EOF inside struct declaration") { + Token::Comma => { + consume(tokens, Token::Comma); + if let Some(member) = struct_member(tokens) { + members.push(member); + } else { + break; + } + }, + _ => {}, + } + } +} +fn struct_member(tokens : &mut Peekable>) -> Option { + let name = identifier(tokens); + if let Some(name) = name { + consume(tokens, Token::Colon); + let type_name = identifier(tokens).expect("Expected Type after Colon"); + Some(StructMember{name, type_name}) + } else { + None + } +} +fn identifier(tokens : &mut Peekable>) -> Option { + let result = tokens.peek().map_or(None, |x| match x { + Token::Identifier(s) => { + Some(s.to_string()) + }, + _ => None + }); + + if let Some(_) = result { + tokens.next(); + } + result +} +fn parse_number(tokens : &mut Peekable>) -> Option { + let result = tokens.peek().map_or(None, |x| match x { + Token::Number(s) => Some(*s), + _ => None + }); + if let Some(_) = result { + tokens.next(); + } + result +} diff --git a/sysdata/idl/log/src/protocol.aldi b/sysdata/idl/log/src/protocol.aldi index f8ff23a..292ea16 100644 --- a/sysdata/idl/log/src/protocol.aldi +++ b/sysdata/idl/log/src/protocol.aldi @@ -1,18 +1,18 @@ // A comment //@auto_increment -//enum LogLevel { -// Error = 0, -// Warn, -// Info, -// Debug, -// Trace, -//} -// +enum LogLevel { + Error = 0, + Warn = 1, + Info = 2, + Debug = 3, + Trace = 4, +} + //@auto_increment -//enum LogResult { -// Err = 0, -// Ok, -//} +enum LogResult { + Err = 0, + Ok = 1, +} struct Log { log_level: LogLevel,