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
|
//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,
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user