Change grammar to properly allow if, while, and for loops (without confusing it with closures).
This commit is contained in:
parent
bf06407d16
commit
692411e232
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -218,9 +218,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.14"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
|
||||
checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
@ -229,9 +229,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.14"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
|
||||
checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@ -239,9 +239,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.14"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
|
||||
checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
@ -252,9 +252,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.14"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
|
||||
checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
@ -338,18 +338,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -12,9 +12,9 @@ name = "dmc"
|
||||
path = "src/bin/dmc/main.rs"
|
||||
|
||||
[dependencies]
|
||||
pest = "2.7.14"
|
||||
pest = { version = "2.8.0" }
|
||||
clap = { version = "4.5.23", features = ["derive"] }
|
||||
pest_derive = "2.7.14"
|
||||
pest_derive = { version = "2.8.0", features = ["grammar-extras"] }
|
||||
codespan-reporting = "0.12.0"
|
||||
log = "0.4.27"
|
||||
indoc = "2.0.6"
|
||||
|
@ -1,7 +1,7 @@
|
||||
fn main(args: Array<String>) {
|
||||
if args[0] == 'test' {
|
||||
if (args[0] == 'test') {
|
||||
println('test');
|
||||
} else if args[0] == 'foo' {
|
||||
} else if (args[0] == 'foo') {
|
||||
println('foo');
|
||||
} else {
|
||||
println('not test');
|
||||
|
117
src/ast/build.rs
117
src/ast/build.rs
@ -941,11 +941,51 @@ fn build_if_else_statement(file_id: usize, if_else_statement_pair: Pair<Rule>) -
|
||||
}
|
||||
|
||||
fn build_while_statement(file_id: usize, while_statement_pair: Pair<Rule>) -> WhileStatement {
|
||||
todo!()
|
||||
let mut inner = while_statement_pair.into_inner();
|
||||
inner.next().unwrap(); // while
|
||||
let condition = expect_and_use(
|
||||
file_id,
|
||||
inner.next().unwrap(),
|
||||
Rule::Expression,
|
||||
build_expression,
|
||||
);
|
||||
|
||||
let body = expect_and_use(
|
||||
file_id,
|
||||
inner.next().unwrap(),
|
||||
Rule::BlockStatement,
|
||||
build_block_statement,
|
||||
);
|
||||
WhileStatement { condition, body }
|
||||
}
|
||||
|
||||
fn build_for_statement(file_id: usize, for_statement_pair: Pair<Rule>) -> ForStatement {
|
||||
todo!()
|
||||
let mut inner = for_statement_pair.into_inner();
|
||||
inner.next().unwrap(); // for
|
||||
let variable = expect_and_use(
|
||||
file_id,
|
||||
inner.next().unwrap(),
|
||||
Rule::Identifier,
|
||||
build_identifier,
|
||||
);
|
||||
inner.next().unwrap(); // in
|
||||
let iterator = expect_and_use(
|
||||
file_id,
|
||||
inner.next().unwrap(),
|
||||
Rule::Expression,
|
||||
build_expression,
|
||||
);
|
||||
let body = expect_and_use(
|
||||
file_id,
|
||||
inner.next().unwrap(),
|
||||
Rule::BlockStatement,
|
||||
build_block_statement,
|
||||
);
|
||||
ForStatement {
|
||||
variable,
|
||||
iterator,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
fn build_expression(file_id: usize, expression_pair: Pair<Rule>) -> Expression {
|
||||
@ -1514,7 +1554,11 @@ mod tests {
|
||||
if let Err(e) = parse_result {
|
||||
panic!("Parsing failed.\n{}", e)
|
||||
} else {
|
||||
let ast = build_ast(0, parse_result.unwrap().next().unwrap());
|
||||
let mut pairs = parse_result.unwrap();
|
||||
if pairs.as_str().trim() != src.trim() {
|
||||
panic!("Parsing did not consume entire input.");
|
||||
}
|
||||
let ast = build_ast(0, pairs.next().unwrap());
|
||||
dbg!(ast);
|
||||
}
|
||||
}
|
||||
@ -1576,7 +1620,7 @@ mod tests {
|
||||
fn if_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
if true {
|
||||
if (true) {
|
||||
foo
|
||||
}
|
||||
}
|
||||
@ -1587,7 +1631,7 @@ mod tests {
|
||||
fn if_else_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
if true {
|
||||
if (true) {
|
||||
foo
|
||||
} else {
|
||||
bar
|
||||
@ -1600,9 +1644,9 @@ mod tests {
|
||||
fn if_else_if_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
if true {
|
||||
if (true) {
|
||||
foo
|
||||
} else if false {
|
||||
} else if (false) {
|
||||
bar
|
||||
}
|
||||
}
|
||||
@ -1613,9 +1657,9 @@ mod tests {
|
||||
fn if_else_if_else_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
if true {
|
||||
if (true) {
|
||||
foo
|
||||
} else if false {
|
||||
} else if (false) {
|
||||
bar
|
||||
} else {
|
||||
buzz
|
||||
@ -1623,4 +1667,59 @@ mod tests {
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
while (true) {
|
||||
foo()
|
||||
}
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_statement() {
|
||||
assert_builds(indoc! {"
|
||||
fn main(args: Array<String>) {
|
||||
for (arg in args) {
|
||||
foo(arg);
|
||||
}
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_with_call_condition() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
if (foo()) {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_with_call_condition() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
while (foo()) {
|
||||
bar()
|
||||
}
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_with_call_iterator() {
|
||||
assert_builds(indoc! {"
|
||||
fn main() {
|
||||
for (foo in bar()) {
|
||||
baz(foo)
|
||||
}
|
||||
}
|
||||
"})
|
||||
}
|
||||
}
|
||||
|
@ -824,9 +824,9 @@ impl Unparse for ReturnStatement {
|
||||
|
||||
impl Unparse for IfStatement {
|
||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.write_indented("if ")?;
|
||||
writer.write_indented("if (")?;
|
||||
self.condition.unparse(writer)?;
|
||||
writer.writeln(" {")?;
|
||||
writer.writeln(") {")?;
|
||||
self.then_block.unparse_inner(writer)?;
|
||||
writer.writeln_indented("}")?;
|
||||
Ok(())
|
||||
@ -847,9 +847,9 @@ impl Unparse for IfElseStatement {
|
||||
impl Unparse for ElseIfs {
|
||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
for if_statement in &self.0 {
|
||||
writer.write_indented("else if ")?;
|
||||
writer.write_indented("else if (")?;
|
||||
if_statement.condition.unparse(writer)?;
|
||||
writer.writeln(" {")?;
|
||||
writer.writeln(") {")?;
|
||||
if_statement.then_block.unparse_inner(writer)?;
|
||||
writer.writeln_indented("}")?;
|
||||
}
|
||||
|
@ -536,7 +536,9 @@ ReturnStatement = {
|
||||
|
||||
IfStatement = {
|
||||
If
|
||||
~ "("
|
||||
~ Expression
|
||||
~ ")"
|
||||
~ BlockStatement
|
||||
}
|
||||
|
||||
@ -558,15 +560,19 @@ ElseBlock = {
|
||||
|
||||
WhileStatement = {
|
||||
While
|
||||
~ "("
|
||||
~ Expression
|
||||
~ ")"
|
||||
~ BlockStatement
|
||||
}
|
||||
|
||||
ForStatement = {
|
||||
For
|
||||
~ Expression
|
||||
~ "("
|
||||
~ Identifier
|
||||
~ In
|
||||
~ Expression
|
||||
~ ")"
|
||||
~ BlockStatement
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ pub struct DeimosParser;
|
||||
mod deimos_parser_tests {
|
||||
use crate::parser::{DeimosParser, Rule};
|
||||
use indoc::indoc;
|
||||
use pest::Parser;
|
||||
use pest::{parses_to, Parser};
|
||||
|
||||
macro_rules! fail_rule {
|
||||
($pair: expr; $rule:path) => {{
|
||||
@ -34,7 +34,7 @@ mod deimos_parser_tests {
|
||||
panic!("Parsing failed.\n{}", e);
|
||||
} else {
|
||||
let mut pairs = parse_result.unwrap();
|
||||
if input != pairs.as_str() {
|
||||
if input.trim() != pairs.as_str().trim() {
|
||||
panic!(
|
||||
"Parsing did not consume entire input. Consumed only:\n{}",
|
||||
pairs.as_str()
|
||||
@ -101,7 +101,7 @@ mod deimos_parser_tests {
|
||||
parses_to(
|
||||
Rule::IfStatement,
|
||||
indoc! {"
|
||||
if foo == 42 {
|
||||
if (foo == 42) {
|
||||
bar()
|
||||
}"},
|
||||
)
|
||||
@ -112,7 +112,7 @@ mod deimos_parser_tests {
|
||||
parses_to(
|
||||
Rule::IfElseStatement,
|
||||
indoc! {"
|
||||
if foo == 42 {
|
||||
if (foo == 42) {
|
||||
bar()
|
||||
} else {
|
||||
baz()
|
||||
@ -125,9 +125,9 @@ mod deimos_parser_tests {
|
||||
parses_to(
|
||||
Rule::IfElseStatement,
|
||||
indoc! {"
|
||||
if foo == 42 {
|
||||
if (foo == 42) {
|
||||
bar()
|
||||
} else if foo == 16 {
|
||||
} else if (foo == 16) {
|
||||
baz()
|
||||
}"},
|
||||
)
|
||||
@ -138,13 +138,46 @@ mod deimos_parser_tests {
|
||||
parses_to(
|
||||
Rule::IfElseStatement,
|
||||
indoc! {"
|
||||
if foo == 42 {
|
||||
if (foo == 42) {
|
||||
foo()
|
||||
} else if foo == 16 {
|
||||
} else if (foo == 16) {
|
||||
baz()
|
||||
} else {
|
||||
fizz()
|
||||
}"},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_statement() {
|
||||
parses_to(Rule::WhileStatement, "while (foo) { bar() }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_statement() {
|
||||
parses_to(Rule::ForStatement, "for (foo in bar) { baz(foo); }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_statement_with_call_condition() {
|
||||
parses_to(Rule::IfStatement, indoc! {"
|
||||
if (foo()) {
|
||||
bar()
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_statement_with_call_condition() {
|
||||
parses_to(Rule::WhileStatement, "while (foo()) { bar(); }")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_statement_with_call_iterator() {
|
||||
parses_to(Rule::ForStatement, indoc! {"
|
||||
for (foo in bar()) {
|
||||
baz(foo);
|
||||
}
|
||||
"})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user