From 869de8c033b7583f149bb452803be1c0d0ed1885 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Sat, 13 Nov 2021 22:38:57 -0800 Subject: [PATCH] Thread Parser through peg rules to provide ID's --- schala-lang/language/src/parsing/new.rs | 302 ++++++++++++----------- schala-lang/language/src/parsing/test.rs | 17 +- 2 files changed, 168 insertions(+), 151 deletions(-) diff --git a/schala-lang/language/src/parsing/new.rs b/schala-lang/language/src/parsing/new.rs index c830b72..c9f63f6 100644 --- a/schala-lang/language/src/parsing/new.rs +++ b/schala-lang/language/src/parsing/new.rs @@ -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 { 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 { - schala_parser::program(input).map_err(|err: peg::error::ParseError<_>| { + pub(crate) fn parse( + &mut self, + input: &str, + _source_reference: &SourceReference, + ) -> Result { + 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 { + 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 = - "{" __ decls:(func_declaration() ** (delimiter()+)) __ "}" { decls } + rule decl_block(parser: &mut Parser) -> Vec = + "{" __ 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 = - "{" __ signatures:(func_signature() ** (delimiter()+)) __ "}" { signatures } + rule signature_block(parser: &mut Parser) -> Vec = + "{" __ 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 = params:(formal_param() ** (_ "," _)) {? if params.len() < 256 { Ok(params) } else { + rule formal_params(parser: &mut Parser) -> Vec = + 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 = - "(" _ args:(expression() ** (_ "," _)) _ ")" { args } + rule annotation_args(parser: &mut Parser) -> Vec = + "(" _ 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 = - "[" indexers:(expression() ++ ",") "]" { indexers } + rule index_part(parser: &mut Parser) -> Vec = + "[" indexers:(expression(parser) ++ ",") "]" { indexers } - rule call_part() -> Vec = - "(" arguments:(invocation_argument() ** ",") ")" { arguments } + rule call_part(parser: &mut Parser) -> Vec = + "(" 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 = - "{" _ enumerators:(enumerator() ++ ",") _ "}" { enumerators } / - enumerator:enumerator() { vec![enumerator] } + rule for_enumerators(parser: &mut Parser) -> Vec = + "{" _ 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 = - "return" _ expr:expression() { Box::new(ForBody::MonadicReturn(expr)) } / - body:block() { Box::new(ForBody::StatementBlock(body)) } + rule for_body(parser: &mut Parser) -> Box = + "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 = - ("if" _ expr:expression() { expr } )? + rule condition_guard(parser: &mut Parser) -> Option = + ("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 = - ("else" _ eorb:expr_or_block() { eorb })? + rule else_case(parser: &mut Parser) -> Option = + ("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, diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index e47d6ae..a61e949 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -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 { @@ -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()); } }