Loads more parsing work
This commit is contained in:
parent
75f8720c54
commit
2bc3bee344
11
Cargo.toml
11
Cargo.toml
|
@ -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
|
|
@ -56,10 +56,10 @@ typemod ::= ['&' ['in' | 'out' | 'inout']];
|
||||||
lambda ::= 'function' '(' [[type typemod] identifier {',' [type typemod] identifier}] ')' statblock;
|
lambda ::= 'function' '(' [[type typemod] identifier {',' [type typemod] identifier}] ')' statblock;
|
||||||
|
|
||||||
exprvalue ::= 'void' | constructcall | funccall | varaccess | cast | literal | '(' assign ')' | lambda;
|
exprvalue ::= 'void' | constructcall | funccall | varaccess | cast | literal | '(' assign ')' | lambda;
|
||||||
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 ';';
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub enum TokenType {
|
||||||
ColonColon,
|
ColonColon,
|
||||||
Comma,
|
Comma,
|
||||||
Dot,
|
Dot,
|
||||||
|
QuestionMark,
|
||||||
OpenBracket,
|
OpenBracket,
|
||||||
CloseBracket,
|
CloseBracket,
|
||||||
OpenCurlyBracket,
|
OpenCurlyBracket,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
)>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
@ -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)),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue