diff --git a/dev/src/idl/mod.rs b/dev/src/idl/mod.rs index 212416c..b636cbb 100644 --- a/dev/src/idl/mod.rs +++ b/dev/src/idl/mod.rs @@ -1,19 +1,30 @@ pub mod protocol; +mod parser; use std::io::Read; +use self::parser::parse; + use { logos::{Lexer, Logos}, - protocol::Protocol, }; #[derive(Logos, Debug, PartialEq, Clone)] #[logos(skip r"[ \t\n\f]+")] // Ignore this regex pattern between tokens enum Token { + #[regex("//[^\n]*\n", logos::skip)] + Ignored, + // Tokens can be literal strings, of any length. #[token("protocol")] Protocol, + #[token("enum")] + Enum, + + #[token("struct")] + Struct, + #[token("{")] LBrace, @@ -41,7 +52,7 @@ enum Token { RArrow, #[regex("[a-zA-Z_]+", |lex|{lex.slice().to_string()})] - Text(String), + Identifier(String), #[regex("[1234567890]+", |lex|{lex.slice().parse::().unwrap()})] Number(u64), @@ -66,13 +77,11 @@ pub fn build_idl(name: String) { Err(err) => println!("{:?}", err), } } - build(tokens); + + println!("{:?}", parse(tokens)); } fn build(a: Vec) { - for toke in a { - println!("{:?}", toke); - } } fn open_protocol(name: String) -> String { diff --git a/dev/src/idl/parser.rs b/dev/src/idl/parser.rs new file mode 100644 index 0000000..f060621 --- /dev/null +++ b/dev/src/idl/parser.rs @@ -0,0 +1,128 @@ +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); +#[derive(Debug, Clone, PartialEq)] +struct Decorator(String); +#[derive(Debug, Clone, PartialEq)] +enum Declaration{ + EnumDeclaration, + StructDeclaration(StructDeclaration), + ProtocolDeclaration, +} +#[derive(Debug, Clone, PartialEq)] +struct StructDeclaration { + name : String, + members : Vec, +} +#[derive(Debug, Clone, PartialEq)] +struct StructMember { + name : String, + 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); + let declaration = parse_declaration(tokens); + + declarations.push(DecoratedDeclaration(decoration, declaration)); + }, + None => break, + } + } + return declarations +} + +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"); + } + } + } + } + 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)) +} + diff --git a/sysdata/idl/log/src/protocol.aidl b/sysdata/idl/log/src/protocol.aidl index ec37b5b..cc46a32 100644 --- a/sysdata/idl/log/src/protocol.aidl +++ b/sysdata/idl/log/src/protocol.aidl @@ -1,24 +1,25 @@ -@auto_increment -enum LogLevel { - Error = 0, - Warn, - Info, - Debug, - Trace, -} - -@auto_increment -enum LogResult { - Err = 0, - Ok, -} - +// A comment +//@auto_increment +//enum LogLevel { +// Error = 0, +// Warn, +// Info, +// Debug, +// Trace, +//} +// +//@auto_increment +//enum LogResult { +// Err = 0, +// Ok, +//} +@example struct Log { log_level: LogLevel, } -@visibility(public) -protocol Log { - fn log(Log) -> LogResult; - fn flush() -> LogResult; -} \ No newline at end of file +//@visibility(public) +//protocol Log { +// fn log(Log) -> LogResult; +// fn flush() -> LogResult; +//}