diff --git a/anselme/ast/String.lua b/anselme/ast/String.lua index 2190098..4aa82a7 100644 --- a/anselme/ast/String.lua +++ b/anselme/ast/String.lua @@ -16,7 +16,7 @@ local String = ast.abstract.Node { end, _format = function(self) - return ("%q"):format(self.string) + return ("\"%s\""):format(self.string:gsub("[\n\t\"]", { ["\n"] = "\\n", ["\t"] = "\\t", ["\""] = "\\\"" })) end, to_lua = function(self, state) diff --git a/anselme/ast/Struct.lua b/anselme/ast/Struct.lua index 51712fa..2dd8a53 100644 --- a/anselme/ast/Struct.lua +++ b/anselme/ast/Struct.lua @@ -113,7 +113,7 @@ Struct = ast.abstract.Runtime { if v ~= nil then return v else - error(("key %q is undefined in %s"):format(key:format(), self.type), 0) + error(("key %s is undefined in %s"):format(key:format(), self.type), 0) end end, get_strict = function(self, key) diff --git a/anselme/parser/expression/comment.lua b/anselme/parser/expression/comment.lua index 237ef6f..ca693cf 100644 --- a/anselme/parser/expression/comment.lua +++ b/anselme/parser/expression/comment.lua @@ -33,7 +33,7 @@ comment = primary { table.insert(content_list, "/*") table.insert(content_list, subcomment) table.insert(content_list, "*/") - -- consumed everything until end-of-line/file, close your eyes and imagine the text has been closed + -- consumed everything until end-of-string, close your eyes and imagine the text has been closed elseif rem:match("^\n") or not rem:match("[^%s]") then rem = "*/" .. rem source:increment(-2) diff --git a/anselme/parser/expression/primary/string.lua b/anselme/parser/expression/primary/string.lua index fd6ce21..4fd5dc0 100644 --- a/anselme/parser/expression/primary/string.lua +++ b/anselme/parser/expression/primary/string.lua @@ -18,9 +18,9 @@ local escape_code = { return primary { type = "string", -- interpolation type - used for errors start_pattern = "\"", -- pattern that start the string interpolation - stop_char = "\"", -- character that stops the string interpolation - must be a single character! + stop_char = "\"", -- character that stops the string interpolation - must be a single one byte character! - allow_implicit_stop = false, -- set to true to allow the string to be closed implicitely when reaching the end of the expression or limit_pattern + allow_implicit_stop = false, -- set to true to allow the string to be closed implicitely when reaching the end of the expression, line, or limit_pattern interpolation = StringInterpolation, @@ -35,10 +35,11 @@ return primary { local start_source = source:clone() local rem = source:consume(str:match("^("..self.start_pattern..")(.-)$")) + local string_pattern = "^([^%{%\\"..stop_pattern..(self.allow_implicit_stop and "\n" or "").."]*)(.-)$" while not rem:match("^"..stop_pattern) do local text_source = source:clone() local text - text, rem = rem:match("^([^\n%{%\\"..stop_pattern.."]*)(.-)$") -- get all text until something potentially happens + text, rem = rem:match(string_pattern) -- get all text until something potentially happens -- cut the text prematurely at limit_pattern if relevant if self.allow_implicit_stop and limit_pattern and text:match(limit_pattern) then @@ -53,7 +54,7 @@ return primary { -- interpolated expression if rem:match("^%{") then - local opts = options:with { limit_pattern = "%}", allow_newlines = false } + local opts = options:with { limit_pattern = "%}", allow_newlines = not self.allow_implicit_stop } local ok, exp ok, exp, rem = pcall(expression_to_ast, source, opts, source:consume(rem:match("^(%{)(.*)$"))) if not ok then error("invalid expression inside interpolation: "..exp, 0) end @@ -65,7 +66,7 @@ return primary { elseif rem:match("^\\") then text, rem = source:consume(rem:match("^(\\(.))(.*)$")) interpolation:insert(String:new(escape_code[text] or text)) - -- consumed everything until end-of-line/file, implicit stop allowed, close your eyes and imagine the text has been closed + -- consumed everything until end-of-string, implicit stop allowed, close your eyes and imagine the text has been closed elseif self.allow_implicit_stop and (rem:match("^\n") or not rem:match("[^%s]")) then rem = self.stop_char .. rem source:increment(-1) diff --git a/anselme/parser/expression/primary/text.lua b/anselme/parser/expression/primary/text.lua index 6414015..0d5d12f 100644 --- a/anselme/parser/expression/primary/text.lua +++ b/anselme/parser/expression/primary/text.lua @@ -1,7 +1,7 @@ local string = require("anselme.parser.expression.primary.string") local ast = require("anselme.ast") -local TextInterpolation, Translatable = ast.TextInterpolation, ast.Translatable +local TextInterpolation, Translatable, String = ast.TextInterpolation, ast.Translatable, ast.String return string { type = "text", @@ -16,7 +16,7 @@ return string { -- remove terminal space local last = interpolation.list[#interpolation.list] - if ast.String:is(last) then last.string = last.string:gsub("[ \t]$", "") end + if String:is(last) then last.string = last.string:gsub("[ \t]$", "") end return Translatable:new(interpolation):set_source(start_source), rem end diff --git a/ideas.md b/ideas.md index d265bab..09a7937 100644 --- a/ideas.md +++ b/ideas.md @@ -23,7 +23,7 @@ Issue: dispatch is decided before evaluating default values. --- -Multiline string and comments? +Multiline comments? # Can be done later diff --git a/test/results/custom text formatting.ans b/test/results/custom text formatting.ans index 2ffbbd0..272e6ed 100644 --- a/test/results/custom text formatting.ans +++ b/test/results/custom text formatting.ans @@ -1,7 +1,6 @@ --# run #-- --- text --- -| {}"" {}"\"Name: Darmanin\\\ -Age: 38\"" {}"" | +| {}"" {}"\"Name: Darmanin\nAge: 38\"" {}"" | --- return --- () --# saved #-- diff --git a/test/results/loop decorator.ans b/test/results/loop decorator.ans index ffd7c0a..9c5ccd3 100644 --- a/test/results/loop decorator.ans +++ b/test/results/loop decorator.ans @@ -1,25 +1,15 @@ --# run #-- --- text --- -| {}"" {}"1" {}"" {}"\ -" {}"" | -| {}"" {}"2" {}"" {}"\ -" {}"" | -| {}"" {}"3" {}"" {}"\ -" {}"" | -| {}"" {}"4" {}"" {}"\ -" {}"" | -| {}"" {}"5" {}"" {}"\ -" {}"" | -| {}"" {}"6" {}"" {}"\ -" {}"" | -| {}"" {}"7" {}"" {}"\ -" {}"" | -| {}"" {}"8" {}"" {}"\ -" {}"" | -| {}"" {}"9" {}"" {}"\ -" {}"" | -| {}"" {}"10" {}"" {}"\ -" {}"" | +| {}"" {}"1" {}"" | +| {}"" {}"2" {}"" | +| {}"" {}"3" {}"" | +| {}"" {}"4" {}"" | +| {}"" {}"5" {}"" | +| {}"" {}"6" {}"" | +| {}"" {}"7" {}"" | +| {}"" {}"8" {}"" | +| {}"" {}"9" {}"" | +| {}"" {}"10" {}"" | --- text --- | {}"" {}"11" {}"" | --- return --- diff --git a/test/results/multiline string.ans b/test/results/multiline string.ans new file mode 100644 index 0000000..fd89f6c --- /dev/null +++ b/test/results/multiline string.ans @@ -0,0 +1,5 @@ +--# run #-- +--- return --- +"foo\nbar\n\ta\n\tb\n\t c\n d" +--# saved #-- +{} \ No newline at end of file diff --git a/test/results/string escaping.ans b/test/results/string escaping.ans index eba151f..c8e2149 100644 --- a/test/results/string escaping.ans +++ b/test/results/string escaping.ans @@ -4,10 +4,9 @@ --- text --- | {}"quote " {}"\"" {}"" | --- text --- -| {}"other codes " {}"\ -" {}" " {}"\\" {}" " {}"\9" {}" " {}"{" {}"braces}" | +| {}"other codes " {}"\n" {}" " {}"\" {}" " {}"\t" {}" " {}"{" {}"braces}" | --- text --- -| {}"" {}"escaping expressions abc and {stuff} \\ and quotes \"" {}"" | +| {}"" {}"escaping expressions abc and {stuff} \ and quotes \"" {}"" | --- return --- () --# saved #-- diff --git a/test/results/text escaping.ans b/test/results/text escaping.ans index 8a2950a..85a669f 100644 --- a/test/results/text escaping.ans +++ b/test/results/text escaping.ans @@ -4,8 +4,7 @@ --- text --- | {}"quote " {}"\"" {}"" | --- text --- -| {}"other codes " {}"\ -" {}" " {}"\\" {}" " {}"\9" {}"" | +| {}"other codes " {}"\n" {}" " {}"\" {}" " {}"\t" {}"" | --- text --- | {}"decorators " {}"#" {}" tag " {}"~" {}" condition " {}"$" {}" fn" | --- text --- diff --git a/test/tests/loop decorator.ans b/test/tests/loop decorator.ans index 9f7547f..9c771da 100644 --- a/test/tests/loop decorator.ans +++ b/test/tests/loop decorator.ans @@ -1,5 +1,5 @@ :i = 0 -while($()(i += 1; i <= 10), $| {i}\n |!) +while($()(i += 1; i <= 10), $| {i} |!) |{i} diff --git a/test/tests/multiline string.ans b/test/tests/multiline string.ans new file mode 100644 index 0000000..43f3d69 --- /dev/null +++ b/test/tests/multiline string.ans @@ -0,0 +1,6 @@ +"foo +bar + a + b + c + d"