pub mod parsed_statement; pub mod parsed_type_modifier; mod parser_operators; #[cfg(test)] mod parser_tests; use super::lexer::lex_tokens::{LexToken, TokenType}; use crate::logger::messages::Message; use crate::logger::messages::Message::UnexpectedToken; use crate::modifiers::{FieldModifier, TypeModifier}; use crate::parsing::parser::parsed_type_modifier::ParsedTypeModifier; use crate::parsing::parser::parser_operators::{BinaryOperator, PreOperator}; use crate::prim_type::PrimitiveType; use crate::span::Span; use enumflags2::BitFlags; use parsed_statement::ParsedStatement; struct ParseReader<'a> { tokens: &'a Vec, position: usize, } impl<'a> ParseReader<'a> { pub fn peek(&mut self) -> &LexToken { let t = self.tokens.get(self.position); match t { None => self.tokens.last().unwrap(), Some(v) => { if v.token_type == TokenType::WhiteSpace { self.peek_ahead(1) } else { v } } } } fn peek_ahead(&mut self, index: usize) -> &LexToken { let t = self.tokens.get(self.position + index); match t { None => self.tokens.last().unwrap(), Some(v) => { if v.token_type == TokenType::WhiteSpace { self.peek_ahead(index + 1) } else { v } } } } pub fn next(&mut self) -> &LexToken { let t = self.tokens.get(self.position); self.position += 1; match t { None => self.tokens.last().unwrap(), Some(v) => { if v.token_type == TokenType::WhiteSpace { self.next() } else { v } } } } pub fn consume( &mut self, expected: TokenType, log: &mut dyn FnMut(Message, Span), ) -> &LexToken { let n = self.next(); if n.token_type != expected { log( Message::UnexpectedToken { expected: vec![expected], found: n.token_type.clone(), }, n.span, ); } n } pub fn create_inner(&self) -> ParseReader<'a> { ParseReader { tokens: self.tokens, position: self.position, } } pub fn set_from_inner(&mut self, inner: &ParseReader) { self.position = inner.position; } } pub fn parse(tokens: Vec, log: &mut dyn FnMut(Message, Span)) -> Box { assert_ne!(tokens.len(), 0); let mut reader = ParseReader { tokens: &tokens, position: 0, }; parse_script(&mut reader, log) } fn parse_identifier( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), can_fail: bool, ) -> Option { let identifier_token = reader.peek(); let s: String; match &identifier_token.token_type { TokenType::Identifier(i) => { s = i.to_string(); reader.next(); } _ => { if !can_fail { log( Message::UnexpectedToken { found: identifier_token.token_type.clone(), expected: vec![TokenType::Identifier(String::new())], }, identifier_token.span, ); } return None; } } Some(s) } fn parse_script( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Box { let mut vec: Vec = Vec::new(); loop { let n = reader.peek(); let token_type = n.token_type.clone(); let span = n.span; match token_type { TokenType::NamespaceKeyword => { vec.push(*parse_namespace(reader, log)); } TokenType::InterfaceKeyword => vec.push(*parse_interface(reader, log).unwrap()), TokenType::EndOfFile => break, TokenType::CloseCurlyBracket => break, _ => { if let Some(s) = parse_interface(reader, log) { vec.push(*s); } else if let Some(s) = parse_var(reader, log) { vec.push(*s); } else { log( UnexpectedToken { expected: vec![TokenType::NamespaceKeyword], found: token_type, }, span, ); reader.next(); } } } } Box::new(ParsedStatement::Script { statements: vec }) } fn parse_namespace( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Box { reader.next(); // Consume namespace let identifier = parse_identifier(reader, log, false); if identifier.is_none() { return Box::new(ParsedStatement::Invalid); } reader.consume(TokenType::OpenCurlyBracket, log); let script = parse_script(reader, log); reader.consume(TokenType::CloseCurlyBracket, log); Box::new(ParsedStatement::Namespace { identifier: identifier.unwrap(), script, }) } fn parse_interface( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { let mut type_mod: BitFlags = BitFlags::empty(); let identifier: Option; let mut has_interface_keyword = false; let mut reader = outer_reader.create_inner(); loop { match &reader.next().token_type { TokenType::ExternalKeyword => type_mod |= TypeModifier::External, TokenType::SharedKeyword => type_mod |= TypeModifier::Shared, TokenType::Identifier(s) => { identifier = Some(s.clone()); break; } TokenType::InterfaceKeyword => { has_interface_keyword = true; } _ => { return None; } }; } if !has_interface_keyword { return None; } let mut statements: Vec = Vec::new(); let mut inherits: Vec = Vec::new(); loop { let t = reader.peek(); match t.token_type { TokenType::Semicolon => { reader.next(); if identifier.is_none() { return Some(Box::new(ParsedStatement::Invalid)); } return Some(Box::new(ParsedStatement::Interface { type_mod, identifier: identifier.unwrap(), inherits, statements, })); } TokenType::Colon | TokenType::OpenCurlyBracket => break, TokenType::EndOfFile => { log( Message::UnexpectedToken { found: t.token_type.clone(), expected: vec![ TokenType::Semicolon, TokenType::Colon, TokenType::OpenCurlyBracket, ], }, t.span, ); return Some(Box::new(ParsedStatement::Invalid)); } _ => { log( Message::UnexpectedToken { found: t.token_type.clone(), expected: vec![ TokenType::Semicolon, TokenType::Colon, TokenType::OpenCurlyBracket, ], }, t.span, ); } } } if reader.peek().token_type == TokenType::Colon { reader.next(); loop { let inherit_identifier = parse_identifier(&mut reader, log, false); if inherit_identifier.is_none() { continue; } inherits.push(inherit_identifier.unwrap()); if reader.peek().token_type != TokenType::Comma { break; } reader.next(); } } reader.consume(TokenType::OpenCurlyBracket, log); // TODO: parse interfacemethod loop { if reader.peek().token_type == TokenType::CloseCurlyBracket { break; } let prop = parse_virtprop(&mut reader, log); if prop.is_none() { break; } statements.push(*prop.unwrap()); } reader.consume(TokenType::CloseCurlyBracket, log); outer_reader.set_from_inner(&reader); if identifier.is_none() { return Some(Box::new(ParsedStatement::Invalid)); } Some(Box::new(ParsedStatement::Interface { type_mod, identifier: identifier.unwrap(), inherits, statements, })) } fn parse_interface_method( _reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_typedef( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_import( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_enum( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_mixin( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_class( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_funcdef( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_func( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_virtprop( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { let mut reader = outer_reader.create_inner(); let mut field_mod: BitFlags = BitFlags::empty(); let property_type: Option>; loop { let t = reader.peek(); match t.token_type { TokenType::PrivateKeyword => { field_mod |= FieldModifier::Private; reader.next(); } TokenType::ProtectedKeyword => { field_mod |= FieldModifier::Protected; reader.next(); } _ => { property_type = parse_type(&mut reader, log); property_type.as_ref()?; break; } } } let mut is_handle = false; if reader.peek().token_type == TokenType::AtSymbol { reader.next(); is_handle = true; } let identifier = parse_identifier(&mut reader, log, false); identifier.as_ref()?; let next = reader.next(); if next.token_type != TokenType::OpenCurlyBracket { return None; } let mut has_get = false; let mut is_get_const = false; let mut get_statement: Option> = None; let mut has_set = false; let mut is_set_const = false; let mut set_statement: Option> = None; let start_span = next.span; loop { let next = reader.peek(); match next.token_type { TokenType::GetKeyword => { reader.next(); has_get = true; let mut peek = reader.peek(); if peek.token_type == TokenType::ConstKeyword { reader.next(); is_get_const = true; peek = reader.peek(); } if peek.token_type != TokenType::Semicolon { get_statement = parse_statblock(&mut reader, log); } else { reader.next(); } } TokenType::SetKeyword => { reader.next(); has_set = true; let mut peek = reader.peek(); if peek.token_type == TokenType::ConstKeyword { reader.next(); is_set_const = true; peek = reader.peek(); } if peek.token_type != TokenType::Semicolon { set_statement = parse_statblock(&mut reader, log); } else { reader.next(); } } _ => break, } } let next = reader.next(); if next.token_type != TokenType::CloseCurlyBracket { return None; } if !has_get && !has_set { log( Message::EmptyProperty, Span { start: start_span.start, end: next.span.end, }, ) } outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::VirtProp { field_mod, property_type: property_type.unwrap(), identifier: identifier.unwrap(), is_handle, has_get, is_get_const, get_statement, has_set, is_set_const, set_statement, })) } fn parse_paramlist( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_funcattr( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_statblock( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { // FIXME if reader.peek().token_type != TokenType::OpenCurlyBracket { return None; } None } fn parse_var( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // var ::= ['private'|'protected'] type identifier let mut reader = outer_reader.create_inner(); let mut field_mod: BitFlags = BitFlags::empty(); let property_type: Option>; loop { let t = reader.peek(); match t.token_type { TokenType::PrivateKeyword => { field_mod |= FieldModifier::Private; reader.next(); } TokenType::ProtectedKeyword => { field_mod |= FieldModifier::Protected; reader.next(); } _ => { property_type = parse_type(&mut reader, log); property_type.as_ref()?; break; } } } if property_type.is_none() { return None; } let identifier = parse_identifier(&mut reader, log, false); identifier.as_ref()?; let mut assignment: Option> = None; // FIXME: Implement arglist // [( '=' (initlist | expr)) | arglist] if reader.peek().token_type == TokenType::Equals { // Eat the equals token. reader.next(); // micro-optimization so we don't go into the initlist if not needed. if reader.peek().token_type == TokenType::OpenCurlyBracket { if let Some(s) = parse_initlist(&mut reader, log) { assignment = Some(s); } } if assignment.is_none() { assignment = parse_expr(&mut reader, log); } } // {',' identifier [( '=' (initlist | expr)) | arglist]} ';'; outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::Var { modifier: field_mod, var_type: property_type.unwrap(), identifier: identifier.unwrap(), assignment, })) } fn parse_statement( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_switch( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_case( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_try( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_dowhile( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_while( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_for( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_if( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_break( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_continue( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_exprstat( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_return( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_ternary( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_expr( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // expr ::= exprterm {(mathop | compop | logicop | bitop) exprterm}; let expr_term = parse_exprterm(reader, log); expr_term.as_ref()?; let mut binary_operand = parse_mathop(reader, log); if binary_operand.is_none() { binary_operand = parse_compop(reader, log); } if binary_operand.is_none() { binary_operand = parse_logicop(reader, log); } if binary_operand.is_none() { binary_operand = parse_bitop(reader, log); } if binary_operand.is_some() { let expr_term2 = parse_exprterm(reader, log); // FIXME: deal with empty expr_term2 return Some(Box::new(ParsedStatement::BinaryExpr { left: expr_term.unwrap(), operator: binary_operand.unwrap(), right: expr_term2.unwrap(), })); } expr_term } fn parse_exprterm( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { let mut reader = outer_reader.create_inner(); // exprterm ::= ([type '='] initlist) | ({exprpreop} exprvalue {exprpostop}); let expr_type = parse_type(&mut reader, log); if expr_type.is_some() { outer_reader.consume(TokenType::Equals, log); } let mut init_list = None; if reader.peek().token_type == TokenType::OpenCurlyBracket { init_list = parse_initlist(&mut reader, log); } if let Some(initlist) = init_list { outer_reader.set_from_inner(&reader); return Some(Box::new(ParsedStatement::ExprTermInitList { statement_type: expr_type, initlist, })); } // Reset to initial here. reader = outer_reader.create_inner(); let mut expr_pre_op = Vec::new(); while let Some(s) = parse_exprpreop(&mut reader, log) { expr_pre_op.push(s); } let expr_value = parse_exprvalue(&mut reader, log); expr_value.as_ref()?; let mut real_value = expr_value.unwrap(); let real_value = parse_exprpostop(&mut reader, log, real_value); outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::ExprTerm { pre_op: expr_pre_op, exp_value: real_value, })) } fn parse_exprpostop( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), base: Box, ) -> Box { // exprpostop ::= ('.' (funccall | identifier)) | ('[' [identifier ':'] assign {',' [identifier ':' assign} ']') | arglist | '++' | '--'; // FIXME: This needs to be implemented. // ('.' (funccall | identifier)) if reader.peek().token_type == TokenType::Dot { reader.next(); } // ('[' [identifier ':'] assign {',' [identifier ':' assign} ']') // arglist // '++' // '--' base } fn parse_exprvalue( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // exprvalue ::= 'void' | constructcall | funccall | varaccess | cast | literal | '(' assign ')' | lambda; if outer_reader.peek().token_type == TokenType::VoidKeyword { outer_reader.next(); return Some(Box::new(ParsedStatement::ExprVoidValue {})); } let mut reader = outer_reader.create_inner(); if let Some(s) = parse_constructcall(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } if let Some(s) = parse_funccall(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } if let Some(s) = parse_varaccess(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } if let Some(s) = parse_cast(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } if let Some(s) = parse_literal(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } if reader.peek().token_type == TokenType::OpenBracket { reader.next(); let inner = parse_assign(&mut reader, log); // FIXME: deal with None value reader.consume(TokenType::CloseBracket, log); outer_reader.set_from_inner(&reader); return inner; } if let Some(s) = parse_lambda(&mut reader, log) { outer_reader.set_from_inner(&reader); return Some(s); } None } fn parse_lambda( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_typemod( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_literal( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { let value = match &reader.peek().token_type { TokenType::IntegerLiteral(v) => Some(Box::new(ParsedStatement::IntegerLiteral(*v))), TokenType::FloatLiteral(v) => Some(Box::new(ParsedStatement::FloatLiteral(*v))), TokenType::TrueKeyword => Some(Box::new(ParsedStatement::BoolLiteral(true))), TokenType::FalseKeyword => Some(Box::new(ParsedStatement::BoolLiteral(false))), // FIXME: String copy, too slow. TokenType::StringLiteral(v) => { Some(Box::new(ParsedStatement::StringLiteral(v.to_string()))) } _ => None, }; if value.is_some() { reader.next(); } value } fn parse_cast( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // cast ::= 'cast' '<' type '>' '(' assign ')'; if reader.peek().token_type != TokenType::CastKeyword { return None; } reader.next(); reader.consume(TokenType::LessThan, log); let cast_type = parse_type(reader, log); // FIXME: deal with no cast type reader.consume(TokenType::GreaterThan, log); reader.consume(TokenType::OpenBracket, log); let assign = parse_assign(reader, log); // FIXME: deal with no assign reader.consume(TokenType::CloseBracket, log); Some(Box::new(ParsedStatement::Cast { cast_type: cast_type.unwrap(), assign: assign.unwrap(), })) } fn parse_varaccess( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // scope identifier let mut reader = outer_reader.create_inner(); let scope = parse_scope(&mut reader, log); let identifier = parse_identifier(&mut reader, log, true); identifier.as_ref()?; outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::VarAccess { scope, identifier: identifier.unwrap(), })) } fn parse_constructcall( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // type arglist let mut reader = outer_reader.create_inner(); let construct_type = parse_type(&mut reader, log); construct_type.as_ref()?; let arg_list = parse_arglist(&mut reader, log); // FIXME: deal with None value for arg list outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::ConstructCall { statement_type: construct_type, arglist: arg_list.unwrap(), })) } fn parse_funccall( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { // scope identifier arglist let mut reader = outer_reader.create_inner(); let scope = parse_scope(&mut reader, log); let identifier = parse_identifier(&mut reader, log, true); identifier.as_ref()?; let arg_list = parse_arglist(&mut reader, log); arg_list.as_ref()?; outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::FuncCall { scope, identifier: identifier.unwrap(), arglist: arg_list.unwrap(), })) } fn parse_arglist( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_exprpreop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // exprpreop ::= '-' | '+' | '!' | '++' | '--' | '~' | '@'; let op = match reader.peek().token_type { TokenType::Minus => Some(PreOperator::Negative), TokenType::Plus => Some(PreOperator::Identity), TokenType::ExclamationMark => Some(PreOperator::Negation), TokenType::PlusPlus => Some(PreOperator::Increment), TokenType::MinusMinus => Some(PreOperator::Decrement), TokenType::Tilde => Some(PreOperator::Complement), TokenType::AtSymbol => Some(PreOperator::HandleOf), _ => None, }; if op.is_some() { reader.next(); } op } fn parse_initlist( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_assign( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_type( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { let f = reader.peek(); let mut is_const = false; if f.token_type == TokenType::ConstKeyword { reader.next(); is_const = true; } let scope = parse_scope(reader, log); let datatype = parse_datatype(reader, log); datatype.as_ref()?; // TODO: Generics let mut modifiers: Vec = Vec::new(); loop { let n = reader.peek(); match n.token_type { TokenType::OpenBlockBracket => { reader.next(); reader.consume(TokenType::CloseBlockBracket, log); modifiers.push(ParsedTypeModifier::Array); } TokenType::AtSymbol => { reader.next(); if reader.peek().token_type == TokenType::ConstKeyword { reader.next(); modifiers.push(ParsedTypeModifier::ConstHandle); } else { modifiers.push(ParsedTypeModifier::Handle); } } _ => break, } } Some(Box::new(ParsedStatement::Type { is_const, scope, datatype: datatype.unwrap(), modifiers, })) } fn parse_scope( outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { // scope ::= ['::'] {identifier '::'} [identifier ['<' type {',' type} '>'] '::'] let mut reader = outer_reader.create_inner(); let is_global = reader.peek().token_type == TokenType::ColonColon; if is_global { reader.next(); } let mut scope: Vec = Vec::new(); loop { let n = reader.peek(); if let TokenType::Identifier(s) = &n.token_type { let identifier = s.to_string(); if reader.peek().token_type == TokenType::ColonColon { reader.next(); reader.next(); scope.push(identifier); } else { break; } } else { break; } } // TODO: generics if !is_global && scope.is_empty() { None } else { outer_reader.set_from_inner(&reader); Some(Box::new(ParsedStatement::Scope { is_global, scope, generic_types: None, })) } } fn parse_datatype( reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { if let Some(identifier) = parse_identifier(reader, log, true) { return Some(Box::new(ParsedStatement::DataTypeIdentifier { identifier })); } let key = reader.peek(); let res = match &key.token_type { TokenType::AutoKeyword => Some(Box::new(ParsedStatement::DataTypeAuto {})), TokenType::VoidKeyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Void, })), TokenType::Int8Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Int8, })), TokenType::Int16Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Int16, })), TokenType::Int32Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Int32, })), TokenType::Int64Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Int64, })), TokenType::Uint8Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::UInt8, })), TokenType::Uint16Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::UInt16, })), TokenType::Uint32Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::UInt32, })), TokenType::Uint64Keyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::UInt64, })), TokenType::FloatKeyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Float, })), TokenType::DoubleKeyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Double, })), TokenType::BoolKeyword => Some(Box::new(ParsedStatement::DataTypePrimType { prim_type: PrimitiveType::Bool, })), _ => None, }; if res.is_some() { reader.next(); } res } fn parse_primtype( _outer_reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option> { unimplemented!(); } fn parse_bitop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // bitop ::= '&' | '|' | '^' | '<<' | '>>' | '>>>'; let operand = match reader.peek().token_type { TokenType::Ampersand => Some(BinaryOperator::BitwiseAnd), TokenType::VerticalLine => Some(BinaryOperator::BitwiseOr), TokenType::Roof => Some(BinaryOperator::BitwiseXor), TokenType::LeftLeft => Some(BinaryOperator::LeftShift), TokenType::RightRight => Some(BinaryOperator::RightShift), TokenType::RightRightRight => Some(BinaryOperator::ArithmeticRightShift), _ => None, }; if operand.is_some() { reader.next(); } operand } fn parse_mathop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // mathop := '+' | '-' | '*' | '/' | '%' | '**'; let operand = match reader.peek().token_type { TokenType::Plus => Some(BinaryOperator::Addition), TokenType::Minus => Some(BinaryOperator::Subtraction), TokenType::Star => Some(BinaryOperator::Multiplication), TokenType::Slash => Some(BinaryOperator::Division), TokenType::Percent => Some(BinaryOperator::Modulo), TokenType::StarStar => Some(BinaryOperator::Exponentiation), _ => None, }; if operand.is_some() { reader.next(); } operand } fn parse_compop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // compop ::= '==' | '!=' | '<' | '<=' | '>' | '>=' | 'is' | '!is'; let operand = match reader.peek().token_type { TokenType::EqualsEquals => Some(BinaryOperator::Equality), TokenType::NotEquals => Some(BinaryOperator::Inequality), TokenType::LessThan => Some(BinaryOperator::LessThan), TokenType::LessThanEquals => Some(BinaryOperator::LessThanEquals), TokenType::GreaterThan => Some(BinaryOperator::GreaterThan), TokenType::GreaterThanEquals => Some(BinaryOperator::GreaterThanEquals), TokenType::IsKeyword => Some(BinaryOperator::IdentityEquality), TokenType::NotIsKeyword => Some(BinaryOperator::IdentityInequality), _ => None, }; if operand.is_some() { reader.next(); } operand } fn parse_logicop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // logicop ::= '&&' | '||' | '^^' | 'and' | 'or' | 'xor'; let operand = match reader.peek().token_type { TokenType::AmpersandAmpersand => Some(BinaryOperator::And), TokenType::LineLine => Some(BinaryOperator::Or), TokenType::RoofRoof => Some(BinaryOperator::Xor), TokenType::AndKeyword => Some(BinaryOperator::And), TokenType::OrKeyword => Some(BinaryOperator::Or), TokenType::XorKeyword => Some(BinaryOperator::Xor), _ => None, }; if operand.is_some() { reader.next(); } operand } fn parse_assignop( reader: &mut ParseReader, _log: &mut dyn FnMut(Message, Span), ) -> Option { // assignop ::= '=' | '+=' | '-=' | '*=' | '/=' | '|=' | '&=' | '^=' | '%=' | '**=' | '<<=' | '>>=' | '>>>='; let operand = match reader.peek().token_type { TokenType::Equals => Some(BinaryOperator::Assignment), TokenType::PlusEquals => Some(BinaryOperator::AssignmentAddition), TokenType::MinusEquals => Some(BinaryOperator::AssignmentSubtraction), TokenType::StarEquals => Some(BinaryOperator::AssignmentMultiplication), TokenType::PercentEquals => Some(BinaryOperator::AssignmentModulo), TokenType::StarStarEquals => Some(BinaryOperator::AssignmentExponentiation), TokenType::SlashEquals => Some(BinaryOperator::AssignmentDivision), TokenType::LineEquals => Some(BinaryOperator::AssignmentBitwiseOr), TokenType::AmpersandEquals => Some(BinaryOperator::AssignmentBitwiseAnd), TokenType::RoofEquals => Some(BinaryOperator::AssignmentBitwiseXor), TokenType::LeftLeftEquals => Some(BinaryOperator::AssignmentLeftShift), TokenType::RightRightEquals => Some(BinaryOperator::AssignmentRightShift), TokenType::RightRightRightEquals => Some(BinaryOperator::AssignmentArithmeticRightShift), _ => None, }; if operand.is_some() { reader.next(); } operand }