Thread Parser through peg rules to provide ID's

This commit is contained in:
Greg Shuflin 2021-11-13 22:38:57 -08:00
parent ba8fb86e3f
commit 869de8c033
2 changed files with 168 additions and 151 deletions

View File

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

View File

@ -6,7 +6,7 @@ use std::{fmt::Write, rc::Rc};
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use super::new::schala_parser; use super::new::{schala_parser, Parser};
use crate::{ast::*, tokenizing::Location}; use crate::{ast::*, tokenizing::Location};
fn rc(s: &str) -> Rc<String> { fn rc(s: &str) -> Rc<String> {
@ -87,7 +87,8 @@ fn ty_simple(name: &str) -> TypeIdentifier {
macro_rules! assert_ast { macro_rules! assert_ast {
($input:expr, $statements:expr) => { ($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() }; let expected = AST { id: Default::default(), statements: $statements.into() };
if ast.is_err() { if ast.is_err() {
println!("Parse error: {}", ast.unwrap_err()); println!("Parse error: {}", ast.unwrap_err());
@ -99,14 +100,16 @@ macro_rules! assert_ast {
macro_rules! assert_fail { macro_rules! assert_fail {
($input:expr, $failure:expr) => { ($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); assert_eq!(err.to_string(), $failure);
}; };
} }
macro_rules! assert_expr { macro_rules! assert_expr {
($input:expr, $correct: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() { if expr.is_err() {
println!("Expression parse error: {}", expr.unwrap_err()); println!("Expression parse error: {}", expr.unwrap_err());
panic!(); panic!();
@ -117,7 +120,8 @@ macro_rules! assert_expr {
macro_rules! assert_fail_expr { macro_rules! assert_fail_expr {
($input:expr, $failure: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 //TODO make real tests for failures
//assert_eq!(err.to_string(), $failure); //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 cases = ["{ a }", "{ a; }", "{a}", "{ a\n }", "{ a\n\n }", "{ a;\n\n; }"];
let mut parser = Parser::new();
for case in cases.iter() { 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()); assert_eq!(block.unwrap(), vec![exst(Value(qn!(a)))].into());
} }
} }