Thread Parser through peg rules to provide ID's
This commit is contained in:
parent
ba8fb86e3f
commit
869de8c033
@ -2,8 +2,12 @@ use std::rc::Rc;
|
||||
|
||||
//TODO make use of the format_parse_error function
|
||||
//use crate::error::{SchalaError, format_parse_error};
|
||||
use crate::parsing::ParseError;
|
||||
use crate::{ast::*, identifier::IdStore, schala::SourceReference};
|
||||
use crate::{
|
||||
ast::*,
|
||||
identifier::{Id, IdStore},
|
||||
parsing::ParseError,
|
||||
schala::SourceReference,
|
||||
};
|
||||
|
||||
fn rc_string(s: &str) -> Rc<String> {
|
||||
Rc::new(s.to_string())
|
||||
@ -18,8 +22,12 @@ impl Parser {
|
||||
Self { id_store: IdStore::new() }
|
||||
}
|
||||
|
||||
pub(crate) fn parse(input: &str, _source_reference: &SourceReference) -> Result<AST, ParseError> {
|
||||
schala_parser::program(input).map_err(|err: peg::error::ParseError<_>| {
|
||||
pub(crate) fn parse(
|
||||
&mut self,
|
||||
input: &str,
|
||||
_source_reference: &SourceReference,
|
||||
) -> Result<AST, ParseError> {
|
||||
schala_parser::program(input, self).map_err(|err: peg::error::ParseError<_>| {
|
||||
let msg = err.to_string();
|
||||
ParseError {
|
||||
production_name: Some("some-production".to_string()),
|
||||
@ -31,6 +39,10 @@ impl Parser {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn fresh(&mut self) -> Id<ASTItem> {
|
||||
self.id_store.fresh()
|
||||
}
|
||||
}
|
||||
|
||||
enum ExtendedPart<'a> {
|
||||
@ -53,37 +65,37 @@ peg::parser! {
|
||||
rule line_comment() = "//" (!['\n'] [_])* &"\n"
|
||||
|
||||
|
||||
pub rule program() -> AST =
|
||||
__ statements:(statement() ** delimiter() ) __ { AST { id: Default::default(), statements: statements.into() } }
|
||||
pub rule program(parser: &mut Parser) -> AST =
|
||||
__ statements:(statement(parser) ** delimiter() ) __ { AST { id: Default::default(), statements: statements.into() } }
|
||||
|
||||
rule delimiter() = (";" / "\n")+
|
||||
|
||||
//Note - this is a hack, ideally the rule `rule block() -> Block = "{" _ items:(statement() **
|
||||
//delimiter()) _ "}" { items.into() }` would've worked, but it doesn't.
|
||||
pub rule block() -> Block = "{" __ items:block_item()* __ "}" { items.into() } /
|
||||
"{" __ stmt:statement() __ "}" { vec![stmt].into() }
|
||||
pub rule block(parser: &mut Parser) -> Block = "{" __ items:block_item(parser)* __ "}" { items.into() } /
|
||||
"{" __ stmt:statement(parser) __ "}" { vec![stmt].into() }
|
||||
|
||||
rule block_item() -> Statement =
|
||||
stmt:statement() delimiter()+ { stmt }
|
||||
rule block_item(parser: &mut Parser) -> Statement =
|
||||
stmt:statement(parser) delimiter()+ { stmt }
|
||||
|
||||
rule statement() -> Statement =
|
||||
_ pos:position!() kind:statement_kind() _ { Statement { id: Default::default(), location: pos.into(), kind } }
|
||||
rule statement(parser: &mut Parser) -> Statement =
|
||||
_ pos:position!() kind:statement_kind(parser) _ { Statement { id: parser.fresh(), location: pos.into(), kind } }
|
||||
|
||||
rule statement_kind() -> StatementKind =
|
||||
__ import:import() { StatementKind::Import(import) } /
|
||||
__ decl:declaration() { StatementKind::Declaration(decl) } /
|
||||
__ flow:flow() { StatementKind::Flow(flow) } /
|
||||
__ expr:expression() { StatementKind::Expression(expr) }
|
||||
rule statement_kind(parser: &mut Parser) -> StatementKind =
|
||||
__ import:import(parser) { StatementKind::Import(import) } /
|
||||
__ decl:declaration(parser) { StatementKind::Declaration(decl) } /
|
||||
__ flow:flow(parser) { StatementKind::Flow(flow) } /
|
||||
__ expr:expression(parser) { StatementKind::Expression(expr) }
|
||||
|
||||
rule flow() -> FlowControl =
|
||||
rule flow(parser: &mut Parser) -> FlowControl =
|
||||
"continue" { FlowControl::Continue } /
|
||||
"break" { FlowControl::Break } /
|
||||
"return" _ expr:expression()? { FlowControl::Return(expr) }
|
||||
"return" _ expr:expression(parser)? { FlowControl::Return(expr) }
|
||||
|
||||
rule import() -> ImportSpecifier =
|
||||
rule import(parser: &mut Parser) -> ImportSpecifier =
|
||||
"import" _ path_components:path_components() suffix:import_suffix()? {
|
||||
ImportSpecifier {
|
||||
id: Default::default(),
|
||||
id: parser.fresh(),
|
||||
path_components,
|
||||
imported_names: suffix.unwrap_or_else(|| ImportedNames::LastOfPath)
|
||||
}
|
||||
@ -103,64 +115,66 @@ peg::parser! {
|
||||
"::{" __ names:(identifier() ** (_ "," _)) __ "}" { ImportedNames::List(names.into_iter().map(rc_string).collect()) }
|
||||
|
||||
|
||||
rule declaration() -> Declaration =
|
||||
binding() / type_decl() / annotation() / func() / interface() / implementation() / module()
|
||||
rule declaration(parser: &mut Parser) -> Declaration =
|
||||
binding(parser) / type_decl() / annotation(parser) / func(parser) / interface(parser) /
|
||||
implementation(parser) / module(parser)
|
||||
|
||||
rule module() -> Declaration =
|
||||
"module" _ name:identifier() _ items:block() { Declaration::Module { name: rc_string(name), items } }
|
||||
rule module(parser: &mut Parser) -> Declaration =
|
||||
"module" _ name:identifier() _ items:block(parser) { Declaration::Module { name: rc_string(name), items } }
|
||||
|
||||
rule implementation() -> Declaration =
|
||||
"impl" _ interface:type_singleton_name() _ "for" _ type_name:type_identifier() _ block:decl_block() {
|
||||
rule implementation(parser: &mut Parser) -> Declaration =
|
||||
"impl" _ interface:type_singleton_name() _ "for" _ type_name:type_identifier() _ block:decl_block(parser) {
|
||||
Declaration::Impl { type_name, interface_name: Some(interface), block }
|
||||
|
||||
} /
|
||||
"impl" _ type_name:type_identifier() _ block:decl_block() {
|
||||
"impl" _ type_name:type_identifier() _ block:decl_block(parser) {
|
||||
Declaration::Impl { type_name, interface_name: None, block }
|
||||
}
|
||||
|
||||
rule decl_block() -> Vec<Declaration> =
|
||||
"{" __ decls:(func_declaration() ** (delimiter()+)) __ "}" { decls }
|
||||
rule decl_block(parser: &mut Parser) -> Vec<Declaration> =
|
||||
"{" __ decls:(func_declaration(parser) ** (delimiter()+)) __ "}" { decls }
|
||||
|
||||
rule interface() -> Declaration =
|
||||
"interface" _ name:identifier() _ signatures:signature_block() { Declaration::Interface { name: rc_string(name), signatures } }
|
||||
rule interface(parser: &mut Parser) -> Declaration =
|
||||
"interface" _ name:identifier() _ signatures:signature_block(parser) { Declaration::Interface { name: rc_string(name), signatures } }
|
||||
|
||||
rule signature_block() -> Vec<Signature> =
|
||||
"{" __ signatures:(func_signature() ** (delimiter()+)) __ "}" { signatures }
|
||||
rule signature_block(parser: &mut Parser) -> Vec<Signature> =
|
||||
"{" __ signatures:(func_signature(parser) ** (delimiter()+)) __ "}" { signatures }
|
||||
|
||||
rule func() -> Declaration =
|
||||
decl:func_declaration() { decl } /
|
||||
sig:func_signature() { Declaration::FuncSig(sig) }
|
||||
rule func(parser: &mut Parser) -> Declaration =
|
||||
decl:func_declaration(parser) { decl } /
|
||||
sig:func_signature(parser) { Declaration::FuncSig(sig) }
|
||||
|
||||
rule func_declaration() -> Declaration =
|
||||
_ sig:func_signature() __ body:block() { Declaration::FuncDecl(sig, body) }
|
||||
rule func_declaration(parser: &mut Parser) -> Declaration =
|
||||
_ sig:func_signature(parser) __ body:block(parser) { Declaration::FuncDecl(sig, body) }
|
||||
|
||||
//TODO handle operators
|
||||
rule func_signature() -> Signature =
|
||||
_ "fn" _ name:identifier() "(" _ params:formal_params() _ ")" _ type_anno:type_anno()? { Signature {
|
||||
rule func_signature(parser: &mut Parser) -> Signature =
|
||||
_ "fn" _ name:identifier() "(" _ params:formal_params(parser) _ ")" _ type_anno:type_anno()? { Signature {
|
||||
name: rc_string(name), operator: false, params, type_anno
|
||||
} }
|
||||
|
||||
rule formal_params() -> Vec<FormalParam> = params:(formal_param() ** (_ "," _)) {? if params.len() < 256 { Ok(params) } else {
|
||||
rule formal_params(parser: &mut Parser) -> Vec<FormalParam> =
|
||||
params:(formal_param(parser) ** (_ "," _)) {? if params.len() < 256 { Ok(params) } else {
|
||||
Err("function-too-long") }
|
||||
}
|
||||
|
||||
rule formal_param() -> FormalParam =
|
||||
name:identifier() _ anno:type_anno()? _ "=" expr:expression() { FormalParam { name: rc_string(name),
|
||||
rule formal_param(parser: &mut Parser) -> FormalParam =
|
||||
name:identifier() _ anno:type_anno()? _ "=" expr:expression(parser) { FormalParam { name: rc_string(name),
|
||||
default: Some(expr), anno } } /
|
||||
name:identifier() _ anno:type_anno()? { FormalParam { name: rc_string(name), default: None, anno } }
|
||||
|
||||
|
||||
rule annotation() -> Declaration =
|
||||
"@" name:identifier() args:annotation_args()? delimiter()+ _ inner:statement() { Declaration::Annotation {
|
||||
rule annotation(parser: &mut Parser) -> Declaration =
|
||||
"@" name:identifier() args:annotation_args(parser)? delimiter()+ _ inner:statement(parser) { Declaration::Annotation {
|
||||
name: rc_string(name), arguments: if let Some(args) = args { args } else { vec![] }, inner: Box::new(inner) }
|
||||
}
|
||||
|
||||
rule annotation_args() -> Vec<Expression> =
|
||||
"(" _ args:(expression() ** (_ "," _)) _ ")" { args }
|
||||
rule annotation_args(parser: &mut Parser) -> Vec<Expression> =
|
||||
"(" _ args:(expression(parser) ** (_ "," _)) _ ")" { args }
|
||||
|
||||
|
||||
rule binding() -> Declaration =
|
||||
"let" _ mutable:"mut"? _ ident:identifier() _ type_anno:type_anno()? _ "=" _ expr:expression() {
|
||||
rule binding(parser: &mut Parser) -> Declaration =
|
||||
"let" _ mutable:"mut"? _ ident:identifier() _ type_anno:type_anno()? _ "=" _ expr:expression(parser) {
|
||||
Declaration::Binding { name: Rc::new(ident.to_string()), constant: mutable.is_none(),
|
||||
type_anno, expr }
|
||||
}
|
||||
@ -203,31 +217,28 @@ peg::parser! {
|
||||
rule type_anno() -> TypeIdentifier =
|
||||
":" _ identifier:type_identifier() { identifier }
|
||||
|
||||
pub rule expression() -> Expression =
|
||||
__ kind:expression_kind() _ type_anno:type_anno()? { Expression { id: Default::default(), type_anno, kind } }
|
||||
pub rule expression(parser: &mut Parser) -> Expression =
|
||||
__ kind:expression_kind(true, parser) _ type_anno:type_anno()? { Expression { id: parser.fresh(), type_anno, kind } }
|
||||
|
||||
rule expression_no_struct() -> Expression =
|
||||
__ kind:expression_kind_no_struct() { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||
rule expression_no_struct(parser: &mut Parser) -> Expression =
|
||||
__ kind:expression_kind(false, parser) { Expression { id: Default::default(), type_anno: None, kind: kind } }
|
||||
|
||||
rule expression_kind() -> ExpressionKind =
|
||||
precedence_expr(true)
|
||||
rule expression_kind(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
precedence_expr(struct_ok, parser)
|
||||
|
||||
rule expression_kind_no_struct() -> ExpressionKind =
|
||||
precedence_expr(false)
|
||||
|
||||
rule precedence_expr(struct_ok: bool) -> ExpressionKind =
|
||||
first:prefix_expr(struct_ok) _ next:(precedence_continuation(struct_ok))* {
|
||||
rule precedence_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
first:prefix_expr(struct_ok, parser) _ next:(precedence_continuation(struct_ok, parser))* {
|
||||
let next = next.into_iter().map(|(sigil, expr)| (BinOp::from_sigil(sigil), expr)).collect();
|
||||
BinopSequence { first, next }.do_precedence()
|
||||
}
|
||||
|
||||
rule precedence_continuation(struct_ok: bool) -> (&'input str, ExpressionKind) =
|
||||
op:operator() _ expr:prefix_expr(struct_ok) _ { (op, expr) }
|
||||
rule precedence_continuation(struct_ok: bool, parser: &mut Parser) -> (&'input str, ExpressionKind) =
|
||||
op:operator() _ expr:prefix_expr(struct_ok, parser) _ { (op, expr) }
|
||||
|
||||
rule prefix_expr(struct_ok: bool) -> ExpressionKind =
|
||||
prefix:prefix()? expr:extended_expr(struct_ok) {
|
||||
rule prefix_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
prefix:prefix()? expr:extended_expr(struct_ok, parser) {
|
||||
if let Some(p) = prefix {
|
||||
let expr = Expression::new(Default::default(), expr);
|
||||
let expr = Expression::new(parser.fresh(), expr);
|
||||
let prefix = PrefixOp::from_sigil(p);
|
||||
ExpressionKind::PrefixExp(prefix, Box::new(expr))
|
||||
} else {
|
||||
@ -244,8 +255,8 @@ peg::parser! {
|
||||
quiet!{!"*/" s:$( ['+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '!' | '$' | '&' | '|' | '?' | '^' | '`']+ ) { s } } /
|
||||
expected!("operator")
|
||||
|
||||
rule extended_expr(struct_ok: bool) -> ExpressionKind =
|
||||
primary:primary(struct_ok) parts:(extended_expr_part()*) {
|
||||
rule extended_expr(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
primary:primary(struct_ok, parser) parts:(extended_expr_part(parser)*) {
|
||||
let mut expression = Expression::new(Default::default(), primary);
|
||||
for part in parts.into_iter() {
|
||||
let kind = match part {
|
||||
@ -261,72 +272,73 @@ peg::parser! {
|
||||
}
|
||||
};
|
||||
|
||||
expression = Expression::new(Default::default(), kind);
|
||||
expression = Expression::new(parser.fresh(), kind);
|
||||
}
|
||||
|
||||
expression.kind
|
||||
}
|
||||
|
||||
rule extended_expr_part() -> ExtendedPart<'input> =
|
||||
indexers:index_part() { ExtendedPart::Index(indexers) } /
|
||||
arguments:call_part() { ExtendedPart::Call(arguments) } /
|
||||
rule extended_expr_part(parser: &mut Parser) -> ExtendedPart<'input> =
|
||||
indexers:index_part(parser) { ExtendedPart::Index(indexers) } /
|
||||
arguments:call_part(parser) { ExtendedPart::Call(arguments) } /
|
||||
"." name:identifier() { ExtendedPart::Accessor(name) }
|
||||
|
||||
rule index_part() -> Vec<Expression> =
|
||||
"[" indexers:(expression() ++ ",") "]" { indexers }
|
||||
rule index_part(parser: &mut Parser) -> Vec<Expression> =
|
||||
"[" indexers:(expression(parser) ++ ",") "]" { indexers }
|
||||
|
||||
rule call_part() -> Vec<InvocationArgument> =
|
||||
"(" arguments:(invocation_argument() ** ",") ")" { arguments }
|
||||
rule call_part(parser: &mut Parser) -> Vec<InvocationArgument> =
|
||||
"(" arguments:(invocation_argument(parser) ** ",") ")" { arguments }
|
||||
|
||||
//TODO this shouldn't be an expression b/c type annotations disallowed here
|
||||
rule invocation_argument() -> InvocationArgument =
|
||||
rule invocation_argument(parser: &mut Parser) -> InvocationArgument =
|
||||
_ "_" _ { InvocationArgument::Ignored } /
|
||||
_ ident:identifier() _ "=" _ expr:expression() { InvocationArgument::Keyword {
|
||||
_ ident:identifier() _ "=" _ expr:expression(parser) { InvocationArgument::Keyword {
|
||||
name: Rc::new(ident.to_string()),
|
||||
expr
|
||||
} } /
|
||||
_ expr:expression() _ { InvocationArgument::Positional(expr) }
|
||||
_ expr:expression(parser) _ { InvocationArgument::Positional(expr) }
|
||||
|
||||
|
||||
rule primary(struct_ok: bool) -> ExpressionKind =
|
||||
while_expr() / for_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() /
|
||||
list_expr() / if_expr() / lambda_expr() /
|
||||
item:named_struct() {? if struct_ok { Ok(item) } else { Err("no-struct-allowed") } } /
|
||||
identifier_expr()
|
||||
rule primary(struct_ok: bool, parser: &mut Parser) -> ExpressionKind =
|
||||
while_expr(parser) / for_expr(parser) / float_literal() / nat_literal() / bool_literal() /
|
||||
string_literal() / paren_expr(parser) /
|
||||
list_expr(parser) / if_expr(parser) / lambda_expr(parser) /
|
||||
item:named_struct(parser) {? if struct_ok { Ok(item) } else { Err("no-struct-allowed") } } /
|
||||
identifier_expr(parser)
|
||||
|
||||
rule lambda_expr() -> ExpressionKind =
|
||||
r#"\"# __ "(" _ params:formal_params() _ ")" _ type_anno:(type_anno()?) _ body:block() {
|
||||
rule lambda_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
r#"\"# __ "(" _ params:formal_params(parser) _ ")" _ type_anno:(type_anno()?) _ body:block(parser) {
|
||||
ExpressionKind::Lambda { params, type_anno, body }
|
||||
} /
|
||||
r#"\"# param:formal_param() _ type_anno:(type_anno()?) _ body:block() {
|
||||
r#"\"# param:formal_param(parser) _ type_anno:(type_anno()?) _ body:block(parser) {
|
||||
ExpressionKind::Lambda { params: vec![param], type_anno, body }
|
||||
}
|
||||
|
||||
rule for_expr() -> ExpressionKind =
|
||||
"for" _ enumerators:for_enumerators() _ body:for_body() {
|
||||
rule for_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"for" _ enumerators:for_enumerators(parser) _ body:for_body(parser) {
|
||||
ExpressionKind::ForExpression { enumerators, body }
|
||||
}
|
||||
|
||||
rule for_enumerators() -> Vec<Enumerator> =
|
||||
"{" _ enumerators:(enumerator() ++ ",") _ "}" { enumerators } /
|
||||
enumerator:enumerator() { vec![enumerator] }
|
||||
rule for_enumerators(parser: &mut Parser) -> Vec<Enumerator> =
|
||||
"{" _ enumerators:(enumerator(parser) ++ ",") _ "}" { enumerators } /
|
||||
enumerator:enumerator(parser) { vec![enumerator] }
|
||||
|
||||
//TODO add guards, etc.
|
||||
rule enumerator() -> Enumerator =
|
||||
ident:identifier() _ "<-" _ generator:expression_no_struct() {
|
||||
rule enumerator(parser: &mut Parser) -> Enumerator =
|
||||
ident:identifier() _ "<-" _ generator:expression_no_struct(parser) {
|
||||
Enumerator { id: Rc::new(ident.to_string()), generator }
|
||||
} /
|
||||
//TODO need to distinguish these two cases in AST
|
||||
ident:identifier() _ "=" _ generator:expression_no_struct() {
|
||||
ident:identifier() _ "=" _ generator:expression_no_struct(parser) {
|
||||
Enumerator { id: Rc::new(ident.to_string()), generator }
|
||||
}
|
||||
|
||||
rule for_body() -> Box<ForBody> =
|
||||
"return" _ expr:expression() { Box::new(ForBody::MonadicReturn(expr)) } /
|
||||
body:block() { Box::new(ForBody::StatementBlock(body)) }
|
||||
rule for_body(parser: &mut Parser) -> Box<ForBody> =
|
||||
"return" _ expr:expression(parser) { Box::new(ForBody::MonadicReturn(expr)) } /
|
||||
body:block(parser) { Box::new(ForBody::StatementBlock(body)) }
|
||||
|
||||
rule while_expr() -> ExpressionKind =
|
||||
"while" _ cond:expression_kind_no_struct()? _ body:block() {
|
||||
rule while_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"while" _ cond:expression_kind(false, parser)? _ body:block(parser) {
|
||||
ExpressionKind::WhileExpression {
|
||||
condition: cond.map(|kind| Box::new(Expression::new(Default::default(), kind))),
|
||||
body,
|
||||
@ -334,11 +346,11 @@ peg::parser! {
|
||||
}
|
||||
|
||||
|
||||
rule identifier_expr() -> ExpressionKind =
|
||||
qn:qualified_identifier() { ExpressionKind::Value(qn) }
|
||||
rule identifier_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
qn:qualified_identifier(parser) { ExpressionKind::Value(qn) }
|
||||
|
||||
rule named_struct() -> ExpressionKind =
|
||||
name:qualified_identifier() _ fields:record_block() {
|
||||
rule named_struct(parser: &mut Parser) -> ExpressionKind =
|
||||
name:qualified_identifier(parser) _ fields:record_block(parser) {
|
||||
ExpressionKind::NamedStruct {
|
||||
name,
|
||||
fields: fields.into_iter().map(|(n, exp)| (Rc::new(n.to_string()), exp)).collect(),
|
||||
@ -347,14 +359,14 @@ peg::parser! {
|
||||
|
||||
|
||||
//TODO anonymous structs, update syntax for structs
|
||||
rule record_block() -> Vec<(&'input str, Expression)> =
|
||||
"{" _ entries:(record_entry() ** ",") _ "}" { entries }
|
||||
rule record_block(parser: &mut Parser) -> Vec<(&'input str, Expression)> =
|
||||
"{" _ entries:(record_entry(parser) ** ",") _ "}" { entries }
|
||||
|
||||
rule record_entry() -> (&'input str, Expression) =
|
||||
_ name:identifier() _ ":" _ expr:expression() _ { (name, expr) }
|
||||
rule record_entry(parser: &mut Parser) -> (&'input str, Expression) =
|
||||
_ name:identifier() _ ":" _ expr:expression(parser) _ { (name, expr) }
|
||||
|
||||
rule qualified_identifier() -> QualifiedName =
|
||||
names:(identifier() ++ "::") { QualifiedName { id: Default::default(), components: names.into_iter().map(|name| Rc::new(name.to_string())).collect() } }
|
||||
rule qualified_identifier(parser: &mut Parser) -> QualifiedName =
|
||||
names:(identifier() ++ "::") { QualifiedName { id: parser.fresh(), components: names.into_iter().map(|name| Rc::new(name.to_string())).collect() } }
|
||||
|
||||
//TODO improve the definition of identifiers
|
||||
rule identifier() -> &'input str =
|
||||
@ -364,69 +376,69 @@ peg::parser! {
|
||||
"break" / "alias" / "type" / "self" / "Self" / "interface" / "impl" / "true" / "false" / "module" / "import"
|
||||
|
||||
|
||||
rule if_expr() -> ExpressionKind =
|
||||
"if" _ discriminator:(expression()?) _ body:if_expr_body() {
|
||||
rule if_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"if" _ discriminator:(expression(parser)?) _ body:if_expr_body(parser) {
|
||||
ExpressionKind::IfExpression {
|
||||
discriminator: discriminator.map(Box::new),
|
||||
body: Box::new(body),
|
||||
}
|
||||
}
|
||||
|
||||
rule if_expr_body() -> IfExpressionBody =
|
||||
cond_block() / simple_pattern_match() / simple_conditional()
|
||||
rule if_expr_body(parser: &mut Parser) -> IfExpressionBody =
|
||||
cond_block(parser) / simple_pattern_match(parser) / simple_conditional(parser)
|
||||
|
||||
rule simple_conditional() -> IfExpressionBody =
|
||||
"then" _ then_case:expr_or_block() _ else_case:else_case() {
|
||||
rule simple_conditional(parser: &mut Parser) -> IfExpressionBody =
|
||||
"then" _ then_case:expr_or_block(parser) _ else_case:else_case(parser) {
|
||||
IfExpressionBody::SimpleConditional { then_case, else_case }
|
||||
}
|
||||
|
||||
rule simple_pattern_match() -> IfExpressionBody =
|
||||
"is" _ pattern:pattern() _ "then" _ then_case:expr_or_block() _ else_case:else_case() {
|
||||
rule simple_pattern_match(parser: &mut Parser) -> IfExpressionBody =
|
||||
"is" _ pattern:pattern(parser) _ "then" _ then_case:expr_or_block(parser) _ else_case:else_case(parser) {
|
||||
IfExpressionBody::SimplePatternMatch { pattern, then_case, else_case }
|
||||
}
|
||||
|
||||
rule cond_block() -> IfExpressionBody =
|
||||
"{" __ cond_arms:(cond_arm() ++ (delimiter()+)) __ "}" { IfExpressionBody::CondList(cond_arms) }
|
||||
rule cond_block(parser: &mut Parser) -> IfExpressionBody =
|
||||
"{" __ cond_arms:(cond_arm(parser) ++ (delimiter()+)) __ "}" { IfExpressionBody::CondList(cond_arms) }
|
||||
|
||||
rule cond_arm() -> ConditionArm =
|
||||
_ "else" _ body:expr_or_block() { ConditionArm { condition: Condition::Else, guard: None, body } } /
|
||||
_ condition:condition() _ guard:condition_guard() _ "then" _ body:expr_or_block()
|
||||
rule cond_arm(parser: &mut Parser) -> ConditionArm =
|
||||
_ "else" _ body:expr_or_block(parser) { ConditionArm { condition: Condition::Else, guard: None, body } } /
|
||||
_ condition:condition(parser) _ guard:condition_guard(parser) _ "then" _ body:expr_or_block(parser)
|
||||
{ ConditionArm { condition, guard, body } }
|
||||
|
||||
rule condition() -> Condition =
|
||||
"is" _ pat:pattern() { Condition::Pattern(pat) } /
|
||||
op:operator() _ expr:expression() { Condition::TruncatedOp(BinOp::from_sigil(op), expr) }
|
||||
rule condition(parser: &mut Parser) -> Condition =
|
||||
"is" _ pat:pattern(parser) { Condition::Pattern(pat) } /
|
||||
op:operator() _ expr:expression(parser) { Condition::TruncatedOp(BinOp::from_sigil(op), expr) }
|
||||
|
||||
rule condition_guard() -> Option<Expression> =
|
||||
("if" _ expr:expression() { expr } )?
|
||||
rule condition_guard(parser: &mut Parser) -> Option<Expression> =
|
||||
("if" _ expr:expression(parser) { expr } )?
|
||||
|
||||
rule expr_or_block() -> Block = block() / pos:position!() ex:expression() {
|
||||
rule expr_or_block(parser: &mut Parser) -> Block = block(parser) / pos:position!() ex:expression(parser) {
|
||||
Statement {
|
||||
id: Default::default(), location: pos.into(),
|
||||
id: parser.fresh() , location: pos.into(),
|
||||
kind: StatementKind::Expression(ex)
|
||||
}.into()
|
||||
}
|
||||
|
||||
rule else_case() -> Option<Block> =
|
||||
("else" _ eorb:expr_or_block() { eorb })?
|
||||
rule else_case(parser: &mut Parser) -> Option<Block> =
|
||||
("else" _ eorb:expr_or_block(parser) { eorb })?
|
||||
|
||||
rule pattern() -> Pattern =
|
||||
"(" _ variants:(pattern() ++ ",") _ ")" { Pattern::TuplePattern(variants) } /
|
||||
_ pat:simple_pattern() { pat }
|
||||
rule pattern(parser: &mut Parser) -> Pattern =
|
||||
"(" _ variants:(pattern(parser) ++ ",") _ ")" { Pattern::TuplePattern(variants) } /
|
||||
_ pat:simple_pattern(parser) { pat }
|
||||
|
||||
rule simple_pattern() -> Pattern =
|
||||
rule simple_pattern(parser: &mut Parser) -> Pattern =
|
||||
pattern_literal() /
|
||||
qn:qualified_identifier() "(" members:(pattern() ** ",") ")" {
|
||||
qn:qualified_identifier(parser) "(" members:(pattern(parser) ** ",") ")" {
|
||||
Pattern::TupleStruct(qn, members)
|
||||
} /
|
||||
qn:qualified_identifier() _ "{" _ items:(record_pattern_entry() ** ",") "}" _ {
|
||||
qn:qualified_identifier(parser) _ "{" _ items:(record_pattern_entry(parser) ** ",") "}" _ {
|
||||
let items = items.into_iter().map(|(name, pat)| (Rc::new(name.to_string()), pat)).collect();
|
||||
Pattern::Record(qn, items)
|
||||
} /
|
||||
qn:qualified_identifier() { Pattern::VarOrName(qn) }
|
||||
qn:qualified_identifier(parser) { Pattern::VarOrName(qn) }
|
||||
|
||||
rule record_pattern_entry() -> (&'input str, Pattern) =
|
||||
_ name:identifier() _ ":" _ pat:pattern() _ { (name, pat) } /
|
||||
rule record_pattern_entry(parser: &mut Parser) -> (&'input str, Pattern) =
|
||||
_ name:identifier() _ ":" _ pat:pattern(parser) _ { (name, pat) } /
|
||||
_ name:identifier() _ {
|
||||
let qn = QualifiedName {
|
||||
id: Default::default(),
|
||||
@ -447,14 +459,14 @@ peg::parser! {
|
||||
"_" { Pattern::Ignored }
|
||||
|
||||
|
||||
rule list_expr() -> ExpressionKind =
|
||||
"[" exprs:(expression() ** ",") "]" {
|
||||
rule list_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"[" exprs:(expression(parser) ** ",") "]" {
|
||||
let mut exprs = exprs;
|
||||
ExpressionKind::ListLiteral(exprs)
|
||||
}
|
||||
|
||||
rule paren_expr() -> ExpressionKind =
|
||||
"(" exprs:(expression() ** ",") ")" {
|
||||
rule paren_expr(parser: &mut Parser) -> ExpressionKind =
|
||||
"(" exprs:(expression(parser) ** ",") ")" {
|
||||
let mut exprs = exprs;
|
||||
match exprs.len() {
|
||||
1 => exprs.pop().unwrap().kind,
|
||||
|
@ -6,7 +6,7 @@ use std::{fmt::Write, rc::Rc};
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::new::schala_parser;
|
||||
use super::new::{schala_parser, Parser};
|
||||
use crate::{ast::*, tokenizing::Location};
|
||||
|
||||
fn rc(s: &str) -> Rc<String> {
|
||||
@ -87,7 +87,8 @@ fn ty_simple(name: &str) -> TypeIdentifier {
|
||||
|
||||
macro_rules! assert_ast {
|
||||
($input:expr, $statements:expr) => {
|
||||
let ast = schala_parser::program($input);
|
||||
let mut parser = Parser::new();
|
||||
let ast = schala_parser::program($input, &mut parser);
|
||||
let expected = AST { id: Default::default(), statements: $statements.into() };
|
||||
if ast.is_err() {
|
||||
println!("Parse error: {}", ast.unwrap_err());
|
||||
@ -99,14 +100,16 @@ macro_rules! assert_ast {
|
||||
|
||||
macro_rules! assert_fail {
|
||||
($input:expr, $failure:expr) => {
|
||||
let err = schala_parser::program($input).unwrap_err();
|
||||
let mut parser = Parser::new();
|
||||
let err = schala_parser::program($input, &mut parser).unwrap_err();
|
||||
assert_eq!(err.to_string(), $failure);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_expr {
|
||||
($input:expr, $correct:expr) => {
|
||||
let expr = schala_parser::expression($input);
|
||||
let mut parser = Parser::new();
|
||||
let expr = schala_parser::expression($input, &mut parser);
|
||||
if expr.is_err() {
|
||||
println!("Expression parse error: {}", expr.unwrap_err());
|
||||
panic!();
|
||||
@ -117,7 +120,8 @@ macro_rules! assert_expr {
|
||||
|
||||
macro_rules! assert_fail_expr {
|
||||
($input:expr, $failure:expr) => {
|
||||
let _err = schala_parser::expression($input).unwrap_err();
|
||||
let mut parser = Parser::new();
|
||||
let _err = schala_parser::expression($input, &mut parser).unwrap_err();
|
||||
//TODO make real tests for failures
|
||||
//assert_eq!(err.to_string(), $failure);
|
||||
};
|
||||
@ -1296,8 +1300,9 @@ fn blocks() {
|
||||
|
||||
let cases = ["{ a }", "{ a; }", "{a}", "{ a\n }", "{ a\n\n }", "{ a;\n\n; }"];
|
||||
|
||||
let mut parser = Parser::new();
|
||||
for case in cases.iter() {
|
||||
let block = schala_parser::block(case);
|
||||
let block = schala_parser::block(case, &mut parser);
|
||||
assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user