aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bitbucket@bruce-hill.com>2018-05-30 13:07:08 -0700
committerBruce Hill <bitbucket@bruce-hill.com>2018-05-30 13:07:15 -0700
commitf9229c5e91ee505cefd48935c84d82f607110284 (patch)
treec771485f471bbe7ff96fed1111473771109c202d
parente5d9879a7972fa09e8c9e8f88642bbcc27e0c5a1 (diff)
Better parse error reporting.
-rw-r--r--core/collections.nom4
-rw-r--r--nomsu.lua19
-rwxr-xr-xnomsu.moon18
-rw-r--r--nomsu.peg61
4 files changed, 66 insertions, 36 deletions
diff --git a/core/collections.nom b/core/collections.nom
index 81ff3d2..91c0c10 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -110,8 +110,8 @@ immediately
return %flat
parse [entries in %dict] as: {key:%k, value:%v} for %k = %v in %dict
- parse [keys in %dict] as: %k for %k = %v in %dict
- parse [values in %dict] as: %v for %k = %v in %dict
+ parse [keys in %dict, keys of %dict] as: %k for %k = %v in %dict
+ parse [values in %dict, values of %dict] as: %v for %k = %v in %dict
# Metatable stuff
immediately
diff --git a/nomsu.lua b/nomsu.lua
index 394af49..3fb7b92 100644
--- a/nomsu.lua
+++ b/nomsu.lua
@@ -190,6 +190,10 @@ do
if seen_errors[start_pos] then
return true
end
+ if utils.size(seen_errors) >= 10 then
+ seen_errors[start_pos + 1] = colored.bright(colored.yellow(colored.onred("Too many errors, canceling parsing...")))
+ return #src
+ end
local err_pos = start_pos
local text_loc = userdata.source:sub(err_pos, err_pos)
local line_no = text_loc:get_line_number()
@@ -197,14 +201,16 @@ do
local prev_line = line_no == 1 and "" or src:sub(LINE_STARTS[src][line_no - 1] or 1, LINE_STARTS[src][line_no] - 2)
local err_line = src:sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no + 1] or 0) - 2)
local next_line = src:sub(LINE_STARTS[src][line_no + 1] or -1, (LINE_STARTS[src][line_no + 2] or 0) - 2)
- local pointer = ("-"):rep(err_pos - LINE_STARTS[src][line_no]) .. "^"
- err_msg = (err_msg or "Parse error") .. " at " .. tostring(userdata.source.filename) .. ":" .. tostring(line_no) .. ":\n"
+ local i = err_pos - LINE_STARTS[src][line_no]
+ local pointer = ("-"):rep(i) .. "^"
+ err_msg = colored.bright(colored.yellow(colored.onred((err_msg or "Parse error") .. " at " .. tostring(userdata.source.filename) .. ":" .. tostring(line_no) .. ":")))
if #prev_line > 0 then
- err_msg = err_msg .. ("\n" .. prev_line)
+ err_msg = err_msg .. ("\n" .. colored.dim(prev_line))
end
- err_msg = err_msg .. "\n" .. tostring(err_line) .. "\n" .. tostring(pointer)
+ err_line = colored.white(err_line:sub(1, i)) .. colored.bright(colored.red(err_line:sub(i + 1, i + 1))) .. colored.dim(err_line:sub(i + 2, -1))
+ err_msg = err_msg .. "\n" .. tostring(err_line) .. "\n" .. tostring(colored.red(pointer))
if #next_line > 0 then
- err_msg = err_msg .. ("\n" .. next_line)
+ err_msg = err_msg .. ("\n" .. colored.dim(next_line))
end
seen_errors[start_pos] = err_msg
return true
@@ -326,7 +332,8 @@ do
end
errors = _accum_0
end
- error(concat(errors, "\n\n"), 0)
+ io.stderr:write(concat(errors, "\n\n") .. "\n")
+ os.exit()
end
return tree
end,
diff --git a/nomsu.moon b/nomsu.moon
index c162246..34e9c06 100755
--- a/nomsu.moon
+++ b/nomsu.moon
@@ -164,6 +164,9 @@ NOMSU_DEFS = with {}
seen_errors = userdata.errors
if seen_errors[start_pos]
return true
+ if utils.size(seen_errors) >= 10
+ seen_errors[start_pos+1] = colored.bright colored.yellow colored.onred "Too many errors, canceling parsing..."
+ return #src
err_pos = start_pos
--if src\sub(err_pos,err_pos)\match("[\r\n]")
-- err_pos += #src\match("[ \t\n\r]*", err_pos)
@@ -173,11 +176,13 @@ NOMSU_DEFS = with {}
prev_line = line_no == 1 and "" or src\sub(LINE_STARTS[src][line_no-1] or 1, LINE_STARTS[src][line_no]-2)
err_line = src\sub(LINE_STARTS[src][line_no], (LINE_STARTS[src][line_no+1] or 0)-2)
next_line = src\sub(LINE_STARTS[src][line_no+1] or -1, (LINE_STARTS[src][line_no+2] or 0)-2)
- pointer = ("-")\rep(err_pos-LINE_STARTS[src][line_no]) .. "^"
- err_msg = (err_msg or "Parse error").." at #{userdata.source.filename}:#{line_no}:\n"
- if #prev_line > 0 then err_msg ..= "\n"..prev_line
- err_msg ..= "\n#{err_line}\n#{pointer}"
- if #next_line > 0 then err_msg ..= "\n"..next_line
+ i = err_pos-LINE_STARTS[src][line_no]
+ pointer = ("-")\rep(i) .. "^"
+ err_msg = colored.bright colored.yellow colored.onred (err_msg or "Parse error").." at #{userdata.source.filename}:#{line_no}:"
+ if #prev_line > 0 then err_msg ..= "\n"..colored.dim(prev_line)
+ err_line = colored.white(err_line\sub(1, i))..colored.bright(colored.red(err_line\sub(i+1,i+1)))..colored.dim(err_line\sub(i+2,-1))
+ err_msg ..= "\n#{err_line}\n#{colored.red pointer}"
+ if #next_line > 0 then err_msg ..= "\n"..colored.dim(next_line)
--error(err_msg)
seen_errors[start_pos] = err_msg
return true
@@ -329,7 +334,8 @@ class NomsuCompiler
keys = utils.keys(userdata.errors)
table.sort(keys)
errors = [userdata.errors[k] for k in *keys]
- error(concat(errors, "\n\n"), 0)
+ io.stderr\write(concat(errors, "\n\n").."\n")
+ os.exit!
return tree
diff --git a/nomsu.peg b/nomsu.peg
index f260f86..0e782e9 100644
--- a/nomsu.peg
+++ b/nomsu.peg
@@ -10,9 +10,9 @@ shebang: "#!" [^%nl]* (!. / %nl)
inline_block (Block):
{| inline_statement (%ws* ";" %ws* inline_statement)+ |}
block (Block):
- {| statement (nodent (statement / (({} ([^%nl]* -> "Error while parsing block line") %userdata) => error)))+ |}
+ {| statement (nodent (statement / (({} ([^%nl]* -> "Unexpected character while parsing block line") %userdata) => error)))+ |}
-statement: (action / expression) (eol / (({} ([^%nl]* -> "Error while parsing line") %userdata) => error))
+statement: (action / expression) (eol / (({} ([^%nl]* -> "Unexpected character while parsing line") %userdata) => error))
inline_statement: inline_action / inline_expression
noindex_inline_expression:
@@ -21,8 +21,8 @@ noindex_inline_expression:
%ws* (inline_block / inline_action / inline_expression) %ws*
(comma %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")"
- / (({} ((!. / &%nl) -> 'Expected to find a ) before the end of the line') %userdata) => error)
- / (({} ([^%nl]* -> 'Error while parsing subexpression') %userdata) => error)
+ / (({} ((!. / &%nl) -> 'Line ended without finding a closing )-parenthesis') %userdata) => error)
+ / (({} ([^%nl]* -> 'Unexpected character while parsing subexpression') %userdata) => error)
)
)
inline_expression:
@@ -31,14 +31,21 @@ indented_expression:
indented_text / indented_nomsu / indented_list / indented_dict
/ ("(..)"? indent
(block / action / expression)
- (dedent / (({} (non_dedent_error -> "Error while parsing indented expression") %userdata) => error))
+ (dedent / (({} (non_dedent_error -> "Unexpected character while parsing indented expression") %userdata) => error))
)
expression:
- inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression
+ inline_expression
+ / (":" %ws* ((inline_block / inline_action / inline_expression) eol
+ / (({} (eol -> "Missing expression after the ':'") %userdata) => error)))
+ / indented_expression
inline_nomsu (EscapedNomsu): "\" {| inline_expression |}
indented_nomsu (EscapedNomsu):
- "\" {| (noindex_inline_expression / (":" %ws* (inline_block / inline_action / inline_expression) eol) / indented_expression) |}
+ "\" {|
+ noindex_inline_expression
+ / (":" %ws* ((inline_block / inline_action / inline_expression) eol
+ / (({} (eol -> "Missing expression after the ':'") %userdata) => error)))
+ / indented_expression |}
index_chain (IndexChain):
{| noindex_inline_expression ("." (text_word / noindex_inline_expression))+ |}
@@ -47,7 +54,8 @@ index_chain (IndexChain):
inline_action (Action):
{|
(inline_expression %ws*)* word (%ws* (inline_expression / word))*
- (%ws* ":" %ws* (inline_block / inline_action / inline_expression))?
+ (%ws* ":" %ws* (inline_block / inline_action / inline_expression
+ / (({} ('' -> "Missing expression after the ':'") %userdata) => error)))?
|}
action (Action):
{| (expression (dotdot? %ws*))* word ((dotdot? %ws*) (expression / word))* |}
@@ -61,7 +69,10 @@ inline_text (Text):
'"' {|
({~ (('\"' -> '"') / ('\\' -> '\') / %escaped_char / [^%nl\"])+ ~}
/ inline_text_interpolation)*
- |} ('"' / (({} ([^%nl]*->'Failed to find a closing " mark on the same line') %userdata) => error))
+ |} ('"' / (
+ (({} (eol->'Line ended before finding a closing double quotation mark') %userdata) => error)
+ /(({} ([^%nl]*->'Unexpected character while parsing Text') %userdata) => error)
+ ))
-- Have to use "%indent" instead of "indent" etc. to avoid messing up text lines that start with "#"
indented_text (Text):
@@ -70,7 +81,7 @@ indented_text (Text):
({~
(("\\" -> "\") / (("\" nodent "..") -> "")/ (%nl+ {~ %nodent -> "" ~}) / [^%nl\] / (!text_interpolation "\"))+
~} / text_interpolation)*
- |} (((!.) %dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Error while parsing Text") %userdata) => error))
+ |} (((!.) %dedent) / (&(%nl %dedent)) / (({} (non_dedent_error -> "Unexpected character while parsing Text") %userdata) => error))
inline_text_interpolation:
"\" (
variable / inline_list / inline_dict / inline_text
@@ -78,8 +89,8 @@ inline_text_interpolation:
%ws* (inline_block / inline_action / inline_expression) %ws*
(comma %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")"
- / (({} (&%nl -> 'Expected to find a ")" before the end of the line') %userdata) => error)
- / (({} ([^%nl]* -> 'Error while parsing text interpolation') %userdata) => error))
+ / (({} (&%nl -> 'Line ended without finding a closing )-parenthesis') %userdata) => error)
+ / (({} ([^%nl]* -> 'Unexpected character while parsing Text interpolation') %userdata) => error))
)
)
text_interpolation:
@@ -94,12 +105,16 @@ variable (Var): "%" { (%ident_char+ ((!"'" %operator_char+) / %ident_char+)*)? }
inline_list (List):
!('[..]')
- "[" %ws* {| (inline_list_item (comma inline_list_item)* comma?)? |} %ws*
- ("]" / (({} ([^%nl]*->"Failed to find a closing ] on the same line") %userdata) => error))
+ "[" %ws*
+ {| (inline_list_item (comma inline_list_item)* comma?)? |} %ws*
+ ("]" / (","? (
+ (({} (eol->"Line ended before finding a closing ]-bracket") %userdata) => error)
+ /(({} ([^%nl]*->"Unexpected character while parsing List") %userdata) => error)
+ )))
indented_list (List):
"[..]" indent
{| list_line (nodent list_line)* |}
- (dedent / (({} (non_dedent_error -> "Error while parsing list") %userdata) => error))
+ (dedent / ((","? {} (non_dedent_error -> "Unexpected character while parsing List") %userdata) => error))
list_line:
((action / expression) !comma)
/ (inline_list_item (comma list_line?)?)
@@ -107,20 +122,22 @@ inline_list_item: inline_block / inline_action / inline_expression
inline_dict (Dict):
!('{..}')
- "{" %ws* {| (inline_dict_entry (comma inline_dict_entry)*)? |} %ws*
- ("}"
- / (({} (%ws* comma? (!. / &%nl)->"Failed to find a closing } on the same line") %userdata) => error)
- / (({} ([^%nl]*->"Error while parsing dictionary") %userdata) => error))
+ "{" %ws*
+ {| (inline_dict_entry (comma inline_dict_entry)*)? |} %ws*
+ ("}" / (","? (
+ (({} (%ws* eol->"Line ended before finding a closing }-brace") %userdata) => error)
+ / (({} ([^%nl]*->"Unexpected character while parsing Dictionary") %userdata) => error)
+ )))
indented_dict (Dict):
"{..}" indent
{| dict_line (nodent dict_line)* |}
- (dedent / (({} (non_dedent_error -> "Error while parsing dict") %userdata) => error))
+ (dedent / ((","? {} (non_dedent_error -> "Unexpected character while parsing Dictionary") %userdata) => error))
dict_line:
(dict_entry !comma) / (inline_dict_entry (comma dict_line?)?)
dict_entry(DictEntry):
- {| dict_key %ws* ":" %ws* (action / expression) |}
+ {| dict_key (%ws* ":" %ws* (action / expression))? |}
inline_dict_entry(DictEntry):
- {| dict_key %ws* (":" %ws* (inline_block / inline_action / inline_expression)?) |}
+ {| dict_key (%ws* ":" %ws* (inline_block / inline_action / inline_expression)?)? |}
dict_key:
text_word / inline_expression