diff --git a/corpus/declarations.sk b/corpus/declarations.sk index 989860e..ad1b6d5 100644 --- a/corpus/declarations.sk +++ b/corpus/declarations.sk @@ -9,4 +9,4 @@ let basic_value = 10 let calculation = (1 * 1) + (2 * (2 + 3)) -let calculation_with_fn fn = 1 * fn (2 * 2) +let calculation_with_fn fn = 1 * (fn (2 * 2)) diff --git a/src/grammar.pest b/src/grammar.pest index 0fff994..768f9f1 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -27,13 +27,14 @@ func = { type_term ~ "->" ~ type_expr } type_ident = ${ #name = ident ~ #args = type_args? } type_args = { "<" ~ MLF ~ type_ident* ~ MLF ~ ">" } -expr = { infix_expr | call_expr | term } +expr = { infix_expr | call_expr | if | term } +if = { "if" ~ #predicate = expr ~ "then" ~ MLF ~ #then = expr ~ (MLF ~ "else" ~ MLF ~ #else = expr)? } term = _{ ident | literal | "(" ~ MLF ~ expr ~ MLF ~ ")" | block } call_expr = { #name = ident ~ #args = (term)+ } infix_expr = { - #lhs = term ~ operator ~ #rhs = expr + #lhs = term ~ operator ~ #rhs = (infix_expr | term) } operator = { "+" | "-" | "*" | "/" | "&&" | "||" | "<" | ">" | "==" | "!=" } @@ -41,19 +42,20 @@ operator = { "+" | "-" | "*" | "/" | "&&" | "||" | "<" | ">" | "==" | "!=" } ident = @{ !KEYWORD ~ ALPHABETIC ~ (ALPHABETIC | NUMBER | "_")* | quoted_indent } quoted_indent = _{ "`" ~ (!"`" ~ ANY)+ ~ "`" } -literal = { string | number | boolean | char } +literal = { quoted_string | number | boolean | char } -string = { "\"" ~ (!"\"" ~ ANY)* ~ "\"" } -char = { "'" ~ !"'" ~ ANY ~ "'" } -number = _{ byte | float | integer } -integer = @{ "-"? ~ ASCII_DIGIT+ } -float = @{ +quoted_string = _{ "\"" ~ string ~ "\"" } +string = { (!"\"" ~ ANY)* } +char = { "'" ~ !"'" ~ ANY ~ "'" } +number = _{ byte | float | integer } +integer = @{ "-"? ~ ASCII_DIGIT+ } +float = @{ "-"? ~ (ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT* | ASCII_DIGIT* ~ "." ~ ASCII_DIGIT+) } -byte = @{ "0x" ~ ASCII_HEX_DIGIT{1, 2} | "0b" ~ ASCII_BIN_DIGIT{0, 8} } -boolean = @{ "true" | "false" } +byte = @{ "0x" ~ ASCII_HEX_DIGIT{1, 2} | "0b" ~ ASCII_BIN_DIGIT{0, 8} } +boolean = @{ "true" | "false" } -KEYWORD = _{ "let" | "rec" | "enum" } +KEYWORD = _{ "let" | "rec" | "enum" | "if" | "then" | "else" } TERMINATE = _{ LF | EOI | ";" } MLF = _{ (LF)* } LF = _{ "\n" | "\r" } diff --git a/src/test/expressions.rs b/src/test/expressions.rs index 9d315ee..62d242b 100644 --- a/src/test/expressions.rs +++ b/src/test/expressions.rs @@ -11,10 +11,8 @@ fn it_parses_addition() { integer(0, 1) ]), operator(2, 3), - expr(4, 5, [ - literal(4, 5, [ - integer(4, 5) - ]) + literal(4, 5, [ + integer(4, 5) ]) ]) ]) @@ -45,9 +43,7 @@ fn it_parses_addition_with_variables() { infix_expr(0, 14, [ ident(0, 5), operator(6, 7), - expr(8, 14, [ - ident(8, 14) - ]) + ident(8, 14) ]) ]) ]); @@ -62,10 +58,8 @@ fn it_parses_subtraction() { float(0, 3) ]), operator(4, 5), - expr(6, 9, [ - literal(6, 9, [ - float(6, 9) - ]) + literal(6, 9, [ + float(6, 9) ]) ]) ]) @@ -81,17 +75,13 @@ fn it_parses_multiple_operations() { integer(0, 1) ]), operator(2, 3), - expr(4, 9, [ - infix_expr(4, 9, [ - literal(4, 5, [ - integer(4, 5) - ]), - operator(6, 7), - expr(8, 9, [ - literal(8, 9, [ - integer(8, 9) - ]) - ]) + infix_expr(4, 9, [ + literal(4, 5, [ + integer(4, 5) + ]), + operator(6, 7), + literal(8, 9, [ + integer(8, 9) ]) ]) ]) @@ -119,11 +109,9 @@ fn it_parses_calls() { integer(7, 8) ]), operator(9, 10), - expr(11, 12, [ literal(11, 12, [ integer(11, 12) ]), - ]) ]) ]), ident(14, 15) @@ -141,11 +129,9 @@ fn it_parses_calls() { integer(7, 8) ]), operator(9, 10), - expr(11, 12, [ - literal(11, 12, [ - integer(11, 12) - ]), - ]) + literal(11, 12, [ + integer(11, 12) + ]), ]) ]) ]), diff --git a/src/test/literals.rs b/src/test/literals.rs index 6180ed4..933e755 100644 --- a/src/test/literals.rs +++ b/src/test/literals.rs @@ -60,17 +60,17 @@ fn it_parses_bytes() { fn it_parses_strings() { parses_to!(parser: SnekParser, input: r#""Hello world""#, rule: Rule::literal, tokens: [ literal(0, 13, [ - string(0, 13) + string(1, 12) ]) ]); parses_to!(parser: SnekParser, input: r#""""#, rule: Rule::literal, tokens: [ literal(0, 2, [ - string(0, 2) + string(1, 1) ]) ]); parses_to!(parser: SnekParser, input: r#""\"""#, rule: Rule::literal, tokens: [ literal(0, 3, [ - string(0, 3) + string(1, 2) ]) ]); } diff --git a/src/test/statements.rs b/src/test/statements.rs index 79a7246..1107fa9 100644 --- a/src/test/statements.rs +++ b/src/test/statements.rs @@ -29,6 +29,13 @@ fn it_parses_decl_with_type() { } } +#[test] +fn it_parses_if_stmt() { + if let Err(e) = (*TESTER).evaluate_strict("if-stmt") { + panic!("{e}") + } +} + #[test] fn it_parses_blocks() { parses_to!(parser: SnekParser, input: "let a = { 1 + 1 }", rule: Rule::statement, tokens: [ @@ -43,10 +50,8 @@ fn it_parses_blocks() { integer(10, 11) ]), operator(12, 13), - expr(14, 15, [ - literal(14, 15, [ - integer(14, 15) - ]) + literal(14, 15, [ + integer(14, 15) ]) ]) ]) @@ -75,10 +80,8 @@ fn it_parses_multiline_blocks() { integer(18, 19) ]), operator(20, 21), - expr(22, 23, [ - literal(22, 23, [ - integer(22, 23) - ]) + literal(22, 23, [ + integer(22, 23) ]) ]) ]) diff --git a/tests/corpus/statements/decl-with-type.txt b/tests/corpus/statements/decl-with-type.txt index 8e8cc4e..3e430de 100644 --- a/tests/corpus/statements/decl-with-type.txt +++ b/tests/corpus/statements/decl-with-type.txt @@ -1,4 +1,4 @@ -Declaration Test +Declaration with types test ====== @@ -24,10 +24,8 @@ let add_a x: Num -> Num = x + a (integer: "1") ) (operator: "+") - (expr - (literal - (integer: "1") - ) + (literal + (integer: "1") ) ) ) @@ -55,9 +53,7 @@ let add_a x: Num -> Num = x + a (infix_expr (ident: "x") (operator: "+") - (expr - (ident: "a") - ) + (ident: "a") ) ) ) diff --git a/tests/corpus/statements/fn-decl.txt b/tests/corpus/statements/fn-decl.txt index 7f7b197..c85b5e4 100644 --- a/tests/corpus/statements/fn-decl.txt +++ b/tests/corpus/statements/fn-decl.txt @@ -1,4 +1,4 @@ -Args Declaration Test +Function Declaration Test ====== @@ -17,9 +17,7 @@ let add1 a = add a 1 (infix_expr (ident: "a") (operator: "+") - (expr - (ident: "b") - ) + (ident: "b") ) ) ) diff --git a/tests/corpus/statements/if-stmt.txt b/tests/corpus/statements/if-stmt.txt new file mode 100644 index 0000000..d38f8b5 --- /dev/null +++ b/tests/corpus/statements/if-stmt.txt @@ -0,0 +1,92 @@ +If-Statements + +====== + +if a == "test" then + print "test" +else + print "no test" + +if 1 != 1 then { + let a = 1 + a + 1 +} + +====== + +(file + (statement + (expr + (if + (expr + (infix_expr + (ident: "a") + (operator: "==") + (literal + (string: "test") + ) + ) + ) + (expr + (call_expr + (ident: "print") + (literal + (string: "test") + ) + ) + ) + (expr + (call_expr + (ident: "print") + (literal + (string: "no test") + ) + ) + ) + ) + ) + ) + (statement + (expr + (if + (expr + (infix_expr + (literal + (integer: "1") + ) + (operator: "!=") + (literal + (integer: "1") + ) + ) + ) + (expr + (block + (statement + (decl + (ident: "a") + (expr + (literal + (integer: "1") + ) + ) + ) + ) + (statement + (expr + (infix_expr + (ident: "a") + (operator: "+") + (literal + (integer: "1") + ) + ) + ) + ) + ) + ) + ) + ) + ) + (EOI: "") +) diff --git a/tests/corpus/statements/simple-decl.txt b/tests/corpus/statements/simple-decl.txt index 81aa4b5..5995b21 100644 --- a/tests/corpus/statements/simple-decl.txt +++ b/tests/corpus/statements/simple-decl.txt @@ -17,26 +17,22 @@ let b = a + 2 (integer: "1") ) (operator: "+") - (expr - (literal - (integer: "1") - ) + (literal + (integer: "1") ) ) ) ) ) - (statement + (statement (decl (ident: "b") (expr (infix_expr (ident: "a") (operator: "+") - (expr - (literal - (integer: "2") - ) + (literal + (integer: "2") ) ) )