More parsing work

This commit is contained in:
Deukhoofd 2022-04-03 19:13:36 +02:00
parent 2bc3bee344
commit f004c19133
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
5 changed files with 177 additions and 27 deletions

View File

@ -85,9 +85,8 @@ paramlist ::= '(' ['void' | (type typemod [identifier] ['=' expr] {','
virtprop ::= ['private' | 'protected'] type ['&'] identifier '{' {('get' | 'set') ['const'] funcattr (statblock | ';')} '}';
func ::= {'shared' | 'external'} ['private' | 'protected'] [((type ['&']) | '~')] identifier paramlist ['const'] funcattr (';' | statblock);
funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
class ::= {'shared' | 'abstract' | 'final' | 'external'} 'class' identifier
class ::= {'shared' | 'abstract' | 'final' | 'external' | 'mixin'} 'class' identifier
(';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef | class} '}'));
mixin ::= 'mixin' class;
enum ::= {'shared' | 'external'} 'enum' identifier [ ':' primtype ] (';' | ('{' identifier ['=' expr] {',' identifier ['=' expr]} '}'));
import ::= 'import' type ['&'] identifier paramlist funcattr 'from' string ';';
typedef ::= 'typedef' (primtype | identifier) identifier ';';
@ -96,4 +95,4 @@ interfacemethod ::= type ['&'] identifier paramlist ['const'] ';';
interface ::= {'external' | 'shared'} 'interface' identifier (';' | ([':' identifier {',' identifier}] '{' {virtprop | interfacemethod} '}'));
namespace ::= 'namespace' identifier '{' script '}';
script ::= {import | enum | typedef | class | mixin | interface | funcdef | virtprop | var | func | namespace | ';'};
script ::= {import | enum | typedef | class | interface | funcdef | virtprop | var | func | namespace | ';'};

View File

@ -1,3 +1,4 @@
mod parsed_funcattr;
pub mod parsed_statement;
pub mod parsed_type_modifier;
mod parser_operators;
@ -9,6 +10,7 @@ use crate::logger::messages::Message;
use crate::logger::messages::Message::UnexpectedToken;
use crate::modifiers::{FieldModifier, TypeModifier};
use crate::parsing::lexer::lex_tokens::TokenType::CloseBracket;
use crate::parsing::parser::parsed_funcattr::FuncAttr;
use crate::parsing::parser::parsed_statement::ParsedStatement::{
AnonymousCall, ExprPostOp, IndexingOperator,
};
@ -311,37 +313,126 @@ fn parse_interface(
}
fn parse_interface_method(
_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
outer_reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
// interfacemethod ::= type ['&'] identifier paramlist ['const'] ';';
let mut reader = outer_reader.create_inner();
let return_type = parse_type(&mut reader, log);
if return_type.is_none() {
return None;
}
let returns_reference = reader.peek().token_type == TokenType::Ampersand;
if returns_reference {
reader.next();
}
let identifier = parse_identifier(&mut reader, log, true);
if identifier.is_none() {
return None;
}
let param_list = parse_paramlist(&mut reader, log);
if param_list.is_none() {
return None;
}
let is_const = reader.peek().token_type == TokenType::ConstKeyword;
if is_const {
reader.next();
}
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::InterfaceMethod {
return_type: return_type.unwrap(),
returns_reference,
identifier: identifier.unwrap(),
param_list: param_list.unwrap(),
is_const,
}))
}
fn parse_typedef(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
// typedef ::= 'typedef' (primtype | identifier) identifier ';';
if reader.peek().token_type != TokenType::TypeDefKeyword {
return None;
}
reader.next();
let mut left_type = parse_primtype(reader, log);
if left_type.is_none() {
let left_type_identifier = parse_identifier(reader, log, false);
if left_type_identifier.is_some() {
left_type = Some(Box::new(ParsedStatement::DataTypeIdentifier {
identifier: left_type_identifier.unwrap(),
}));
}
}
let right_type_identifier = parse_identifier(reader, log, false);
if right_type_identifier.is_none() {
return None;
}
let right_type = Box::new(ParsedStatement::DataTypeIdentifier {
identifier: right_type_identifier.unwrap(),
});
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::TypeDefStatement {
from: left_type.unwrap(),
to: right_type,
}))
}
fn parse_import(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
// import ::= 'import' type ['&'] identifier paramlist funcattr 'from' string ';';
if reader.peek().token_type != TokenType::ImportKeyword {
return None;
}
reader.next();
let import_type = parse_type(reader, log);
let is_reference_type = reader.peek().token_type == TokenType::Ampersand;
if is_reference_type {
reader.next();
}
let identifier = parse_identifier(reader, log, false);
identifier.as_ref()?;
let param_list = parse_paramlist(reader, log);
let func_attr = parse_funcattr(reader, log);
reader.consume(TokenType::FromKeyword, log);
let mut source = None;
let source_token = reader.next();
if let TokenType::StringLiteral(s) = &source_token.token_type {
source = Some(s.to_string());
}
if source.is_none() {
log(
Message::UnexpectedToken {
found: source_token.token_type.clone(),
expected: vec![TokenType::StringLiteral("".to_string())],
},
source_token.span,
);
return None;
}
reader.consume(TokenType::Semicolon, log);
Some(Box::new(ParsedStatement::ImportStatement {
import_type: import_type.unwrap(),
is_reference: is_reference_type,
identifier: identifier.unwrap(),
param_list: param_list.unwrap(),
func_attr,
source: source.unwrap(),
}))
}
fn parse_enum(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
}
fn parse_mixin(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// enum ::= {'shared' | 'external'} 'enum' identifier [ ':' primtype ] (';' | ('{' identifier ['=' expr] {',' identifier ['=' expr]} '}'));
unimplemented!();
}
@ -349,6 +440,8 @@ fn parse_class(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// class ::= {'shared' | 'abstract' | 'final' | 'external' | 'mixin'} 'class' identifier
// (';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef | class} '}'));
unimplemented!();
}
@ -356,6 +449,7 @@ fn parse_funcdef(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
unimplemented!();
}
@ -363,6 +457,7 @@ fn parse_func(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// func ::= {'shared' | 'external'} ['private' | 'protected'] [((type ['&']) | '~')] identifier paramlist ['const'] funcattr (';' | statblock);
unimplemented!();
}
@ -511,17 +606,29 @@ fn parse_paramlist(
default = parse_expr(reader, log);
// FIXME: log if default is emtpy
}
params.push((param_type, type_mod, identifier, default));
params.push((param_type.unwrap(), type_mod, identifier, default));
}
return Some(Box::new(ParsedStatement::ParamList { parameters: params }));
Some(Box::new(ParsedStatement::ParamList { parameters: params }))
}
fn parse_funcattr(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
unimplemented!();
reader: &mut ParseReader,
log: &mut dyn FnMut(Message, Span),
) -> BitFlags<FuncAttr> {
// funcattr ::= {'override' | 'final' | 'explicit' | 'property'};
let mut func_attr: BitFlags<FuncAttr> = BitFlags::empty();
loop {
match reader.peek().token_type {
TokenType::OverrideKeyword => func_attr |= FuncAttr::Override,
TokenType::FinalKeyword => func_attr |= FuncAttr::Final,
TokenType::ExplicitKeyword => func_attr |= FuncAttr::Explicit,
TokenType::PropertyKeyword => func_attr |= FuncAttr::Property,
_ => break,
}
reader.next();
}
func_attr
}
fn parse_statblock(
@ -1123,6 +1230,7 @@ fn parse_lambda(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// lambda ::= 'function' '(' [[type typemod] identifier {',' [type typemod] identifier}] ')' statblock;
unimplemented!();
}
@ -1262,6 +1370,7 @@ fn parse_arglist(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// arglist ::= '(' [identifier ':'] assign {',' [identifier ':'] assign} ')';
unimplemented!();
}
@ -1292,6 +1401,7 @@ fn parse_initlist(
_outer_reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
// initlist ::= '{' [assign | initlist] {',' [assign | initlist]} '}';
unimplemented!();
}
@ -1408,9 +1518,19 @@ fn parse_datatype(
if let Some(identifier) = parse_identifier(reader, log, true) {
return Some(Box::new(ParsedStatement::DataTypeIdentifier { identifier }));
}
if reader.peek().token_type == TokenType::AutoKeyword {
reader.next();
return Some(Box::new(ParsedStatement::DataTypeAuto {}));
}
parse_primtype(reader, log)
}
fn parse_primtype(
reader: &mut ParseReader,
_log: &mut dyn FnMut(Message, Span),
) -> Option<Box<ParsedStatement>> {
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,
})),

View File

@ -0,0 +1,11 @@
use enumflags2::bitflags;
#[bitflags]
#[repr(u8)]
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum FuncAttr {
Override,
Final,
Explicit,
Property,
}

View File

@ -1,6 +1,7 @@
use super::parsed_type_modifier::ParsedTypeModifier;
use crate::defines::{LiteralFloat, LiteralInt};
use crate::modifiers::{FieldModifier, TypeModifier};
use crate::parsing::parser::parsed_funcattr::FuncAttr;
use crate::parsing::parser::parsed_type_modifier::ReferenceModifier;
use crate::parsing::parser::parser_operators::{
BinaryOperator, PostOperator, PreOperator, TernaryOperator,
@ -175,4 +176,23 @@ pub enum ParsedStatement {
Option<Box<ParsedStatement>>, // default expression
)>,
},
InterfaceMethod {
return_type: Box<ParsedStatement>,
returns_reference: bool,
identifier: String,
param_list: Box<ParsedStatement>,
is_const: bool,
},
TypeDefStatement {
from: Box<ParsedStatement>,
to: Box<ParsedStatement>,
},
ImportStatement {
import_type: Box<ParsedStatement>,
is_reference: bool,
identifier: String,
param_list: Box<ParsedStatement>,
func_attr: BitFlags<FuncAttr>,
source: String,
},
}

View File

@ -9,7 +9,7 @@ pub enum ParsedTypeModifier {
#[bitflags]
#[repr(u8)]
#[derive(Eq, PartialEq, Debug)]
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum ReferenceModifier {
In,
Out,