|
|
|
@ -163,16 +163,15 @@ fn parse_script( |
|
|
|
|
vec.push(*parse_namespace(reader, log)); |
|
|
|
|
} |
|
|
|
|
TokenType::InterfaceKeyword => vec.push(*parse_interface(reader, log).unwrap()), |
|
|
|
|
TokenType::EnumKeyword => vec.push(*parse_enum(reader, log).unwrap()), |
|
|
|
|
TokenType::EndOfFile => break, |
|
|
|
|
TokenType::CloseCurlyBracket => break, |
|
|
|
|
_ => { |
|
|
|
|
if let Some(s) = parse_enum(reader, log) { |
|
|
|
|
vec.push(*s); |
|
|
|
|
} |
|
|
|
|
// else if let Some(s) = parse_class(reader, log) {
|
|
|
|
|
// vec.push(*s);
|
|
|
|
|
// }
|
|
|
|
|
else if let Some(s) = parse_interface(reader, log) { |
|
|
|
|
} else if let Some(s) = parse_class(reader, log) { |
|
|
|
|
vec.push(*s); |
|
|
|
|
} else if let Some(s) = parse_interface(reader, log) { |
|
|
|
|
vec.push(*s); |
|
|
|
|
} else if let Some(s) = parse_virtprop(reader, log) { |
|
|
|
|
vec.push(*s); |
|
|
|
@ -219,6 +218,8 @@ fn parse_interface( |
|
|
|
|
outer_reader: &mut ParseReader, |
|
|
|
|
log: &mut dyn FnMut(Message, Span), |
|
|
|
|
) -> Option<Box<ParsedStatement>> { |
|
|
|
|
// interface ::= {'external' | 'shared'} 'interface' identifier (';' | ([':' identifier {',' identifier}] '{' {virtprop | interfacemethod} '}'));
|
|
|
|
|
|
|
|
|
|
let mut type_mod: BitFlags<TypeModifier> = BitFlags::empty(); |
|
|
|
|
let identifier: Option<String>; |
|
|
|
|
let mut has_interface_keyword = false; |
|
|
|
@ -304,14 +305,16 @@ fn parse_interface( |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
reader.consume(TokenType::OpenCurlyBracket, log); |
|
|
|
|
// TODO: parse interfacemethod
|
|
|
|
|
loop { |
|
|
|
|
if reader.peek().token_type == TokenType::CloseCurlyBracket { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
let prop = parse_virtprop(&mut reader, log); |
|
|
|
|
let mut prop = parse_virtprop(&mut reader, log); |
|
|
|
|
if prop.is_none() { |
|
|
|
|
break; |
|
|
|
|
prop = parse_interface_method(&mut reader, log); |
|
|
|
|
if prop.is_none() { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
statements.push(*prop.unwrap()); |
|
|
|
|
} |
|
|
|
@ -337,27 +340,22 @@ fn parse_interface_method( |
|
|
|
|
// 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; |
|
|
|
|
} |
|
|
|
|
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); |
|
|
|
|
if identifier.is_none() { |
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|
identifier.as_ref()?; |
|
|
|
|
let param_list = parse_paramlist(&mut reader, log); |
|
|
|
|
if param_list.is_none() { |
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|
param_list.as_ref()?; |
|
|
|
|
let is_const = reader.peek().token_type == TokenType::ConstKeyword; |
|
|
|
|
if is_const { |
|
|
|
|
reader.next(); |
|
|
|
|
} |
|
|
|
|
reader.consume(TokenType::Semicolon, log); |
|
|
|
|
|
|
|
|
|
outer_reader.set_from_inner(&reader); |
|
|
|
|
Some(Box::new(ParsedStatement::InterfaceMethod { |
|
|
|
|
return_type: return_type.unwrap(), |
|
|
|
|
returns_reference, |
|
|
|
@ -379,16 +377,14 @@ fn parse_typedef( |
|
|
|
|
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() { |
|
|
|
|
if let Some(s) = left_type_identifier { |
|
|
|
|
left_type = Some(Box::new(ParsedStatement::DataTypeIdentifier { |
|
|
|
|
identifier: left_type_identifier.unwrap(), |
|
|
|
|
identifier: s, |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
let right_type_identifier = parse_identifier(reader, log, false); |
|
|
|
|
if right_type_identifier.is_none() { |
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|
right_type_identifier.as_ref()?; |
|
|
|
|
let right_type = Box::new(ParsedStatement::DataTypeIdentifier { |
|
|
|
|
identifier: right_type_identifier.unwrap(), |
|
|
|
|
}); |
|
|
|
@ -531,20 +527,156 @@ fn parse_enum( |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn parse_class( |
|
|
|
|
_outer_reader: &mut ParseReader, |
|
|
|
|
_log: &mut dyn FnMut(Message, Span), |
|
|
|
|
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!(); |
|
|
|
|
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( |
|
|
|
|
_outer_reader: &mut ParseReader, |
|
|
|
|
_log: &mut dyn FnMut(Message, Span), |
|
|
|
|
outer_reader: &mut ParseReader, |
|
|
|
|
log: &mut dyn FnMut(Message, Span), |
|
|
|
|
) -> Option<Box<ParsedStatement>> { |
|
|
|
|
// 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( |
|
|
|
@ -788,7 +920,7 @@ fn parse_paramlist( |
|
|
|
|
|
|
|
|
|
fn parse_funcattr( |
|
|
|
|
reader: &mut ParseReader, |
|
|
|
|
log: &mut dyn FnMut(Message, Span), |
|
|
|
|
_log: &mut dyn FnMut(Message, Span), |
|
|
|
|
) -> BitFlags<FuncAttr> { |
|
|
|
|
// funcattr ::= {'override' | 'final' | 'explicit' | 'property'};
|
|
|
|
|
let mut func_attr: BitFlags<FuncAttr> = BitFlags::empty(); |
|
|
|
@ -1067,8 +1199,8 @@ fn parse_for( |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
let assign = parse_assign(reader, log); |
|
|
|
|
if assign.is_some() { |
|
|
|
|
increment_expressions.push(assign.unwrap()); |
|
|
|
|
if let Some(s) = assign { |
|
|
|
|
increment_expressions.push(s); |
|
|
|
|
} |
|
|
|
|
if reader.peek().token_type != TokenType::Comma { |
|
|
|
|
break; |
|
|
|
@ -1433,7 +1565,7 @@ fn parse_lambda( |
|
|
|
|
|
|
|
|
|
fn parse_typemod( |
|
|
|
|
reader: &mut ParseReader, |
|
|
|
|
log: &mut dyn FnMut(Message, Span), |
|
|
|
|
_log: &mut dyn FnMut(Message, Span), |
|
|
|
|
) -> Option<BitFlags<ReferenceModifier>> { |
|
|
|
|
// typemod ::= ['&' ['in' | 'out' | 'inout']];
|
|
|
|
|
if reader.peek().token_type == TokenType::Ampersand { |
|
|
|
|