diff --git a/examples/basic/function0002.ngr b/examples/basic/function0002.ngr index 2ff6935..69e6e72 100644 --- a/examples/basic/function0002.ngr +++ b/examples/basic/function0002.ngr @@ -1,7 +1,7 @@ x = 1; function add_x(y) x + y; a = 3; -function add_x_twice(y) add_x(y) + x +function add_x_twice(y) add_x(y) + x; print x; result = add_x(a); print x; diff --git a/examples/basic/function0003.ngr b/examples/basic/function0003.ngr index 0b55b08..1813dd8 100644 --- a/examples/basic/function0003.ngr +++ b/examples/basic/function0003.ngr @@ -2,7 +2,7 @@ x = 1u64; function mean_x(y) { base = x + y; result = base / 2; - result; + result }; a = 3; mean_x_and_a = mean_x(a); diff --git a/src/syntax/parser.lalrpop b/src/syntax/parser.lalrpop index 9798ed1..ee546b9 100644 --- a/src/syntax/parser.lalrpop +++ b/src/syntax/parser.lalrpop @@ -60,7 +60,8 @@ pub Program: Program = { // a program is just a set of statements => Program { items - } + }, + => Program { items: vec![] }, } ProgramTopLevel: Vec = { @@ -68,17 +69,21 @@ ProgramTopLevel: Vec = { rest.push(t); rest }, - => Vec::new(), + => vec![t], } pub TopLevel: TopLevel = { => f, - => TopLevel::Statement(s), + ";" => TopLevel::Statement(s), } Function: TopLevel = { "function" "(" OptionalComma ")" ";" => TopLevel::Function(opt_name, args, exp), +// "function" "(" OptionalComma ")" "{" "}" => +// TopLevel::Function(opt_name, args, Expression::Block(Location::new(file_idx, s..e), vec![])), +// "function" "(" OptionalComma ")" "{" "}" => +// TopLevel::Function(opt_name, args, Expression::Block(Location::new(file_idx, s..e), stmts)), } OptionalName: Option = { @@ -112,36 +117,22 @@ Statements: Vec = { // a statement is either a set of statements followed by another // statement (note, here, that you can name the result of a sub-parse // using ) ... - => { + ";" => { stmts.push(stmt); stmts }, - // ... or it's nothing. This may feel like an awkward way to define - // lists of things -- and it is a bit awkward -- but there are actual - // technical reasons that you want to (a) use recursivion to define - // these, and (b) use *left* recursion, specifically. That's why, in - // this file, all of the recursive cases are to the left, like they - // are above. - // - // the details of why left recursion is better is actually pretty - // fiddly and in the weeds, and if you're interested you should look - // up LALR parsers versus LL parsers; both their differences and how - // they're constructed, as they're kind of neat. - // - // but if you're just writing grammars with lalrpop, then you should - // just remember that you should always use left recursion, and be - // done with it. - => { - Vec::new() + => { + vec![stmt] } } +#[inline] Statement: Statement = { // A statement can be a variable binding. Note, here, that we use this // funny @L thing to get the source location before the variable, so that // we can say that this statement spans across everything. - "> "=" ";" => + "> "=" => Statement::Binding( Location::new(file_idx, ls..le), Name::new(v, Location::new(file_idx, ls..var_end)), @@ -149,14 +140,14 @@ Statement: Statement = { ), // A statement can just be a print statement. - "print" "> ";" => + "print" "> => Statement::Print( Location::new(file_idx, ls..le), Name::new(v, Location::new(file_idx, name_start..name_end)), ), // A statement can just be an expression. - ";" => + => Statement::Expression(e), } @@ -237,6 +228,7 @@ AtomicExpression: Expression = { "> => Expression::Value(Location::new(file_idx, l..end), Value::Number(n.0, n.1, n.2)), // this expression could actually be a block! "{" "}" => Expression::Block(Location::new(file_idx, s..e), stmts), + "{" "}" => Expression::Block(Location::new(file_idx, s..e), vec![]), // finally, let people parenthesize expressions and get back to a // lower precedence "(" ")" => e, diff --git a/src/syntax/validate.rs b/src/syntax/validate.rs index de7dbee..9013ac4 100644 --- a/src/syntax/validate.rs +++ b/src/syntax/validate.rs @@ -68,6 +68,7 @@ impl Program { /// actually a problem. pub fn validate(&self) -> (Vec, Vec) { let mut bound_variables = ScopedMap::new(); + println!("validate: {}", self); self.validate_with_bindings(&mut bound_variables) }