Adds parsing for class, and for funcdef
This commit is contained in:
parent
2e87674720
commit
b1d516b268
|
@ -0,0 +1,93 @@
|
||||||
|
////////////////////////////
|
||||||
|
// Automatically Generated//
|
||||||
|
////////////////////////////
|
||||||
|
use crate::logger::messages::Message;
|
||||||
|
use crate::parsing::lexer::lex;
|
||||||
|
use crate::parsing::lexer::lex_tokens::LexToken;
|
||||||
|
use crate::parsing::parser::parse;
|
||||||
|
use crate::parsing::parser::parsed_statement::ParsedStatement;
|
||||||
|
use crate::span::Span;
|
||||||
|
|
||||||
|
fn panic_on_error(msg: Message, _: Span) {
|
||||||
|
std::panic::panic_any(msg.stringify());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn integration_empty_class_declaration() {
|
||||||
|
let script = "class Foo {}";
|
||||||
|
let lexed_tokens = lex(script, &mut panic_on_error);
|
||||||
|
println!("{}", serde_json::to_string(&lexed_tokens).unwrap());
|
||||||
|
let expected_tokens: Vec<LexToken> =
|
||||||
|
serde_json::from_str(r#"[
|
||||||
|
{
|
||||||
|
"token_type": "ClassKeyword",
|
||||||
|
"span": {
|
||||||
|
"start": 0,
|
||||||
|
"end": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 5,
|
||||||
|
"end": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Foo"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 6,
|
||||||
|
"end": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 9,
|
||||||
|
"end": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "OpenCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 10,
|
||||||
|
"end": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "CloseCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 11,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "EndOfFile",
|
||||||
|
"span": {
|
||||||
|
"start": 12,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"#).unwrap();
|
||||||
|
assert_eq!(lexed_tokens, expected_tokens);
|
||||||
|
|
||||||
|
let parsed_tree = parse(lexed_tokens, &mut panic_on_error);
|
||||||
|
println!("{}", serde_json::to_string(&parsed_tree).unwrap());
|
||||||
|
let expected_tree: Box<ParsedStatement> =
|
||||||
|
serde_json::from_str(r#"{
|
||||||
|
"Script": {
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"ClassDeclaration": {
|
||||||
|
"modifiers": 0,
|
||||||
|
"name": "Foo",
|
||||||
|
"inherits": [],
|
||||||
|
"statements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"#).unwrap();
|
||||||
|
assert_eq!(parsed_tree, expected_tree);
|
||||||
|
}
|
|
@ -1,2 +1,4 @@
|
||||||
mod enum_definition;
|
mod enum_definition;
|
||||||
|
mod multiple_inheritance_class;
|
||||||
|
mod empty_class_declaration;
|
||||||
mod add_function;
|
mod add_function;
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
////////////////////////////
|
||||||
|
// Automatically Generated//
|
||||||
|
////////////////////////////
|
||||||
|
use crate::logger::messages::Message;
|
||||||
|
use crate::parsing::lexer::lex;
|
||||||
|
use crate::parsing::lexer::lex_tokens::LexToken;
|
||||||
|
use crate::parsing::parser::parse;
|
||||||
|
use crate::parsing::parser::parsed_statement::ParsedStatement;
|
||||||
|
use crate::span::Span;
|
||||||
|
|
||||||
|
fn panic_on_error(msg: Message, _: Span) {
|
||||||
|
std::panic::panic_any(msg.stringify());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn integration_multiple_inheritance_class() {
|
||||||
|
let script = "class Foo : Zom, Aar, Bar {}";
|
||||||
|
let lexed_tokens = lex(script, &mut panic_on_error);
|
||||||
|
println!("{}", serde_json::to_string(&lexed_tokens).unwrap());
|
||||||
|
let expected_tokens: Vec<LexToken> =
|
||||||
|
serde_json::from_str(r#"[
|
||||||
|
{
|
||||||
|
"token_type": "ClassKeyword",
|
||||||
|
"span": {
|
||||||
|
"start": 0,
|
||||||
|
"end": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 5,
|
||||||
|
"end": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Foo"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 6,
|
||||||
|
"end": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 9,
|
||||||
|
"end": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Colon",
|
||||||
|
"span": {
|
||||||
|
"start": 10,
|
||||||
|
"end": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 11,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Zom"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 12,
|
||||||
|
"end": 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Comma",
|
||||||
|
"span": {
|
||||||
|
"start": 15,
|
||||||
|
"end": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 16,
|
||||||
|
"end": 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Aar"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 17,
|
||||||
|
"end": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Comma",
|
||||||
|
"span": {
|
||||||
|
"start": 20,
|
||||||
|
"end": 21
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 21,
|
||||||
|
"end": 22
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Bar"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 22,
|
||||||
|
"end": 25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 25,
|
||||||
|
"end": 26
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "OpenCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 26,
|
||||||
|
"end": 27
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "CloseCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 27,
|
||||||
|
"end": 28
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "EndOfFile",
|
||||||
|
"span": {
|
||||||
|
"start": 28,
|
||||||
|
"end": 28
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"#).unwrap();
|
||||||
|
assert_eq!(lexed_tokens, expected_tokens);
|
||||||
|
|
||||||
|
let parsed_tree = parse(lexed_tokens, &mut panic_on_error);
|
||||||
|
println!("{}", serde_json::to_string(&parsed_tree).unwrap());
|
||||||
|
let expected_tree: Box<ParsedStatement> =
|
||||||
|
serde_json::from_str(r#"{
|
||||||
|
"Script": {
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"ClassDeclaration": {
|
||||||
|
"modifiers": 0,
|
||||||
|
"name": "Foo",
|
||||||
|
"inherits": [
|
||||||
|
"Zom",
|
||||||
|
"Aar",
|
||||||
|
"Bar"
|
||||||
|
],
|
||||||
|
"statements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"#).unwrap();
|
||||||
|
assert_eq!(parsed_tree, expected_tree);
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"token_type": "ClassKeyword",
|
||||||
|
"span": {
|
||||||
|
"start": 0,
|
||||||
|
"end": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 5,
|
||||||
|
"end": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Foo"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 6,
|
||||||
|
"end": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 9,
|
||||||
|
"end": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "OpenCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 10,
|
||||||
|
"end": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "CloseCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 11,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "EndOfFile",
|
||||||
|
"span": {
|
||||||
|
"start": 12,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"Script": {
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"ClassDeclaration": {
|
||||||
|
"modifiers": 0,
|
||||||
|
"name": "Foo",
|
||||||
|
"inherits": [],
|
||||||
|
"statements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
class Foo {}
|
|
@ -0,0 +1,129 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"token_type": "ClassKeyword",
|
||||||
|
"span": {
|
||||||
|
"start": 0,
|
||||||
|
"end": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 5,
|
||||||
|
"end": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Foo"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 6,
|
||||||
|
"end": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 9,
|
||||||
|
"end": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Colon",
|
||||||
|
"span": {
|
||||||
|
"start": 10,
|
||||||
|
"end": 11
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 11,
|
||||||
|
"end": 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Zom"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 12,
|
||||||
|
"end": 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Comma",
|
||||||
|
"span": {
|
||||||
|
"start": 15,
|
||||||
|
"end": 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 16,
|
||||||
|
"end": 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Aar"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 17,
|
||||||
|
"end": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "Comma",
|
||||||
|
"span": {
|
||||||
|
"start": 20,
|
||||||
|
"end": 21
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 21,
|
||||||
|
"end": 22
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": {
|
||||||
|
"Identifier": "Bar"
|
||||||
|
},
|
||||||
|
"span": {
|
||||||
|
"start": 22,
|
||||||
|
"end": 25
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "WhiteSpace",
|
||||||
|
"span": {
|
||||||
|
"start": 25,
|
||||||
|
"end": 26
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "OpenCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 26,
|
||||||
|
"end": 27
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "CloseCurlyBracket",
|
||||||
|
"span": {
|
||||||
|
"start": 27,
|
||||||
|
"end": 28
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"token_type": "EndOfFile",
|
||||||
|
"span": {
|
||||||
|
"start": 28,
|
||||||
|
"end": 28
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"Script": {
|
||||||
|
"statements": [
|
||||||
|
{
|
||||||
|
"ClassDeclaration": {
|
||||||
|
"modifiers": 0,
|
||||||
|
"name": "Foo",
|
||||||
|
"inherits": [
|
||||||
|
"Zom",
|
||||||
|
"Aar",
|
||||||
|
"Bar"
|
||||||
|
],
|
||||||
|
"statements": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
class Foo : Zom, Aar, Bar {}
|
|
@ -11,6 +11,7 @@ pub enum TypeModifier {
|
||||||
Shared = 0x02,
|
Shared = 0x02,
|
||||||
Abstract = 0x04,
|
Abstract = 0x04,
|
||||||
Final = 0x08,
|
Final = 0x08,
|
||||||
|
Mixin = 0x10,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bitflags]
|
#[bitflags]
|
||||||
|
|
|
@ -163,16 +163,15 @@ fn parse_script(
|
||||||
vec.push(*parse_namespace(reader, log));
|
vec.push(*parse_namespace(reader, log));
|
||||||
}
|
}
|
||||||
TokenType::InterfaceKeyword => vec.push(*parse_interface(reader, log).unwrap()),
|
TokenType::InterfaceKeyword => vec.push(*parse_interface(reader, log).unwrap()),
|
||||||
|
TokenType::EnumKeyword => vec.push(*parse_enum(reader, log).unwrap()),
|
||||||
TokenType::EndOfFile => break,
|
TokenType::EndOfFile => break,
|
||||||
TokenType::CloseCurlyBracket => break,
|
TokenType::CloseCurlyBracket => break,
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(s) = parse_enum(reader, log) {
|
if let Some(s) = parse_enum(reader, log) {
|
||||||
vec.push(*s);
|
vec.push(*s);
|
||||||
}
|
} else if let Some(s) = parse_class(reader, log) {
|
||||||
// else if let Some(s) = parse_class(reader, log) {
|
vec.push(*s);
|
||||||
// vec.push(*s);
|
} else if let Some(s) = parse_interface(reader, log) {
|
||||||
// }
|
|
||||||
else if let Some(s) = parse_interface(reader, log) {
|
|
||||||
vec.push(*s);
|
vec.push(*s);
|
||||||
} else if let Some(s) = parse_virtprop(reader, log) {
|
} else if let Some(s) = parse_virtprop(reader, log) {
|
||||||
vec.push(*s);
|
vec.push(*s);
|
||||||
|
@ -219,6 +218,8 @@ fn parse_interface(
|
||||||
outer_reader: &mut ParseReader,
|
outer_reader: &mut ParseReader,
|
||||||
log: &mut dyn FnMut(Message, Span),
|
log: &mut dyn FnMut(Message, Span),
|
||||||
) -> Option<Box<ParsedStatement>> {
|
) -> Option<Box<ParsedStatement>> {
|
||||||
|
// interface ::= {'external' | 'shared'} 'interface' identifier (';' | ([':' identifier {',' identifier}] '{' {virtprop | interfacemethod} '}'));
|
||||||
|
|
||||||
let mut type_mod: BitFlags<TypeModifier> = BitFlags::empty();
|
let mut type_mod: BitFlags<TypeModifier> = BitFlags::empty();
|
||||||
let identifier: Option<String>;
|
let identifier: Option<String>;
|
||||||
let mut has_interface_keyword = false;
|
let mut has_interface_keyword = false;
|
||||||
|
@ -304,15 +305,17 @@ fn parse_interface(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.consume(TokenType::OpenCurlyBracket, log);
|
reader.consume(TokenType::OpenCurlyBracket, log);
|
||||||
// TODO: parse interfacemethod
|
|
||||||
loop {
|
loop {
|
||||||
if reader.peek().token_type == TokenType::CloseCurlyBracket {
|
if reader.peek().token_type == TokenType::CloseCurlyBracket {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let prop = parse_virtprop(&mut reader, log);
|
let mut prop = parse_virtprop(&mut reader, log);
|
||||||
|
if prop.is_none() {
|
||||||
|
prop = parse_interface_method(&mut reader, log);
|
||||||
if prop.is_none() {
|
if prop.is_none() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
statements.push(*prop.unwrap());
|
statements.push(*prop.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,27 +340,22 @@ fn parse_interface_method(
|
||||||
// interfacemethod ::= type ['&'] identifier paramlist ['const'] ';';
|
// interfacemethod ::= type ['&'] identifier paramlist ['const'] ';';
|
||||||
let mut reader = outer_reader.create_inner();
|
let mut reader = outer_reader.create_inner();
|
||||||
let return_type = parse_type(&mut reader, log);
|
let return_type = parse_type(&mut reader, log);
|
||||||
if return_type.is_none() {
|
return_type.as_ref()?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let returns_reference = reader.peek().token_type == TokenType::Ampersand;
|
let returns_reference = reader.peek().token_type == TokenType::Ampersand;
|
||||||
if returns_reference {
|
if returns_reference {
|
||||||
reader.next();
|
reader.next();
|
||||||
}
|
}
|
||||||
let identifier = parse_identifier(&mut reader, log, true);
|
let identifier = parse_identifier(&mut reader, log, true);
|
||||||
if identifier.is_none() {
|
identifier.as_ref()?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let param_list = parse_paramlist(&mut reader, log);
|
let param_list = parse_paramlist(&mut reader, log);
|
||||||
if param_list.is_none() {
|
param_list.as_ref()?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let is_const = reader.peek().token_type == TokenType::ConstKeyword;
|
let is_const = reader.peek().token_type == TokenType::ConstKeyword;
|
||||||
if is_const {
|
if is_const {
|
||||||
reader.next();
|
reader.next();
|
||||||
}
|
}
|
||||||
reader.consume(TokenType::Semicolon, log);
|
reader.consume(TokenType::Semicolon, log);
|
||||||
|
|
||||||
|
outer_reader.set_from_inner(&reader);
|
||||||
Some(Box::new(ParsedStatement::InterfaceMethod {
|
Some(Box::new(ParsedStatement::InterfaceMethod {
|
||||||
return_type: return_type.unwrap(),
|
return_type: return_type.unwrap(),
|
||||||
returns_reference,
|
returns_reference,
|
||||||
|
@ -379,16 +377,14 @@ fn parse_typedef(
|
||||||
let mut left_type = parse_primtype(reader, log);
|
let mut left_type = parse_primtype(reader, log);
|
||||||
if left_type.is_none() {
|
if left_type.is_none() {
|
||||||
let left_type_identifier = parse_identifier(reader, log, false);
|
let left_type_identifier = parse_identifier(reader, log, false);
|
||||||
if left_type_identifier.is_some() {
|
if let Some(s) = left_type_identifier {
|
||||||
left_type = Some(Box::new(ParsedStatement::DataTypeIdentifier {
|
left_type = Some(Box::new(ParsedStatement::DataTypeIdentifier {
|
||||||
identifier: left_type_identifier.unwrap(),
|
identifier: s,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let right_type_identifier = parse_identifier(reader, log, false);
|
let right_type_identifier = parse_identifier(reader, log, false);
|
||||||
if right_type_identifier.is_none() {
|
right_type_identifier.as_ref()?;
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let right_type = Box::new(ParsedStatement::DataTypeIdentifier {
|
let right_type = Box::new(ParsedStatement::DataTypeIdentifier {
|
||||||
identifier: right_type_identifier.unwrap(),
|
identifier: right_type_identifier.unwrap(),
|
||||||
});
|
});
|
||||||
|
@ -531,20 +527,156 @@ fn parse_enum(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_class(
|
fn parse_class(
|
||||||
_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>> {
|
||||||
// class ::= {'shared' | 'abstract' | 'final' | 'external' | 'mixin'} 'class' identifier
|
// class ::= {'shared' | 'abstract' | 'final' | 'external' | 'mixin'} 'class' identifier
|
||||||
// (';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef | class} '}'));
|
// (';' | ([':' identifier {',' identifier}] '{' {virtprop | func | var | funcdef | class} '}'));
|
||||||
unimplemented!();
|
let mut inner_reader = reader.create_inner();
|
||||||
|
let mut modifiers: BitFlags<TypeModifier> = BitFlags::empty();
|
||||||
|
loop {
|
||||||
|
match inner_reader.peek().token_type {
|
||||||
|
TokenType::SharedKeyword => {
|
||||||
|
inner_reader.next();
|
||||||
|
modifiers |= TypeModifier::Shared;
|
||||||
|
}
|
||||||
|
TokenType::AbstractKeyword => {
|
||||||
|
inner_reader.next();
|
||||||
|
modifiers |= TypeModifier::Abstract;
|
||||||
|
}
|
||||||
|
TokenType::FinalKeyword => {
|
||||||
|
inner_reader.next();
|
||||||
|
modifiers |= TypeModifier::Final;
|
||||||
|
}
|
||||||
|
TokenType::ExternalKeyword => {
|
||||||
|
inner_reader.next();
|
||||||
|
modifiers |= TypeModifier::External;
|
||||||
|
}
|
||||||
|
TokenType::MixinKeyword => {
|
||||||
|
inner_reader.next();
|
||||||
|
modifiers |= TypeModifier::Mixin;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if inner_reader.peek().token_type != TokenType::ClassKeyword {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
inner_reader.next();
|
||||||
|
reader.set_from_inner(&inner_reader);
|
||||||
|
|
||||||
|
let name = parse_identifier(reader, log, false);
|
||||||
|
|
||||||
|
// (';' |
|
||||||
|
// (
|
||||||
|
// [':' identifier {',' identifier}]
|
||||||
|
// '{' {virtprop | func | var | funcdef | class} '}'
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
|
||||||
|
// FIXME: Do we need predeclaring class (class foo;)?
|
||||||
|
|
||||||
|
let mut inherits = Vec::new();
|
||||||
|
|
||||||
|
if reader.peek().token_type == TokenType::Colon {
|
||||||
|
reader.next();
|
||||||
|
loop {
|
||||||
|
let inherit = parse_identifier(reader, log, false);
|
||||||
|
if let Some(s) = inherit {
|
||||||
|
inherits.push(s);
|
||||||
|
}
|
||||||
|
if reader.peek().token_type != TokenType::Comma {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.consume(TokenType::OpenCurlyBracket, log);
|
||||||
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut statement = parse_virtprop(reader, log);
|
||||||
|
if statement.is_none() {
|
||||||
|
statement = parse_func(reader, log);
|
||||||
|
if statement.is_none() {
|
||||||
|
statement = parse_var(reader, log);
|
||||||
|
if statement.is_none() {
|
||||||
|
statement = parse_funcdef(reader, log);
|
||||||
|
if statement.is_none() {
|
||||||
|
statement = parse_class(reader, log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(s) = statement {
|
||||||
|
statements.push(s);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.consume(TokenType::CloseCurlyBracket, log);
|
||||||
|
|
||||||
|
Some(Box::new(ParsedStatement::ClassDeclaration {
|
||||||
|
modifiers,
|
||||||
|
name: name.unwrap(),
|
||||||
|
inherits,
|
||||||
|
statements,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_funcdef(
|
fn parse_funcdef(
|
||||||
_outer_reader: &mut ParseReader,
|
outer_reader: &mut ParseReader,
|
||||||
_log: &mut dyn FnMut(Message, Span),
|
log: &mut dyn FnMut(Message, Span),
|
||||||
) -> Option<Box<ParsedStatement>> {
|
) -> Option<Box<ParsedStatement>> {
|
||||||
// funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
|
// funcdef ::= {'external' | 'shared'} 'funcdef' type ['&'] identifier paramlist ';'
|
||||||
unimplemented!();
|
let mut reader = outer_reader.create_inner();
|
||||||
|
let mut modifiers: BitFlags<TypeModifier> = BitFlags::empty();
|
||||||
|
loop {
|
||||||
|
match reader.peek().token_type {
|
||||||
|
TokenType::SharedKeyword => {
|
||||||
|
reader.next();
|
||||||
|
modifiers |= TypeModifier::Shared;
|
||||||
|
}
|
||||||
|
TokenType::ExternalKeyword => {
|
||||||
|
reader.next();
|
||||||
|
modifiers |= TypeModifier::External;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if reader.peek().token_type != TokenType::FuncDefKeyword {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
reader.next();
|
||||||
|
let return_type = parse_type(&mut reader, log);
|
||||||
|
return_type.as_ref()?;
|
||||||
|
let returns_reference = reader.peek().token_type == TokenType::Ampersand;
|
||||||
|
if returns_reference {
|
||||||
|
reader.next();
|
||||||
|
}
|
||||||
|
let identifier = parse_identifier(&mut reader, log, true);
|
||||||
|
identifier.as_ref()?;
|
||||||
|
let param_list = parse_paramlist(&mut reader, log);
|
||||||
|
param_list.as_ref()?;
|
||||||
|
if reader.peek().token_type != TokenType::Semicolon {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
reader.next();
|
||||||
|
|
||||||
|
outer_reader.set_from_inner(&reader);
|
||||||
|
|
||||||
|
Some(Box::new(ParsedStatement::FuncDefDeclaration {
|
||||||
|
modifiers,
|
||||||
|
returns_reference,
|
||||||
|
return_type,
|
||||||
|
name: identifier.unwrap(),
|
||||||
|
param_list: param_list.unwrap(),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_func(
|
fn parse_func(
|
||||||
|
@ -788,7 +920,7 @@ fn parse_paramlist(
|
||||||
|
|
||||||
fn parse_funcattr(
|
fn parse_funcattr(
|
||||||
reader: &mut ParseReader,
|
reader: &mut ParseReader,
|
||||||
log: &mut dyn FnMut(Message, Span),
|
_log: &mut dyn FnMut(Message, Span),
|
||||||
) -> BitFlags<FuncAttr> {
|
) -> BitFlags<FuncAttr> {
|
||||||
// funcattr ::= {'override' | 'final' | 'explicit' | 'property'};
|
// funcattr ::= {'override' | 'final' | 'explicit' | 'property'};
|
||||||
let mut func_attr: BitFlags<FuncAttr> = BitFlags::empty();
|
let mut func_attr: BitFlags<FuncAttr> = BitFlags::empty();
|
||||||
|
@ -1067,8 +1199,8 @@ fn parse_for(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let assign = parse_assign(reader, log);
|
let assign = parse_assign(reader, log);
|
||||||
if assign.is_some() {
|
if let Some(s) = assign {
|
||||||
increment_expressions.push(assign.unwrap());
|
increment_expressions.push(s);
|
||||||
}
|
}
|
||||||
if reader.peek().token_type != TokenType::Comma {
|
if reader.peek().token_type != TokenType::Comma {
|
||||||
break;
|
break;
|
||||||
|
@ -1433,7 +1565,7 @@ fn parse_lambda(
|
||||||
|
|
||||||
fn parse_typemod(
|
fn parse_typemod(
|
||||||
reader: &mut ParseReader,
|
reader: &mut ParseReader,
|
||||||
log: &mut dyn FnMut(Message, Span),
|
_log: &mut dyn FnMut(Message, Span),
|
||||||
) -> Option<BitFlags<ReferenceModifier>> {
|
) -> Option<BitFlags<ReferenceModifier>> {
|
||||||
// typemod ::= ['&' ['in' | 'out' | 'inout']];
|
// typemod ::= ['&' ['in' | 'out' | 'inout']];
|
||||||
if reader.peek().token_type == TokenType::Ampersand {
|
if reader.peek().token_type == TokenType::Ampersand {
|
||||||
|
|
|
@ -224,4 +224,17 @@ pub enum ParsedStatement {
|
||||||
func_attr: BitFlags<FuncAttr>,
|
func_attr: BitFlags<FuncAttr>,
|
||||||
block: Option<Box<ParsedStatement>>,
|
block: Option<Box<ParsedStatement>>,
|
||||||
},
|
},
|
||||||
|
FuncDefDeclaration {
|
||||||
|
modifiers: BitFlags<TypeModifier>,
|
||||||
|
returns_reference: bool,
|
||||||
|
return_type: Option<Box<ParsedStatement>>,
|
||||||
|
name: String,
|
||||||
|
param_list: Box<ParsedStatement>,
|
||||||
|
},
|
||||||
|
ClassDeclaration {
|
||||||
|
modifiers: BitFlags<TypeModifier>,
|
||||||
|
name: String,
|
||||||
|
inherits: Vec<String>,
|
||||||
|
statements: Vec<Box<ParsedStatement>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue