Loads more parsing work

This commit is contained in:
Deukhoofd 2022-04-03 15:25:26 +02:00
parent 75f8720c54
commit 2bc3bee344
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
12 changed files with 571 additions and 108 deletions

View File

@ -2,9 +2,18 @@
name = "seraph_script" name = "seraph_script"
version = "0.1.0" version = "0.1.0"
authors = ["Deukhoofd <Deukhoofd@gmail.com>"] authors = ["Deukhoofd <Deukhoofd@gmail.com>"]
edition = "2018" edition = "2021"
[dependencies] [dependencies]
itertools = "0.10.0" itertools = "0.10.0"
enumflags2 = "0.7.1" enumflags2 = "0.7.1"
backtrace = "0.3.63" backtrace = "0.3.63"
[profile.release]
lto = true
codegen-units = 1
debug = true
opt-level = 3
[profile.dev]
opt-level = 1

View File

@ -59,7 +59,7 @@ exprvalue ::= 'void' | constructcall | funccall | varaccess | cast | l
exprpostop ::= ('.' (funccall | identifier)) | ('[' [ identifier ':'] assign {',' [ identifier ':' assign } ']' ) | arglist | '++' | '--'; exprpostop ::= ('.' (funccall | identifier)) | ('[' [ identifier ':'] assign {',' [ identifier ':' assign } ']' ) | arglist | '++' | '--';
exprterm ::= ([type '='] initlist) | ({exprpreop} exprvalue {exprpostop}); exprterm ::= ([type '='] initlist) | ({exprpreop} exprvalue {exprpostop});
expr ::= exprterm {(mathop | compop | logicop | bitop) exprterm}; expr ::= exprterm {(mathop | compop | logicop | bitop) exprterm};
ternary ::= expr ['?' assign : assign]; ternary ::= expr ['?' assign ':' assign];
return ::= 'return' [assign] ';'; return ::= 'return' [assign] ';';
exprstat ::= assign ';'; exprstat ::= assign ';';

View File

@ -2,7 +2,6 @@
#![feature(exclusive_range_pattern)] #![feature(exclusive_range_pattern)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(fn_traits)] #![feature(fn_traits)]
#![feature(macro_attributes_in_derive_output)]
#![feature(iter_advance_by)] #![feature(iter_advance_by)]
#![feature(backtrace)] #![feature(backtrace)]

View File

@ -13,6 +13,7 @@ pub enum Message {
expected: Vec<TokenType>, expected: Vec<TokenType>,
}, },
EmptyProperty, EmptyProperty,
EmptyIndex,
} }
impl Message { impl Message {
@ -35,6 +36,7 @@ impl Message {
) )
} }
Message::EmptyProperty => "Property encountered without a getter or setter".to_string(), Message::EmptyProperty => "Property encountered without a getter or setter".to_string(),
Message::EmptyIndex => "Index operator had an empty index".to_string(),
} }
} }
} }

View File

