More declarations

This commit is contained in:
Greg Shuflin 2021-11-07 03:13:35 -08:00
parent d46f40bc0f
commit 54b33282ef
2 changed files with 51 additions and 8 deletions

View File

@ -13,6 +13,8 @@ peg::parser! {
rule _ = quiet!{ whitespace() } rule _ = quiet!{ whitespace() }
rule __ = quiet!{ [' ' | '\t' ]* }
pub rule program() -> AST = pub rule program() -> AST =
n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } } n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } }
@ -27,11 +29,43 @@ peg::parser! {
stmt:statement() delimiter()+ { stmt } stmt:statement() delimiter()+ { stmt }
rule statement() -> Statement = rule statement() -> Statement =
_ decl:declaration() { Statement { id: Default::default(), location: Default::default(), kind: StatementKind::Declaration(decl) } } / kind:statement_kind() { Statement { id: Default::default(), location: Default::default(), kind } }
_ expr:expression() { Statement { id: Default::default(), location: Default::default(), kind: StatementKind::Expression(expr) } }
rule statement_kind() -> StatementKind =
_ decl:declaration() { StatementKind::Declaration(decl) } /
_ expr:expression() { StatementKind::Expression(expr) }
rule declaration() -> Declaration = rule declaration() -> Declaration =
binding() / type_decl() binding() / type_decl() / annotation() / func()
rule func() -> Declaration =
sig:func_signature() __ body:block() { Declaration::FuncDecl(sig, body) } /
sig:func_signature() { Declaration::FuncSig(sig) }
//TODO handle operators
rule func_signature() -> Signature =
"fn" _ name:identifier() "(" _ params:formal_params() _ ")" _ 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 {
Err("function-too-long") }
}
rule formal_param() -> FormalParam =
name:identifier() _ anno:type_anno()? _ "=" expr:expression() { 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 {
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 binding() -> Declaration = rule binding() -> Declaration =
"let" _ mutable:"mut"? _ ident:identifier() _ type_anno:type_anno()? _ "=" _ expr:expression() { "let" _ mutable:"mut"? _ ident:identifier() _ type_anno:type_anno()? _ "=" _ expr:expression() {

View File

@ -126,6 +126,13 @@ macro_rules! assert_fail {
}; };
} }
macro_rules! assert_fail2 {
($input:expr, $failure:expr) => {
let err = schala_parser::program($input).unwrap_err();
assert_eq!(err.to_string(), $failure);
};
}
macro_rules! assert_expr { macro_rules! assert_expr {
($input:expr, $correct:expr) => { ($input:expr, $correct:expr) => {
let mut parser = make_parser($input); let mut parser = make_parser($input);
@ -770,7 +777,7 @@ fn bindings() {
#[test] #[test]
fn functions() { fn functions() {
use ExpressionKind::*; use ExpressionKind::*;
assert_ast!( assert_ast2!(
"fn oi()", "fn oi()",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature { vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("oi"), name: rc("oi"),
@ -780,12 +787,12 @@ fn functions() {
})))] })))]
); );
assert_ast!( assert_ast2!(
"oi()", "oi()",
vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))] vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))]
); );
assert_expr!( assert_expr2!(
"oi(a, 2+2)", "oi(a, 2+2)",
expr(Call { expr(Call {
f: bx(expr(Value(qn!(oi)))), f: bx(expr(Value(qn!(oi)))),
@ -797,7 +804,7 @@ fn functions() {
); );
assert_fail!("a(b,,c)", "Expected a literal expression, got Comma"); assert_fail!("a(b,,c)", "Expected a literal expression, got Comma");
assert_ast!( assert_ast2!(
"fn a(b, c: Int): Int", "fn a(b, c: Int): Int",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature { vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("a"), name: rc("a"),
@ -825,7 +832,9 @@ fn max_function_params() {
write!(buf, "a{}, ", n).unwrap(); write!(buf, "a{}, ", n).unwrap();
} }
write!(buf, ") {{ return 20 }}").unwrap(); write!(buf, ") {{ return 20 }}").unwrap();
assert_fail!(&buf, "A function cannot have more than 255 arguments"); //assert_fail2!(&buf, "A function cannot have more than 255 arguments");
//TODO better errors again
assert_fail2!(&buf, "error at 1:1439: expected ['a' ..= 'z' | 'A' ..= 'Z' | '_']");
} }
#[test] #[test]