More types of expr

This commit is contained in:
Greg Shuflin 2021-11-04 22:31:29 -07:00
parent 6a318257d6
commit 76b1e9c0dc
4 changed files with 64 additions and 28 deletions

9
Cargo.lock generated
View File

@ -561,8 +561,7 @@ dependencies = [
[[package]] [[package]]
name = "peg" name = "peg"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/kevinmehall/rust-peg?rev=960222580c8da25b17d32c2aae6f52f902728b62#960222580c8da25b17d32c2aae6f52f902728b62"
checksum = "07c0b841ea54f523f7aa556956fbd293bcbe06f2e67d2eb732b7278aaf1d166a"
dependencies = [ dependencies = [
"peg-macros", "peg-macros",
"peg-runtime", "peg-runtime",
@ -571,8 +570,7 @@ dependencies = [
[[package]] [[package]]
name = "peg-macros" name = "peg-macros"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/kevinmehall/rust-peg?rev=960222580c8da25b17d32c2aae6f52f902728b62#960222580c8da25b17d32c2aae6f52f902728b62"
checksum = "b5aa52829b8decbef693af90202711348ab001456803ba2a98eb4ec8fb70844c"
dependencies = [ dependencies = [
"peg-runtime", "peg-runtime",
"proc-macro2 1.0.30", "proc-macro2 1.0.30",
@ -582,8 +580,7 @@ dependencies = [
[[package]] [[package]]
name = "peg-runtime" name = "peg-runtime"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/kevinmehall/rust-peg?rev=960222580c8da25b17d32c2aae6f52f902728b62#960222580c8da25b17d32c2aae6f52f902728b62"
checksum = "c719dcf55f09a3a7e764c6649ab594c18a177e3599c467983cdf644bfc0a4088"
[[package]] [[package]]
name = "phf" name = "phf"

View File

@ -14,7 +14,9 @@ derivative = "1.0.3"
colored = "1.8" colored = "1.8"
radix_trie = "0.1.5" radix_trie = "0.1.5"
assert_matches = "1.5" assert_matches = "1.5"
peg = "0.7.0" #peg = "0.7.0"
peg = { git = "https://github.com/kevinmehall/rust-peg", rev = "960222580c8da25b17d32c2aae6f52f902728b62" }
schala-lang-codegen = { path = "../codegen" } schala-lang-codegen = { path = "../codegen" }
schala-repl = { path = "../../schala-repl" } schala-repl = { path = "../../schala-repl" }

View File

@ -7,7 +7,7 @@ peg::parser! {
rule whitespace() = [' ' | '\t' | '\n']* rule whitespace() = [' ' | '\t' | '\n']*
rule _ = quiet!{ whitespace() } rule _ = quiet!{ whitespace() }
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() } }
@ -55,15 +55,49 @@ peg::parser! {
quiet!{$( ['+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '!' | '$' | '&' | '|' | '?' | '^' | '`']+ )} / quiet!{$( ['+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '!' | '$' | '&' | '|' | '?' | '^' | '`']+ )} /
expected!("operator") expected!("operator")
#[cache_left_rec]
rule extended_expr() -> ExpressionKind = rule extended_expr() -> ExpressionKind =
indexee:extended_expr() indexers:index_part() {
ExpressionKind::Index {
indexee: Box::new(Expression::new(Default::default(), indexee)),
indexers,
}
} /
f:extended_expr() arguments:call_part() {
ExpressionKind::Call {
f: Box::new(Expression::new(Default::default(), f)),
arguments,
}
} /
expr:extended_expr() "." name:identifier() { ExpressionKind::Access {
name: Rc::new(name.to_string()),
expr: Box::new(Expression::new(Default::default(),expr)),
} } /
primary() primary()
rule index_part() -> Vec<Expression> =
"[" indexers:(expression() ++ ",") "]" { indexers }
rule call_part() -> Vec<InvocationArgument> =
"(" arguments:(invocation_argument() ** ",") ")" { arguments }
//TODO this shouldn't be an expression b/c type annotations disallowed here
rule invocation_argument() -> InvocationArgument =
_ "_" _ { InvocationArgument::Ignored } /
_ ident:identifier() _ "=" _ expr:expression() { InvocationArgument::Keyword {
name: Rc::new(ident.to_string()),
expr
} } /
_ expr:expression() _ { InvocationArgument::Positional(expr) }
rule primary() -> ExpressionKind = rule primary() -> ExpressionKind =
float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() /
list_expr() / if_expr() / identifier_expr() list_expr() / if_expr() / named_struct() / identifier_expr()
rule identifier_expr() -> ExpressionKind = rule identifier_expr() -> ExpressionKind =
named_struct() / qn:qualified_identifier() { ExpressionKind::Value(qn) } qn:qualified_identifier() { ExpressionKind::Value(qn) }
rule named_struct() -> ExpressionKind = rule named_struct() -> ExpressionKind =
name:qualified_identifier() _ fields:record_block() { name:qualified_identifier() _ fields:record_block() {

View File

@ -152,13 +152,6 @@ macro_rules! assert_fail_expr2 {
}; };
} }
macro_rules! assert_fail_expr {
($input:expr, $failure:expr) => {
let mut parser = make_parser($input);
let err = parser.expression().unwrap_err();
assert_eq!(err.msg, $failure);
};
}
#[test] #[test]
fn basic_literals() { fn basic_literals() {
use ExpressionKind::*; use ExpressionKind::*;
@ -250,15 +243,15 @@ fn operators() {
fn accessors() { fn accessors() {
use ExpressionKind::*; use ExpressionKind::*;
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })); assert_expr2!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
assert_expr!( assert_expr2!(
"a.b.c", "a.b.c",
expr(Access { expr(Access {
name: rc("c"), name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })) expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
}) })
); );
assert_expr!( assert_expr2!(
"a.b.c(3)", "a.b.c(3)",
expr(Call { expr(Call {
f: bx(expr(Access { f: bx(expr(Access {
@ -268,7 +261,7 @@ fn accessors() {
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))], arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
}) })
); );
assert_expr!( assert_expr2!(
"a.b().c", "a.b().c",
expr(Access { expr(Access {
name: rc("c"), name: rc("c"),
@ -307,7 +300,7 @@ fn identifiers() {
assert_expr2!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma)))); assert_expr2!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
assert_expr2!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b))))); assert_expr2!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
assert_expr2!("None", expr(Value(qn!(None)))); assert_expr2!("None", expr(Value(qn!(None))));
assert_expr!( assert_expr2!(
"thing::item::call()", "thing::item::call()",
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] }) expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
); );
@ -335,14 +328,24 @@ fn named_struct() {
#[test] #[test]
fn index() { fn index() {
use ExpressionKind::*; use ExpressionKind::*;
assert_expr!( assert_expr2!(
"a[b,c]", "armok[b,c]",
expr(Index { expr(Index {
indexee: bx(expr(Value(qn!(a)))), indexee: bx(expr(Value(qn!(armok)))),
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))] indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
}) })
); );
assert_expr!( assert_expr2!(
"a[b,c][1]",
expr(Index {
indexee: bx(expr(Index {
indexee: bx(expr(Value(qn!(a)))),
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
})),
indexers: vec![expr(NatLiteral(1))]
})
);
assert_expr2!(
"perspicacity()[a]", "perspicacity()[a]",
expr(Index { expr(Index {
indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })), indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })),
@ -354,9 +357,9 @@ fn index() {
let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] }); let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] });
let c = expr(Call { f: bx(b), arguments: vec![] }); let c = expr(Call { f: bx(b), arguments: vec![] });
let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] }); let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] });
assert_expr!("a()[b]()[d]", d); assert_expr2!("a()[b]()[d]", d);
assert_fail_expr!("a[]", "Empty index expressions are not allowed"); assert_fail_expr2!("a[]", "Empty index expressions are not allowed");
} }
#[test] #[test]