@ -20,6 +20,7 @@ pub enum TokenType {
ColonColon, ColonColon,
Comma, Comma,
Dot, Dot,
QuestionMark,
OpenBracket, OpenBracket,
CloseBracket, CloseBracket,
OpenCurlyBracket, OpenCurlyBracket,

View File

@ -426,7 +426,6 @@ pub fn lex(s: &str, log: &mut dyn FnMut(Message, Span)) -> Vec<LexToken> {
add_token(TT::ExclamationMark, start_pos, chars.real_position); add_token(TT::ExclamationMark, start_pos, chars.real_position);
} }
} }
'~' => lex_and_consume(&mut chars, TT::Tilde, &mut add_token), '~' => lex_and_consume(&mut chars, TT::Tilde, &mut add_token),
'@' => lex_and_consume(&mut chars, TT::AtSymbol, &mut add_token), '@' => lex_and_consume(&mut chars, TT::AtSymbol, &mut add_token),
';' => lex_and_consume(&mut chars, TT::Semicolon, &mut add_token), ';' => lex_and_consume(&mut chars, TT::Semicolon, &mut add_token),
@ -450,6 +449,7 @@ pub fn lex(s: &str, log: &mut dyn FnMut(Message, Span)) -> Vec<LexToken> {
']' => lex_and_consume(&mut chars, TT::CloseBlockBracket, &mut add_token), ']' => lex_and_consume(&mut chars, TT::CloseBlockBracket, &mut add_token),
',' => lex_and_consume(&mut chars, TT::Comma, &mut add_token), ',' => lex_and_consume(&mut chars, TT::Comma, &mut add_token),
'.' => lex_and_consume(&mut chars, TT::Dot, &mut add_token), '.' => lex_and_consume(&mut chars, TT::Dot, &mut add_token),
'?' => lex_and_consume(&mut chars, TT::QuestionMark, &mut add_token),
'0'..'9' => lex_numeric(&mut chars, &mut add_token), '0'..'9' => lex_numeric(&mut chars, &mut add_token),
'a'..'z' | 'A'..'Z' | '_' => lex_keyword_or_identifier(&mut chars, &mut add_token), 'a'..'z' | 'A'..'Z' | '_' => lex_keyword_or_identifier(&mut chars, &mut add_token),

View File

@ -8,12 +8,20 @@ use super::lexer::lex_tokens::{LexToken, TokenType};
use crate::logger::messages::Message; use crate::logger::messages::Message;
use crate::logger::messages::Message::UnexpectedToken; use crate::logger::messages::Message::UnexpectedToken;
use crate::modifiers::{FieldModifier, TypeModifier}; use crate::modifiers::{FieldModifier, TypeModifier};
use crate::parsing::parser::parsed_type_modifier::ParsedTypeModifier; use crate::parsing::lexer::lex_tokens::TokenType::CloseBracket;
use crate::parsing::parser::parser_operators::{BinaryOperator, PreOperator}; use crate::parsing::parser::parsed_statement::ParsedStatement::{
AnonymousCall, ExprPostOp, IndexingOperator,
};
use crate::parsing::parser::parsed_type_modifier::{ParsedTypeModifier, ReferenceModifier};
use crate::parsing::parser::parser_operators::{
BinaryOperator, PostOperator, PreOperator, TernaryOperator,
};
use crate::prim_type::PrimitiveType; use crate::prim_type::PrimitiveType;
use crate::span::Span; use crate::span::Span;
use enumflags2::BitFlags; use enumflags2::BitFlags;
use parsed_statement::ParsedStatement; use parsed_statement::ParsedStatement;
use std::fs::read;
use std::os::linux::raw::stat;
struct ParseReader<'a> { struct ParseReader<'a> {
tokens: &'a Vec<LexToken>, tokens: &'a Vec<LexToken>,
@ -21,7 +29,7 @@ struct ParseReader<'a> {
} }
impl<'a> ParseReader<'a> { impl<'a> ParseReader<'a> {
pub fn peek(&mut self) -> &LexToken { pub fn peek(&self) -> &LexToken {
let t = self.tokens.get(self.position); let t = self.tokens.get(self.position);
match t { match t {
None => self.tokens.last().unwrap(), None => self.tokens.last().unwrap(),
@ -35,7 +43,7 @@ impl<'a> ParseReader<'a> {
} }
} }
fn peek_ahead(&mut self, index: usize) -> &LexToken { fn peek_ahead(&self, index: usize) -> &LexToken {
let t = self.tokens.get(self.position + index); let t = self.tokens.get(self.position + index);
match t { match t {
None => self.tokens.last().unwrap(), None => self.tokens.last().unwrap(),
@ -471,10 +479,42 @@ fn parse_virtprop(
} }
fn parse_paramlist( fn parse_paramlist(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // paramlist ::= '(' ['void' | (type typemod [identifier] ['=' expr] {',' type typemod [identifier] ['=' expr]})] ')';
if reader.peek().token_type != TokenType::OpenBracket {
return None;
}
reader.next();
// (void) is equivalent to ()
if reader.peek().token_type == TokenType::VoidKeyword {
reader.next();
reader.consume(TokenType::CloseBracket, log);
return Some(Box::new(ParsedStatement::ParamList { parameters: vec![] }));
}
let mut params = Vec::new();
loop {
if reader.peek().token_type == TokenType::CloseBracket {
reader.next();
break;
}
let param_type = parse_type(reader, log);
// FIXME: Deal with empty param_type
let type_mod = parse_typemod(reader, log);
let identifier = parse_identifier(reader, log, true);
let mut default = None;
if reader.peek().token_type == TokenType::Equals {
reader.next();
default = parse_expr(reader, log);
// FIXME: log if default is emtpy
}
params.push((param_type, type_mod, identifier, default));
}
return Some(Box::new(ParsedStatement::ParamList { parameters: params }));
} }
fn parse_funcattr( fn parse_funcattr(
@ -486,13 +526,35 @@ fn parse_funcattr(
fn parse_statblock( fn parse_statblock(
reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
// FIXME // statblock ::= '{' {var | statement} '}';
if reader.peek().token_type != TokenType::OpenCurlyBracket { if reader.peek().token_type != TokenType::OpenCurlyBracket {
return None; return None;
} }
None reader.consume(TokenType::OpenCurlyBracket, log);
let mut children = Vec::new();
loop {
if reader.peek().token_type == TokenType::CloseCurlyBracket {
break;
}
let var = parse_var(reader, log);
if let Some(..) = var {
children.push(var.unwrap());
continue;
}
let statement = parse_statement(reader, log);
if let Some(..) = statement {
children.push(statement.unwrap());
continue;
}
// FIXME: Log error
break;
}
reader.consume(TokenType::CloseCurlyBracket, log);
Some(Box::new(ParsedStatement::StatBlock {
statements: children,
}))
} }
fn parse_var( fn parse_var(
@ -522,16 +584,14 @@ fn parse_var(
} }
} }
} }
if property_type.is_none() { property_type.as_ref()?;
return None;
}
let identifier = parse_identifier(&mut reader, log, false); let identifier = parse_identifier(&mut reader, log, false);
identifier.as_ref()?; identifier.as_ref()?;
let mut assignment: Option<Box<ParsedStatement>> = None; let mut assignment: Option<Box<ParsedStatement>> = None;
// FIXME: Implement arglist // TODO: Implement arglist
// [( '=' (initlist | expr)) | arglist] // [( '=' (initlist | expr)) | arglist]
if reader.peek().token_type == TokenType::Equals { if reader.peek().token_type == TokenType::Equals {
// Eat the equals token. // Eat the equals token.
@ -547,6 +607,8 @@ fn parse_var(
} }
} }
//TODO: Multiple variable creation
// {',' identifier [( '=' (initlist | expr)) | arglist]} ';'; // {',' identifier [( '=' (initlist | expr)) | arglist]} ';';
outer_reader.set_from_inner(&reader); outer_reader.set_from_inner(&reader);
@ -559,94 +621,257 @@ fn parse_var(
} }
fn parse_statement( fn parse_statement(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // statement ::= (if | for | while | return | statblock | break | continue | dowhile | switch | exprstat | try );
match reader.peek().token_type {
TokenType::IfKeyword => parse_if(reader, log),
TokenType::ForKeyword => parse_for(reader, log),
TokenType::WhileKeyword => parse_while(reader, log),
TokenType::ReturnKeyword => parse_return(reader, log),
TokenType::OpenCurlyBracket => parse_statblock(reader, log),
TokenType::BreakKeyword => parse_break(reader, log),
TokenType::ContinueKeyword => parse_continue(reader, log),
TokenType::DoKeyword => parse_dowhile(reader, log),
TokenType::SwitchKeyword => parse_switch(reader, log),
TokenType::TryKeyword => parse_try(reader, log),
_ => parse_exprstat(reader, log),
}
} }
fn parse_switch( fn parse_switch(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // switch ::= 'switch' '(' assign ')' '{' {case} '}';
reader.consume(TokenType::SwitchKeyword, log);
reader.consume(TokenType::OpenBracket, log);
let assign = parse_assign(reader, log);
// FIXME: Deal with None assign
reader.consume(TokenType::CloseBracket, log);
reader.consume(TokenType::OpenCurlyBracket, log);
let mut vec = Vec::new();
loop {
if reader.peek().token_type == TokenType::CloseCurlyBracket {
break;
}
let case = parse_case(reader, log);
if case.is_none() {
break;
}
vec.push(case.unwrap());
}
Some(Box::new(ParsedStatement::Switch {
expression: assign.unwrap(),
cases: vec,
}))
} }
fn parse_case( fn parse_case(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // case ::= (('case' expr) | 'default') ':' {statement};
let mut expression = None;
let initial_token = &reader.peek().token_type;
if initial_token == &TokenType::DefaultKeyword {
reader.next();
} else if initial_token == &TokenType::CaseKeyword {
reader.next();
expression = parse_assign(reader, log);
if expression.is_none() {
// FIXME: log error
}
}
reader.consume(TokenType::Colon, log);
let statement = parse_statement(reader, log);
// FIXME: deal with None statement
Some(Box::new(ParsedStatement::Case {
expression,
statement: statement.unwrap(),
}))
} }
fn parse_try( fn parse_try(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // try ::= 'try' statblock 'catch' statblock;
reader.consume(TokenType::TryKeyword, log);
let try_block = parse_statblock(reader, log);
reader.consume(TokenType::CatchKeyword, log);
let catch_block = parse_statblock(reader, log);
// FIXME: Deal with empty try or catch blocks.
Some(Box::new(ParsedStatement::TryStatement {
try_block: try_block.unwrap(),
catch_block: catch_block.unwrap(),
}))
} }
fn parse_dowhile( fn parse_dowhile(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // dowhile ::= 'do' statement 'while' '(' assign ')' ';';
reader.consume(TokenType::DoKeyword, log);
let statement = parse_statement(reader, log);
reader.consume(TokenType::WhileKeyword, log);
reader.consume(TokenType::OpenBracket, log);
let condition = parse_assign(reader, log);
reader.consume(TokenType::CloseBracket, log);
reader.consume(TokenType::Semicolon, log);
// FIXME: Deal with empty statement or condition.
Some(Box::new(ParsedStatement::DoWhileStatement {
statement: statement.unwrap(),
condition: condition.unwrap(),
}))
} }
fn parse_while( fn parse_while(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // while ::= 'while' '(' assign ')' statement;
reader.consume(TokenType::WhileKeyword, log);
reader.consume(TokenType::OpenBracket, log);
let condition = parse_assign(reader, log);
reader.consume(TokenType::CloseBracket, log);
let statement = parse_statement(reader, log);
// FIXME: Deal with empty statement or condition.
Some(Box::new(ParsedStatement::WhileStatement {
condition: condition.unwrap(),
statement: statement.unwrap(),
}))
} }
fn parse_for( fn parse_for(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // for ::= 'for' '(' (var | exprstat) exprstat [assign {',' assign}] ')' statement;
reader.consume(TokenType::ForKeyword, log);
reader.consume(TokenType::OpenBracket, log);
let mut initializer = parse_var(reader, log);
if initializer.is_none() {
initializer = parse_exprstat(reader, log);
}
// FIXME: initializer can still be None
let bounds = parse_exprstat(reader, log);
let mut increment_expressions = Vec::new();
loop {
if reader.peek().token_type == TokenType::CloseBracket {
break;
}
let assign = parse_assign(reader, log);
if assign.is_some() {
increment_expressions.push(assign.unwrap());
}
if reader.peek().token_type != TokenType::Comma {
break;
}
reader.next();
}
Some(Box::new(ParsedStatement::ForStatement {
initializer: initializer.unwrap(),
bounds: bounds.unwrap(),
increment: increment_expressions,
}))
} }
fn parse_if( fn parse_if(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // if ::= 'if' '(' assign ')' statement ['else' statement];
reader.consume(TokenType::IfKeyword, log);
reader.consume(TokenType::OpenBracket, log);
let condition = parse_assign(reader, log);
// FIXME: deal with empty condition
reader.consume(TokenType::CloseBracket, log);
let statement = parse_statement(reader, log);
let mut else_statement = None;
if reader.peek().token_type == TokenType::ElseKeyword {
reader.next();
else_statement = parse_statement(reader, log);
}
Some(Box::new(ParsedStatement::IfStatement {
condition: condition.unwrap(),
statement: statement.unwrap(),
else_statement,
}))
} }
fn parse_break( fn parse_break(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // break ::= 'break' ';';
reader.consume(TokenType::BreakKeyword, log);
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::BreakStatement {}))
} }
fn parse_continue( fn parse_continue(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // continue ::= 'continue' ';';
reader.consume(TokenType::ContinueKeyword, log);
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::ContinueStatement {}))
} }
fn parse_exprstat( fn parse_exprstat(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // exprstat ::= assign ';';
let expression = parse_assign(reader, log);
expression.as_ref()?;
reader.consume(TokenType::Semicolon, log);
expression
} }
fn parse_return( fn parse_return(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // return ::= 'return' [assign] ';';
reader.consume(TokenType::ReturnKeyword, log);
let expression = parse_assign(reader, log);
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::ReturnStatement { expression }))
} }
fn parse_ternary( fn parse_ternary(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // ternary ::= expr ['?' assign ':' assign];
let expr = parse_expr(reader, log);
expr.as_ref()?;
if reader.peek().token_type == TokenType::QuestionMark {
reader.next();
let a = parse_assign(reader, log);
reader.consume(TokenType::Colon, log);
let b = parse_assign(reader, log);
// FIXME: Deal with None a or b
return Some(Box::new(ParsedStatement::TernaryExpr {
left: expr.unwrap(),
operator: TernaryOperator::Conditional,
middle: a.unwrap(),
right: b.unwrap(),
}));
}
expr
} }
fn parse_expr( fn parse_expr(
@ -669,7 +894,7 @@ fn parse_expr(
binary_operand = parse_bitop(reader, log); binary_operand = parse_bitop(reader, log);
} }
if binary_operand.is_some() { if let Some(..) = binary_operand {
let expr_term2 = parse_exprterm(reader, log); let expr_term2 = parse_exprterm(reader, log);
// FIXME: deal with empty expr_term2 // FIXME: deal with empty expr_term2
return Some(Box::new(ParsedStatement::BinaryExpr { return Some(Box::new(ParsedStatement::BinaryExpr {
@ -717,34 +942,135 @@ fn parse_exprterm(
let mut real_value = expr_value.unwrap(); let mut real_value = expr_value.unwrap();
let real_value = parse_exprpostop(&mut reader, log, real_value); loop {
let post_op_value = parse_exprpostop(&mut reader, log, real_value);
real_value = post_op_value.0;
if !post_op_value.1 {
break;
}
}
for op in expr_pre_op.iter().rev() {
real_value = Box::new(ParsedStatement::ExprPreOp {
operator: *op,
operand: real_value,
})
}
outer_reader.set_from_inner(&reader); outer_reader.set_from_inner(&reader);
Some(Box::new(ParsedStatement::ExprTerm { Some(real_value)
pre_op: expr_pre_op,
exp_value: real_value,
}))
} }
fn parse_exprpostop( fn parse_exprpostop(
reader: &mut ParseReader, reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
base: Box<ParsedStatement>, base: Box<ParsedStatement>,
) -> Box<ParsedStatement> { ) -> (Box<ParsedStatement>, bool) {
// exprpostop ::= ('.' (funccall | identifier)) | ('[' [identifier ':'] assign {',' [identifier ':' assign} ']') | arglist | '++' | '--'; // exprpostop ::= ('.' (funccall | identifier)) | ('[' [identifier ':'] assign {',' [identifier ':' assign} ']') | arglist | '++' | '--';
// FIXME: This needs to be implemented.
// ('.' (funccall | identifier)) // ('.' (funccall | identifier))
if reader.peek().token_type == TokenType::Dot { if reader.peek().token_type == TokenType::Dot {
reader.next(); reader.next();
if let Some(s) = parse_funccall(reader, log) {
return (
Box::new(ParsedStatement::MemberFuncCall {
operand: base,
func_call: s,
}),
true,
);
}
if let Some(s) = parse_identifier(reader, log, false) {
return (
Box::new(ParsedStatement::MemberAccess {
operand: base,
identifier: s,
}),
true,
);
}
// We've already errored if we've reached this point (through the parse_identifier), so just
// return.
return (base, false);
} }
// ('[' [identifier ':'] assign {',' [identifier ':' assign} ']')
// arglist
// '++'
// '--'
base // ( '[' [ identifier ':'] assign { ',' [ identifier ':' assign } ']' )
if reader.peek().token_type == TokenType::OpenBlockBracket {
reader.next();
let mut vec = Vec::new();
let mut inner_reader = reader.create_inner();
loop {
let mut identifier = None;
if let Some(s) = parse_identifier(&mut inner_reader, log, true) {
if inner_reader.peek().token_type == TokenType::Colon {
inner_reader.next();
identifier = Some(s);
}
}
let assign = parse_assign(&mut inner_reader, log);
if assign.is_none() {
break;
}
vec.push((identifier, assign.unwrap()));
if inner_reader.peek().token_type == TokenType::CloseBlockBracket {
break;
}
inner_reader.consume(TokenType::Comma, log);
}
if vec.is_empty() {
log(Message::EmptyIndex, reader.peek().span);
}
reader.set_from_inner(&inner_reader);
reader.consume(TokenType::CloseBlockBracket, log);
return (
Box::new(IndexingOperator {
operand: base,
index: vec,
}),
true,
);
}
// arglist
// We know an arglist always opens with a '(', so we can just check for that to avoid a function
// call
if reader.peek().token_type == TokenType::OpenBracket {
if let Some(s) = parse_arglist(reader, log) {
return (
Box::new(AnonymousCall {
operand: base,
arg_list: s,
}),
true,
);
}
}
// '++'
if reader.peek().token_type == TokenType::PlusPlus {
reader.next();
return (
Box::new(ExprPostOp {
operand: base,
operator: PostOperator::Increment,
}),
true,
);
}
// '--'
if reader.peek().token_type == TokenType::MinusMinus {
reader.next();
return (
Box::new(ExprPostOp {
operand: base,
operator: PostOperator::Decrement,
}),
true,
);
}
(base, false)
} }
fn parse_exprvalue( fn parse_exprvalue(
@ -801,10 +1127,35 @@ fn parse_lambda(
} }
fn parse_typemod( fn parse_typemod(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<BitFlags<ReferenceModifier>> {
unimplemented!(); // typemod ::= ['&' ['in' | 'out' | 'inout']];
if reader.peek().token_type == TokenType::Ampersand {
reader.next();
} else {
return None;
}
let mut type_mod: BitFlags<ReferenceModifier> =
BitFlags::from(ReferenceModifier::In) | ReferenceModifier::Out;
match reader.peek().token_type {
TokenType::InKeyword => {
type_mod = BitFlags::from(ReferenceModifier::In);
reader.next();
}
TokenType::OutKeyword => {
type_mod = BitFlags::from(ReferenceModifier::Out);
reader.next();
}
TokenType::InOutKeyword => {
// This is implicit if not otherwise stated, so just consume the token and continue.
reader.next();
}
_ => {}
}
Some(type_mod)
} }
fn parse_literal( fn parse_literal(
@ -945,16 +1296,30 @@ fn parse_initlist(
} }
fn parse_assign( fn parse_assign(
_outer_reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
unimplemented!(); // ternary [ assignop assign ];
let ternary = parse_ternary(reader, log);
ternary.as_ref()?;
if let Some(assign_op) = parse_assignop(reader, log) {
let assign = parse_assign(reader, log);
// FIXME: deal with None assign.
return Some(Box::new(ParsedStatement::Assignment {
left: ternary.unwrap(),
operator: assign_op,
right: assign.unwrap(),
}));
}
ternary
} }
fn parse_type( fn parse_type(
reader: &mut ParseReader, reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span), log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> { ) -> Option<Box<ParsedStatement>> {
// type ::= ['const'] scope datatype ['<' type {',' type} '>'] { ('[' ']') | ('@' ['const']) };
let f = reader.peek(); let f = reader.peek();
let mut is_const = false; let mut is_const = false;
if f.token_type == TokenType::ConstKeyword { if f.token_type == TokenType::ConstKeyword {
@ -1090,13 +1455,6 @@ fn parse_datatype(
res res
} }
fn parse_primtype(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
}
fn parse_bitop( fn parse_bitop(
reader: &mut ParseReader, reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span), _log: &mut dyn FnMut(Message, Span),

View File

@ -1,7 +1,10 @@
use super::parsed_type_modifier::ParsedTypeModifier; use super::parsed_type_modifier::ParsedTypeModifier;
use crate::defines::{LiteralFloat, LiteralInt}; use crate::defines::{LiteralFloat, LiteralInt};
use crate::modifiers::{FieldModifier, TypeModifier}; use crate::modifiers::{FieldModifier, TypeModifier};
use crate::parsing::parser::parser_operators::{BinaryOperator, PreOperator}; use crate::parsing::parser::parsed_type_modifier::ReferenceModifier;
use crate::parsing::parser::parser_operators::{
BinaryOperator, PostOperator, PreOperator, TernaryOperator,
};
use crate::prim_type::PrimitiveType; use crate::prim_type::PrimitiveType;
use enumflags2::BitFlags; use enumflags2::BitFlags;
@ -63,12 +66,13 @@ pub enum ParsedStatement {
statement_type: Option<Box<ParsedStatement>>, statement_type: Option<Box<ParsedStatement>>,
initlist: Box<ParsedStatement>, initlist: Box<ParsedStatement>,
}, },
ExprTerm {
pre_op: Vec<PreOperator>,
exp_value: Box<ParsedStatement>,
},
ExprPreOp { ExprPreOp {
operator: PreOperator, operator: PreOperator,
operand: Box<ParsedStatement>,
},
ExprPostOp {
operator: PostOperator,
operand: Box<ParsedStatement>,
}, },
ExprVoidValue {}, ExprVoidValue {},
ConstructCall { ConstructCall {
@ -97,4 +101,78 @@ pub enum ParsedStatement {
operator: BinaryOperator, operator: BinaryOperator,
right: Box<ParsedStatement>, right: Box<ParsedStatement>,
}, },
TernaryExpr {
left: Box<ParsedStatement>,
operator: TernaryOperator,
middle: Box<ParsedStatement>,
right: Box<ParsedStatement>,
},
MemberAccess {
operand: Box<ParsedStatement>,
identifier: String,
},
MemberFuncCall {
operand: Box<ParsedStatement>,
func_call: Box<ParsedStatement>,
},
IndexingOperator {
operand: Box<ParsedStatement>,
index: Vec<(Option<String>, Box<ParsedStatement>)>,
},
AnonymousCall {
operand: Box<ParsedStatement>,
arg_list: Box<ParsedStatement>,
},
Assignment {
left: Box<ParsedStatement>,
operator: BinaryOperator,
right: Box<ParsedStatement>,
},
Switch {
expression: Box<ParsedStatement>,
cases: Vec<Box<ParsedStatement>>,
},
Case {
// None for default
expression: Option<Box<ParsedStatement>>,
statement: Box<ParsedStatement>,
},
TryStatement {
try_block: Box<ParsedStatement>,
catch_block: Box<ParsedStatement>,
},
StatBlock {
statements: Vec<Box<ParsedStatement>>,
},
DoWhileStatement {
statement: Box<ParsedStatement>,
condition: Box<ParsedStatement>,
},
WhileStatement {
condition: Box<ParsedStatement>,
statement: Box<ParsedStatement>,
},
ForStatement {
initializer: Box<ParsedStatement>,
bounds: Box<ParsedStatement>,
increment: Vec<Box<ParsedStatement>>,
},
IfStatement {
condition: Box<ParsedStatement>,
statement: Box<ParsedStatement>,
else_statement: Option<Box<ParsedStatement>>,
},
BreakStatement {},
ContinueStatement {},
ReturnStatement {
expression: Option<Box<ParsedStatement>>,
},
ParamList {
parameters: Vec<(
Box<ParsedStatement>, // type
Option<BitFlags<ReferenceModifier>>, // typemod
Option<String>, // identifier
Option<Box<ParsedStatement>>, // default expression
)>,
},
} }

View File

@ -1,6 +1,16 @@
use enumflags2::bitflags;
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
pub enum ParsedTypeModifier { pub enum ParsedTypeModifier {
Array, Array,
Handle, Handle,
ConstHandle, ConstHandle,
} }
#[bitflags]
#[repr(u8)]
#[derive(Eq, PartialEq, Debug)]
pub enum ReferenceModifier {
In,
Out,
}

View File

@ -1,4 +1,4 @@
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum PreOperator { pub enum PreOperator {
Negative, Negative,
Identity, Identity,
@ -9,7 +9,13 @@ pub enum PreOperator {
HandleOf, HandleOf,
} }
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum PostOperator {
Increment,
Decrement,
}
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum BinaryOperator { pub enum BinaryOperator {
// math op // math op
Addition, Addition,
@ -53,3 +59,8 @@ pub enum BinaryOperator {
AssignmentRightShift, AssignmentRightShift,
AssignmentArithmeticRightShift, AssignmentArithmeticRightShift,
} }
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum TernaryOperator {
Conditional,
}

View File

@ -254,10 +254,7 @@ fn test_assign_to_global_variable() {
assert!(assignment.is_some()); assert!(assignment.is_some());
assert_eq!( assert_eq!(
*(assignment.as_ref().unwrap().as_ref()), *(assignment.as_ref().unwrap().as_ref()),
ParsedStatement::ExprTerm { ParsedStatement::IntegerLiteral(100)
pre_op: vec![],
exp_value: Box::from(ParsedStatement::IntegerLiteral(100)),
}
); );
} else { } else {
unreachable!() unreachable!()
@ -308,9 +305,9 @@ fn test_assign_negative_to_global_variable() {
assert!(assignment.is_some()); assert!(assignment.is_some());
assert_eq!( assert_eq!(
*(assignment.as_ref().unwrap().as_ref()), *(assignment.as_ref().unwrap().as_ref()),
ParsedStatement::ExprTerm { ParsedStatement::ExprPreOp {
pre_op: vec![PreOperator::Negative], operator: PreOperator::Negative,
exp_value: Box::from(ParsedStatement::IntegerLiteral(100)), operand: Box::from(ParsedStatement::IntegerLiteral(100)),
} }
); );
} else { } else {
@ -365,14 +362,11 @@ fn test_assign_addition_to_global_variable() {
assert_eq!( assert_eq!(
*(assignment.as_ref().unwrap().as_ref()), *(assignment.as_ref().unwrap().as_ref()),
ParsedStatement::BinaryExpr { ParsedStatement::BinaryExpr {
left: Box::new(ParsedStatement::ExprTerm { left: Box::new(ParsedStatement::IntegerLiteral(100)),
pre_op: vec![],
exp_value: Box::new(ParsedStatement::IntegerLiteral(100)),
}),
operator: BinaryOperator::Addition, operator: BinaryOperator::Addition,
right: Box::new(ParsedStatement::ExprTerm { right: Box::new(ParsedStatement::ExprPreOp {
pre_op: vec![PreOperator::Negative], operator: PreOperator::Negative,
exp_value: Box::new(ParsedStatement::IntegerLiteral(20)), operand: Box::new(ParsedStatement::IntegerLiteral(20)),
}), }),
} }
); );

View File

@ -16,6 +16,7 @@ pub enum PrimitiveType {
Bool, Bool,
} }
#[allow(dead_code)]
pub fn get_primitive_type_byte_size(t: PrimitiveType) -> PointerSize { pub fn get_primitive_type_byte_size(t: PrimitiveType) -> PointerSize {
match t { match t {
PrimitiveType::Void => 0, PrimitiveType::Void => 0,