1
0
Fork 0
mirror of https://github.com/Reuh/anselme.git synced 2025-10-27 16:49:31 +00:00

[language] allow newlines between ! and identifier in _!_ call operator

This commit is contained in:
Étienne Fildadut 2024-05-21 17:34:04 +02:00
parent 69da1ff223
commit 03922ebde4
8 changed files with 26 additions and 30 deletions

View file

@ -78,6 +78,9 @@ Call = ast.abstract.Node {
is_simple_assignment = function(self) is_simple_assignment = function(self)
return self:is_infix("_=_") and Quote:is(self.arguments.positional[1]) and Identifier:is(self.arguments.positional[1].expression) return self:is_infix("_=_") and Quote:is(self.arguments.positional[1]) and Identifier:is(self.arguments.positional[1].expression)
end, 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, ...) traverse = function(self, fn, ...)
fn(self.func, ...) fn(self.func, ...)

View file

@ -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,
}

View file

@ -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 escape = require("anselme.common").escape
local identifier = require("anselme.parser.expression.primary.identifier") 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 ast = require("anselme.ast")
local Call, ArgumentTuple = ast.Call, ast.ArgumentTuple local Call, ArgumentTuple = ast.Call, ast.ArgumentTuple
return infix { return infix_or_suffix {
operator = "!", operator = "!",
identifier = "_!_", identifier = "_!_",
priority = operator_priority["_!_"], priority = operator_priority["_!_"],
match = function(self, str, current_priority, primary) match = function(self, str, current_priority, primary)
local escaped = escape(self.operator) 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\n]*(.-)$"))
return self.priority > current_priority and str:match("^"..escaped) and identifier:match(str:match("^"..escaped.."[ \t]*(.-)$"))
end, end,
build_ast = function(self, left, right) build_ast = function(self, left, right)

View file

@ -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 -- useful for operators that are both valid as infix and as suffix
local infix = require("anselme.parser.expression.secondary.infix.infix") local infix = require("anselme.parser.expression.secondary.infix.infix")
local escape = require("anselme.common").escape local escape = require("anselme.common").escape
local expression_to_ast = require("anselme.parser.expression.to_ast") local expression_to_ast = require("anselme.parser.expression.to_ast")
local ast = require("anselme.ast")
local Call = ast.Call
return infix { return infix {
-- returns exp, rem if expression found -- returns exp, rem if expression found
-- returns nil if no 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) local s, right, rem = pcall(expression_to_ast, source, options, sright, self.priority)
if not s then return nil end 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 return self:build_ast(primary, right):set_source(start_source), rem
end, end,
} }

View file

@ -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: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:4:1 in block: insert(a, b)…
↳ from test/tests/merge nested mutable error bis.ans:3:18 in call: _ ↳ 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: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:26:1 in block: if(fn . "current checkpoint")…
↳ from stdlib/script.ans:25:8 in call: _ ↳ from stdlib/script.ans:25:8 in call: _
↳ from stdlib/script.ans:39:9 in call: value(s)! ↳ from stdlib/script.ans:39:9 in call: value(s)!

View file

@ -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: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:4:1 in block: insert(a, b)…
↳ from test/tests/merge nested mutable error.ans:3:18 in call: _ ↳ 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: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:26:1 in block: if(fn . "current checkpoint")…
↳ from stdlib/script.ans:25:8 in call: _ ↳ from stdlib/script.ans:25:8 in call: _
↳ from stdlib/script.ans:39:9 in call: value(s)! ↳ from stdlib/script.ans:39:9 in call: value(s)!

View file

@ -0,0 +1,5 @@
--# run #--
--- return ---
5
--# saved #--
{}

View file

@ -0,0 +1,5 @@
(
"hello"
!
len
)