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
//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,

View File

@ -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());
}
}