diff --git a/anselme/ast/Call.lua b/anselme/ast/Call.lua index 5096c57..3acc51c 100644 --- a/anselme/ast/Call.lua +++ b/anselme/ast/Call.lua @@ -78,6 +78,9 @@ Call = ast.abstract.Node { is_simple_assignment = function(self) return self:is_infix("_=_") and Quote:is(self.arguments.positional[1]) and Identifier:is(self.arguments.positional[1].expression) end, + is_implicit_block_identifier = function(self) + return Identifier:is(self.func) and self.func.name == "_" and self.explicit == false + end, traverse = function(self, fn, ...) fn(self.func, ...) diff --git a/anselme/parser/expression/primary/prefix/prefix_maybe_nil_right.lua b/anselme/parser/expression/primary/prefix/prefix_maybe_nil_right.lua deleted file mode 100644 index e75e0a5..0000000 --- a/anselme/parser/expression/primary/prefix/prefix_maybe_nil_right.lua +++ /dev/null @@ -1,21 +0,0 @@ -local prefix = require("anselme.parser.expression.primary.prefix.prefix") -local escape = require("anselme.common").escape -local expression_to_ast = require("anselme.parser.expression.to_ast") - -local ast = require("anselme.ast") -local Nil = ast.Nil - -return prefix { - parse = function(self, source, options, str) - local source_start = source:clone() - local escaped = escape(self.operator) - - local sright = source:consume(str:match("^("..escaped..")(.*)$")) - local s, right, rem = pcall(expression_to_ast, source, options, sright, self.priority) - if not s then - return self:build_ast(Nil:new()):set_source(source_start), sright - else - return self:build_ast(right):set_source(source_start), rem - end - end, -} diff --git a/anselme/parser/expression/secondary/infix/call.lua b/anselme/parser/expression/secondary/infix/call.lua index 8601a1c..3898c95 100644 --- a/anselme/parser/expression/secondary/infix/call.lua +++ b/anselme/parser/expression/secondary/infix/call.lua @@ -1,4 +1,4 @@ -local infix = require("anselme.parser.expression.secondary.infix.infix") +local infix_or_suffix = require("anselme.parser.expression.secondary.infix.infix_or_suffix") local escape = require("anselme.common").escape local identifier = require("anselme.parser.expression.primary.identifier") @@ -7,15 +7,14 @@ local operator_priority = require("anselme.common").operator_priority local ast = require("anselme.ast") local Call, ArgumentTuple = ast.Call, ast.ArgumentTuple -return infix { +return infix_or_suffix { operator = "!", identifier = "_!_", priority = operator_priority["_!_"], match = function(self, str, current_priority, primary) local escaped = escape(self.operator) - -- TODO: doesn't support newline between ! and identifier, even in multiline expression - return self.priority > current_priority and str:match("^"..escaped) and identifier:match(str:match("^"..escaped.."[ \t]*(.-)$")) + return self.priority > current_priority and str:match("^"..escaped) and identifier:match(str:match("^"..escaped.."[ \t\n]*(.-)$")) end, build_ast = function(self, left, right) diff --git a/anselme/parser/expression/secondary/infix/infix_or_suffix.lua b/anselme/parser/expression/secondary/infix/infix_or_suffix.lua index 41949e4..0651527 100644 --- a/anselme/parser/expression/secondary/infix/infix_or_suffix.lua +++ b/anselme/parser/expression/secondary/infix/infix_or_suffix.lua @@ -1,10 +1,13 @@ --- same as infix, but skip if no valid expression after the operator instead of erroring +-- same as infix, but skip if no valid expression or end-of-line after the operator instead of erroring -- useful for operators that are both valid as infix and as suffix local infix = require("anselme.parser.expression.secondary.infix.infix") local escape = require("anselme.common").escape local expression_to_ast = require("anselme.parser.expression.to_ast") +local ast = require("anselme.ast") +local Call = ast.Call + return infix { -- returns exp, rem if expression found -- returns nil if no expression found @@ -27,6 +30,8 @@ return infix { local s, right, rem = pcall(expression_to_ast, source, options, sright, self.priority) if not s then return nil end + if Call:is(right) and right:is_implicit_block_identifier() then return nil end -- skip if end-of-line, ignoring implicit _ + return self:build_ast(primary, right):set_source(start_source), rem end, } diff --git a/test/results/merge nested mutable error bis.ans b/test/results/merge nested mutable error bis.ans index b7cdd42..19322f3 100644 --- a/test/results/merge nested mutable error bis.ans +++ b/test/results/merge nested mutable error bis.ans @@ -4,9 +4,9 @@ ↳ from test/tests/merge nested mutable error bis.ans:14:7 in call: error("abort") ↳ from test/tests/merge nested mutable error bis.ans:4:1 in block: insert(a, b)… ↳ from test/tests/merge nested mutable error bis.ans:3:18 in call: _ - ↳ from stdlib/script.ans:31:6 in call: fn! + ↳ from stdlib/script.ans:31:7 in call: fn! ↳ from stdlib/script.ans:30:1 in block: resume target = ()… - ↳ from stdlib/script.ans:29:7 in call: else! + ↳ from stdlib/script.ans:29:8 in call: else! ↳ from stdlib/script.ans:26:1 in block: if(fn . "current checkpoint")… ↳ from stdlib/script.ans:25:8 in call: _ ↳ from stdlib/script.ans:39:9 in call: value(s)! diff --git a/test/results/merge nested mutable error.ans b/test/results/merge nested mutable error.ans index 938e47a..61d6715 100644 --- a/test/results/merge nested mutable error.ans +++ b/test/results/merge nested mutable error.ans @@ -4,9 +4,9 @@ ↳ from test/tests/merge nested mutable error.ans:14:7 in call: error("abort") ↳ from test/tests/merge nested mutable error.ans:4:1 in block: insert(a, b)… ↳ from test/tests/merge nested mutable error.ans:3:18 in call: _ - ↳ from stdlib/script.ans:31:6 in call: fn! + ↳ from stdlib/script.ans:31:7 in call: fn! ↳ from stdlib/script.ans:30:1 in block: resume target = ()… - ↳ from stdlib/script.ans:29:7 in call: else! + ↳ from stdlib/script.ans:29:8 in call: else! ↳ from stdlib/script.ans:26:1 in block: if(fn . "current checkpoint")… ↳ from stdlib/script.ans:25:8 in call: _ ↳ from stdlib/script.ans:39:9 in call: value(s)! diff --git a/test/results/method call newline.ans b/test/results/method call newline.ans new file mode 100644 index 0000000..460e101 --- /dev/null +++ b/test/results/method call newline.ans @@ -0,0 +1,5 @@ +--# run #-- +--- return --- +5 +--# saved #-- +{} \ No newline at end of file diff --git a/test/tests/method call newline.ans b/test/tests/method call newline.ans new file mode 100644 index 0000000..c0563dc --- /dev/null +++ b/test/tests/method call newline.ans @@ -0,0 +1,5 @@ +( + "hello" + ! + len +) \ No newline at end of file