Fixed up comment generation to old standards

This commit is contained in:
Bruce Hill 2018-07-14 14:41:17 -07:00
parent 01a4f36398
commit d535dc5794
7 changed files with 162 additions and 157 deletions

View File

@ -1,37 +1,34 @@
-- Nomsu version 2 -- Nomsu version 2
file (File): file (File):
%nl*
{:curr_indent: ' '* :} {:curr_indent: ' '* :}
comment? blank_lines?
(chunk (nl_nodent chunk_delimeter nl_nodent chunk)*)? (chunk (nl_nodent chunk_delimeter nl_nodent chunk)*)?
%nl* blank_lines?
(!! .+ -> "Parse error" !!)? (!! .+ -> "Parse error" !!)?
nodent: =curr_indent !(" ") nodent: =curr_indent !(" ")
indent: =curr_indent " " indent: =curr_indent " "
blank_lines: %nl (%ws* %nl)* blank_lines: %nl ((nodent comment / %ws*) %nl)*
eol: (!. / &%nl) eol: %ws* eol_comment? (!. / &%nl)
comment (Comment):
!inline_comment
"#" {~ [^%nl]* (blank_lines (indent -> '') [^%nl]*)* ~}
inline_comment (Comment):
"#(" {~ (inline_comment / [^%nl])* ~} ")#"
nl_nodent: blank_lines nodent nl_nodent: blank_lines nodent
nl_indent: blank_lines {:curr_indent: indent :} nl_indent: blank_lines {:curr_indent: indent :} (comment nl_nodent)?
chunk: block / ((comment nl_nodent)* (action / expression)? (nl_nodent comment)*) comment:
chunk_delimeter: ("~")^+3 "#" (({} {~ [^%nl]* ((%nl (!indent %ws* %nl)*) (indent -> '') [^%nl]*)* ~} %userdata) => add_comment)
eol_comment:
"#" (({} {[^%nl]*} %userdata) => add_comment)
chunk: block / action / expression
chunk_delimeter: ("~")^+3 eol
inline_block (Block): inline_block (Block):
inline_statement (%ws* ";" %ws* inline_statement)+ (%ws* inline_comment)* inline_statement (%ws* ";" %ws* inline_statement)+
block (Block): block (Block):
block_line (nl_nodent block_line)+ (nl_nodent comment)* statement (nl_nodent statement)+
block_line:
statement %ws* (!! [^%nl]+ -> "Unexpected character while parsing block line" !!)?
statement: (comment nl_nodent)* (action / expression) %ws* (!! [^%nl]+ -> "Unexpected character while parsing line" !!)? statement: (action / expression) (eol / (!! [^%nl]+ -> "Unexpected character while parsing line" !!))
inline_statement: (inline_comment %ws*)* (inline_action / inline_expression) inline_statement: (inline_action / inline_expression)
noindex_inline_expression: noindex_inline_expression:
number / variable / inline_text / inline_list / inline_dict / inline_nomsu number / variable / inline_text / inline_list / inline_dict / inline_nomsu
@ -39,22 +36,21 @@ noindex_inline_expression:
%ws* (inline_block / inline_action / inline_expression) %ws* %ws* (inline_block / inline_action / inline_expression) %ws*
(%ws* ',' %ws* (inline_block / inline_action / inline_expression) %ws*)* (%ws* ',' %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")" (")"
/ (!! %ws* eol -> 'Line ended without finding a closing )-parenthesis' !!) / (!! eol -> 'Line ended without finding a closing )-parenthesis' !!)
/ (!! [^%nl]+ -> 'Unexpected character while parsing subexpression' !!) / (!! [^%nl]+ -> 'Unexpected character while parsing subexpression' !!)
) )
) )
inline_expression: index_chain / noindex_inline_expression inline_expression: index_chain / noindex_inline_expression
indented_expression: indented_expression:
indented_text / indented_nomsu / indented_list / indented_dict / ({| indented_text / indented_nomsu / indented_list / indented_dict / ({|
("(..)" / ":")? nl_indent (comment nl_nodent)* ("(..)")? nl_indent
(block / action / expression) (block / action / expression) (nl_nodent comment)*
(!! [^%nl]+ -> "Unexpected character while parsing indented expression" !!)? (!! [^%nl]+ -> "Unexpected character while parsing indented expression" !!)?
|} -> unpack) |} -> unpack)
expression: expression:
inline_expression inline_expression
/ (":" %ws* / (":" %ws*
(!! eol -> "Missing expression after the ':'" !!)? (inline_block / inline_action / inline_expression / (!! '' -> "Missing expression after the ':'" !!)))
(inline_block / inline_action / inline_expression) %ws* eol)
/ indented_expression / indented_expression
inline_nomsu (EscapedNomsu): "\" inline_expression inline_nomsu (EscapedNomsu): "\" inline_expression
@ -62,8 +58,7 @@ indented_nomsu (EscapedNomsu):
"\" ( "\" (
noindex_inline_expression noindex_inline_expression
/ (":" %ws* / (":" %ws*
(!! eol -> "Missing expression after the '\:'" !!)? (inline_block / inline_action / inline_expression) (!! '' -> "Missing expression after the '\:'" !!))
(inline_block / inline_action / inline_expression) %ws* eol)
/ indented_expression) / indented_expression)
index_chain (IndexChain): index_chain (IndexChain):
@ -72,23 +67,21 @@ index_chain (IndexChain):
-- Actions need either at least 1 word, or at least 2 tokens -- Actions need either at least 1 word, or at least 2 tokens
inline_action (Action): inline_action (Action):
!chunk_delimeter !chunk_delimeter
(inline_comment %ws*)* ( (inline_expression (%ws* (inline_expression / word))+)
( (inline_expression ((%ws* inline_comment)* %ws* (inline_expression / word))+) / (word (%ws* (inline_expression / word))*))
/ (word ((%ws* inline_comment)* %ws* (inline_expression / word))*)) (%ws* ":" %ws* (inline_block / inline_action / inline_expression
((%ws* inline_comment)* %ws* ":" %ws* (inline_block / inline_action / inline_expression
/ (!! '' -> "Missing expression after the ':'" !!)))? / (!! '' -> "Missing expression after the ':'" !!)))?
action (Action): action (Action):
!chunk_delimeter !chunk_delimeter
(inline_comment %ws*)* ( (expression ((nl_nodent "..")? %ws* (expression / word))+)
( (expression (((nl_nodent comment)* nl_nodent "..")? %ws* (inline_comment %ws*)* (expression / word))+) / (word ((nl_nodent "..")? %ws* (expression / word))*))
/ (word (((nl_nodent comment)* nl_nodent "..")? %ws* (inline_comment %ws*)* (expression / word))*))
word: !number { %operator_char+ / %ident_char+ } word: !number { %operator_char+ / %ident_char+ }
text_word (Text): word text_word (Text): word
inline_text (Text): inline_text (Text):
!('".."' %ws* eol) !('".."' eol)
'"' '"'
({~ (('\"' -> '"') / ('\\' -> '\') / %escaped_char / [^%nl\"])+ ~} ({~ (('\"' -> '"') / ('\\' -> '\') / %escaped_char / [^%nl\"])+ ~}
/ inline_text_interpolation)* / inline_text_interpolation)*
@ -102,16 +95,16 @@ inline_text_interpolation:
%ws* (inline_block / inline_action / inline_expression) %ws* %ws* (inline_block / inline_action / inline_expression) %ws*
(%ws* ',' %ws* (inline_block / inline_action / inline_expression) %ws*)* (%ws* ',' %ws* (inline_block / inline_action / inline_expression) %ws*)*
(")" (")"
/ (!! %ws* eol -> 'Line ended without finding a closing )-parenthesis' !!) / (!! eol -> 'Line ended without finding a closing )-parenthesis' !!)
/ (!! [^%nl]+ -> 'Unexpected character while parsing Text interpolation' !!))) / (!! [^%nl]+ -> 'Unexpected character while parsing Text interpolation' !!)))
) )
indented_text (Text): indented_text (Text):
'".."' %ws* %nl {:curr_indent: indent :} '".."' eol %nl {:curr_indent: indent :}
(indented_plain_text / text_interpolation / {~ blank_lines (=curr_indent -> "") ~})* (indented_plain_text / text_interpolation / {~ blank_lines (=curr_indent -> "") ~})*
(!! [^%nl]+ -> "Unexpected character while parsing Text" !!)? (!! [^%nl]+ -> "Unexpected character while parsing Text" !!)?
indented_plain_text (Text): indented_plain_text (Text):
{~ (("\\" -> "\") / (("\" (blank_lines =curr_indent comment)* blank_lines =curr_indent "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+ {~ (("\\" -> "\") / (("\" blank_lines =curr_indent "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+
(blank_lines (=curr_indent -> ""))* ~} (blank_lines (=curr_indent -> ""))* ~}
text_interpolation: text_interpolation:
inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..") inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..")
@ -127,16 +120,16 @@ inline_list (List):
"[" %ws* "[" %ws*
(inline_list_item (%ws* ',' %ws* inline_list_item)* (%ws* ',')?)? %ws* (inline_list_item (%ws* ',' %ws* inline_list_item)* (%ws* ',')?)? %ws*
("]" / (","? ( ("]" / (","? (
(!! %ws* eol -> "Line ended before finding a closing ]-bracket" !!) (!! eol -> "Line ended before finding a closing ]-bracket" !!)
/(!! [^%nl]+ -> "Unexpected character while parsing List" !!)? /(!! [^%nl]+ -> "Unexpected character while parsing List" !!)?
))) )))
indented_list (List): indented_list (List):
"[..]" nl_indent (comment nl_nodent)* "[..]" eol nl_indent
list_line (nl_nodent list_line)* list_line (nl_nodent list_line)* (nl_nodent comment)*
(","? (!! [^%nl]+ -> "Unexpected character while parsing List" !!))? (","? (!! [^%nl]+ -> "Unexpected character while parsing List" !!))?
list_line: list_line:
(inline_list_item %ws* "," %ws*)+ %ws* eol (inline_list_item %ws* "," %ws*)+ eol
/ (inline_list_item %ws* "," %ws*)* (action / expression) / (inline_list_item %ws* "," %ws*)* (action / expression) eol
inline_list_item: inline_block / inline_action / inline_expression inline_list_item: inline_block / inline_action / inline_expression
inline_dict (Dict): inline_dict (Dict):
@ -144,16 +137,16 @@ inline_dict (Dict):
"{" %ws* "{" %ws*
(inline_dict_entry (%ws* ',' %ws* inline_dict_entry)*)? %ws* (inline_dict_entry (%ws* ',' %ws* inline_dict_entry)*)? %ws*
("}" / (","? ( ("}" / (","? (
(!! %ws* eol -> "Line ended before finding a closing }-brace" !!) (!! eol -> "Line ended before finding a closing }-brace" !!)
/ (!! [^%nl]* -> "Unexpected character while parsing Dictionary" !!) / (!! [^%nl]* -> "Unexpected character while parsing Dictionary" !!)
))) )))
indented_dict (Dict): indented_dict (Dict):
"{..}" nl_indent (comment nl_nodent)* "{..}" eol nl_indent
dict_line ((nl_nodent comment)* nl_nodent dict_line)* (nl_nodent comment)* dict_line (nl_nodent dict_line)* (nl_nodent comment)*
(","? (!! [^%nl]+ -> "Unexpected character while parsing Dictionary" !!))? (","? (!! [^%nl]+ -> "Unexpected character while parsing Dictionary" !!))?
dict_line: dict_line:
(inline_dict_entry %ws* "," %ws*)+ %ws* eol (inline_dict_entry %ws* "," %ws*)+ eol
/ (inline_dict_entry %ws* "," %ws*)* dict_entry / (inline_dict_entry %ws* "," %ws*)* dict_entry eol
dict_entry(DictEntry): dict_entry(DictEntry):
dict_key (%ws* ":" %ws* (action / expression))? dict_key (%ws* ":" %ws* (action / expression))?
inline_dict_entry(DictEntry): inline_dict_entry(DictEntry):

View File

@ -607,7 +607,7 @@ do
end end
local bit_lua = self:compile(bit) local bit_lua = self:compile(bit)
if not (bit_lua.is_value) then if not (bit_lua.is_value) then
local src = ' ' .. gsub(tostring(self:tree_to_nomsu(bit)), '\n', '\n ') local src = ' ' .. gsub(tostring(recurse(bit)), '\n', '\n ')
local line = tostring(bit.source.filename) .. ":" .. tostring(files.get_line_number(files.read(bit.source.filename), bit.source.start)) local line = tostring(bit.source.filename) .. ":" .. tostring(files.get_line_number(files.read(bit.source.filename), bit.source.start))
self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.") self:compile_error(bit, "Cannot use:\n%s\nas a string interpolation value, since it's not an expression.")
end end
@ -719,27 +719,45 @@ do
end end
NomsuCompiler.tree_to_nomsu = function(self, tree, options) NomsuCompiler.tree_to_nomsu = function(self, tree, options)
options = options or { } options = options or { }
local comment_i = 0 if not (options.pop_comments) then
local pop_comments local comments
pop_comments = function(pos) do
if not (tree.comments) then local _accum_0 = { }
return '' local _len_0 = 1
end for p, c in pairs(tree.comments or { }) do
local nomsu = NomsuCode(tree.source) _accum_0[_len_0] = {
for i = comment_i + 1, #tree.comments do comment = c,
comment_i = i pos = p
local comment = tree.comments[i] }
if comment.source.start > pos then _len_0 = _len_0 + 1
break
end end
nomsu:append("#" .. (gsub(comment[1], "\n", "\n ")) .. "\n") comments = _accum_0
end end
if #nomsu.bits == 0 then table.sort(comments, function(a, b)
return '' return a.pos < b.pos
end)
local comment_i = 1
options.pop_comments = function(pos)
local nomsu = NomsuCode(tree.source)
while comments[comment_i] and comments[comment_i].pos <= pos do
local comment = comments[comment_i].comment
nomsu:append("#" .. (gsub(comment, "\n", "\n ")) .. "\n")
if comment:match("^\n.") then
nomsu:append("\n")
end
comment_i = comment_i + 1
end
return #nomsu.bits == 0 and '' or nomsu
end end
return nomsu
end end
local inline, can_use_colon = options.inline, options.can_use_colon local recurse
recurse = function(t, opts)
opts = opts or { }
opts.pop_comments = options.pop_comments
return self:tree_to_nomsu(t, opts)
end
local inline, can_use_colon, pop_comments
inline, can_use_colon, pop_comments = options.inline, options.can_use_colon, options.pop_comments
local _exp_0 = tree.type local _exp_0 = tree.type
if "File" == _exp_0 then if "File" == _exp_0 then
if inline then if inline then
@ -751,8 +769,9 @@ do
nomsu:append("\n\n" .. tostring(("~"):rep(80)) .. "\n\n") nomsu:append("\n\n" .. tostring(("~"):rep(80)) .. "\n\n")
end end
nomsu:append(pop_comments(chunk.source.start)) nomsu:append(pop_comments(chunk.source.start))
nomsu:append(self:tree_to_nomsu(chunk)) nomsu:append(recurse(chunk))
end end
nomsu:append(pop_comments(tree.source.stop))
return nomsu return nomsu
elseif "Action" == _exp_0 then elseif "Action" == _exp_0 then
if inline then if inline then
@ -764,7 +783,7 @@ do
end end
nomsu:append(bit) nomsu:append(bit)
else else
local arg_nomsu = self:tree_to_nomsu(bit, { local arg_nomsu = recurse(bit, {
inline = true inline = true
}) })
if not (arg_nomsu) then if not (arg_nomsu) then
@ -800,7 +819,7 @@ do
elseif bit.type == "Block" then elseif bit.type == "Block" then
arg_nomsu = nil arg_nomsu = nil
else else
arg_nomsu = self:tree_to_nomsu(bit, { arg_nomsu = recurse(bit, {
inline = true inline = true
}) })
end end
@ -822,7 +841,7 @@ do
next_space = " " next_space = " "
end end
else else
arg_nomsu = self:tree_to_nomsu(bit, { arg_nomsu = recurse(bit, {
can_use_colon = true can_use_colon = true
}) })
if not (arg_nomsu) then if not (arg_nomsu) then
@ -850,11 +869,11 @@ do
return nomsu return nomsu
end end
elseif "EscapedNomsu" == _exp_0 then elseif "EscapedNomsu" == _exp_0 then
local nomsu = self:tree_to_nomsu(tree[1], { local nomsu = recurse(tree[1], {
inline = true inline = true
}) })
if nomsu == nil and not inline then if nomsu == nil and not inline then
nomsu = self:tree_to_nomsu(tree[1]) nomsu = recurse(tree[1])
return nomsu and NomsuCode(tree.source, "\\:\n ", pop_comments(tree.source.start), nomsu) return nomsu and NomsuCode(tree.source, "\\:\n ", pop_comments(tree.source.start), nomsu)
end end
return nomsu and NomsuCode(tree.source, "\\(", nomsu, ")") return nomsu and NomsuCode(tree.source, "\\(", nomsu, ")")
@ -865,7 +884,7 @@ do
if i > 1 then if i > 1 then
nomsu:append("; ") nomsu:append("; ")
end end
local line_nomsu = self:tree_to_nomsu(line, { local line_nomsu = recurse(line, {
inline = true inline = true
}) })
if not (line_nomsu) then if not (line_nomsu) then
@ -878,7 +897,7 @@ do
local nomsu = NomsuCode(tree.source) local nomsu = NomsuCode(tree.source)
for i, line in ipairs(tree) do for i, line in ipairs(tree) do
nomsu:append(pop_comments(line.source.start)) nomsu:append(pop_comments(line.source.start))
line = assert(self:tree_to_nomsu(line, { line = assert(recurse(line, {
can_use_colon = true can_use_colon = true
}), "Could not convert line to nomsu") }), "Could not convert line to nomsu")
nomsu:append(line) nomsu:append(line)
@ -902,7 +921,7 @@ do
elseif bit.type == "Text" then elseif bit.type == "Text" then
nomsu:append(make_text(bit)) nomsu:append(make_text(bit))
else else
local interp_nomsu = assert(self:tree_to_nomsu(bit, { local interp_nomsu = assert(recurse(bit, {
inline = true inline = true
})) }))
if bit.type ~= "Var" and bit.type ~= "List" and bit.type ~= "Dict" and bit.type ~= "Text" then if bit.type ~= "Var" and bit.type ~= "List" and bit.type ~= "Dict" and bit.type ~= "Text" then
@ -915,7 +934,7 @@ do
end end
return NomsuCode(tree.source, '"', make_text(tree), '"') return NomsuCode(tree.source, '"', make_text(tree), '"')
else else
local inline_version = self:tree_to_nomsu(tree, { local inline_version = recurse(tree, {
inline = true inline = true
}) })
if inline_version and #inline_version <= MAX_LINE then if inline_version and #inline_version <= MAX_LINE then
@ -959,7 +978,7 @@ do
elseif bit.type == "Text" then elseif bit.type == "Text" then
nomsu:append(make_text(bit)) nomsu:append(make_text(bit))
else else
local interp_nomsu = self:tree_to_nomsu(bit, { local interp_nomsu = recurse(bit, {
inline = true inline = true
}) })
if interp_nomsu then if interp_nomsu then
@ -968,7 +987,7 @@ do
end end
nomsu:append("\\", interp_nomsu) nomsu:append("\\", interp_nomsu)
else else
interp_nomsu = assert(self:tree_to_nomsu(bit)) interp_nomsu = assert(recurse(bit))
if not (interp_nomsu) then if not (interp_nomsu) then
return nil return nil
end end
@ -987,7 +1006,7 @@ do
if inline then if inline then
local nomsu = NomsuCode(tree.source, "[") local nomsu = NomsuCode(tree.source, "[")
for i, item in ipairs(tree) do for i, item in ipairs(tree) do
local item_nomsu = self:tree_to_nomsu(item, { local item_nomsu = recurse(item, {
inline = true inline = true
}) })
if not (item_nomsu) then if not (item_nomsu) then
@ -1001,7 +1020,7 @@ do
nomsu:append("]") nomsu:append("]")
return nomsu return nomsu
else else
local inline_version = self:tree_to_nomsu(tree, { local inline_version = recurse(tree, {
inline = true inline = true
}) })
if inline_version and #inline_version <= MAX_LINE then if inline_version and #inline_version <= MAX_LINE then
@ -1016,7 +1035,7 @@ do
line_comments = '' line_comments = ''
end end
for i, item in ipairs(tree) do for i, item in ipairs(tree) do
local item_nomsu = self:tree_to_nomsu(item, { local item_nomsu = recurse(item, {
inline = true inline = true
}) })
if item_nomsu and #tostring(line) + #", " + #item_nomsu <= MAX_LINE then if item_nomsu and #tostring(line) + #", " + #item_nomsu <= MAX_LINE then
@ -1026,7 +1045,7 @@ do
line:append(item_nomsu) line:append(item_nomsu)
else else
if not (item_nomsu) then if not (item_nomsu) then
item_nomsu = self:tree_to_nomsu(item) item_nomsu = recurse(item)
if not (item_nomsu) then if not (item_nomsu) then
return nil return nil
end end
@ -1055,7 +1074,7 @@ do
if inline then if inline then
local nomsu = NomsuCode(tree.source, "{") local nomsu = NomsuCode(tree.source, "{")
for i, entry in ipairs(tree) do for i, entry in ipairs(tree) do
local entry_nomsu = self:tree_to_nomsu(entry, { local entry_nomsu = recurse(entry, {
inline = true inline = true
}) })
if not (entry_nomsu) then if not (entry_nomsu) then
@ -1069,7 +1088,7 @@ do
nomsu:append("}") nomsu:append("}")
return nomsu return nomsu
else else
local inline_version = self:tree_to_nomsu(tree, { local inline_version = recurse(tree, {
inline = true inline = true
}) })
if inline_version then if inline_version then
@ -1084,7 +1103,7 @@ do
line_comments = '' line_comments = ''
end end
for i, entry in ipairs(tree) do for i, entry in ipairs(tree) do
local entry_nomsu = self:tree_to_nomsu(entry) local entry_nomsu = recurse(entry)
if not (entry_nomsu) then if not (entry_nomsu) then
return nil return nil
end end
@ -1116,7 +1135,7 @@ do
end end
elseif "DictEntry" == _exp_0 then elseif "DictEntry" == _exp_0 then
local key, value = tree[1], tree[2] local key, value = tree[1], tree[2]
local key_nomsu = self:tree_to_nomsu(key, { local key_nomsu = recurse(key, {
inline = true inline = true
}) })
if not (key_nomsu) then if not (key_nomsu) then
@ -1127,7 +1146,7 @@ do
end end
local value_nomsu local value_nomsu
if value then if value then
value_nomsu = self:tree_to_nomsu(value, { value_nomsu = recurse(value, {
inline = true inline = true
}) })
else else
@ -1140,7 +1159,7 @@ do
if inline then if inline then
return nil return nil
end end
value_nomsu = self:tree_to_nomsu(value) value_nomsu = recurse(value)
if not (value_nomsu) then if not (value_nomsu) then
return nil return nil
end end
@ -1159,7 +1178,7 @@ do
end end
end end
if not (bit_nomsu) then if not (bit_nomsu) then
bit_nomsu = self:tree_to_nomsu(bit, { bit_nomsu = recurse(bit, {
inline = true inline = true
}) })
end end

View File

@ -383,7 +383,7 @@ with NomsuCompiler
string_buffer = "" string_buffer = ""
bit_lua = @compile(bit) bit_lua = @compile(bit)
unless bit_lua.is_value unless bit_lua.is_value
src = ' '..gsub(tostring(@tree_to_nomsu(bit)), '\n','\n ') src = ' '..gsub(tostring(recurse(bit)), '\n','\n ')
line = "#{bit.source.filename}:#{files.get_line_number(files.read(bit.source.filename), bit.source.start)}" line = "#{bit.source.filename}:#{files.get_line_number(files.read(bit.source.filename), bit.source.start)}"
@compile_error bit, @compile_error bit,
"Cannot use:\n%s\nas a string interpolation value, since it's not an expression." "Cannot use:\n%s\nas a string interpolation value, since it's not an expression."
@ -483,19 +483,25 @@ with NomsuCompiler
.tree_to_nomsu = (tree, options)=> .tree_to_nomsu = (tree, options)=>
options or= {} options or= {}
comment_i = 0 unless options.pop_comments
pop_comments = (pos)-> comments = [{comment:c, pos:p} for p,c in pairs(tree.comments or {})]
return '' unless tree.comments table.sort comments, (a,b)-> a.pos < b.pos
nomsu = NomsuCode(tree.source) comment_i = 1
for i=comment_i+1,#tree.comments options.pop_comments = (pos)->
comment_i = i nomsu = NomsuCode(tree.source)
comment = tree.comments[i] while comments[comment_i] and comments[comment_i].pos <= pos
break if comment.source.start > pos comment = comments[comment_i].comment
nomsu\append "#"..(gsub(comment[1], "\n", "\n ")).."\n" nomsu\append("#"..(gsub(comment, "\n", "\n ")).."\n")
if #nomsu.bits == 0 then return '' if comment\match("^\n.") then nomsu\append("\n") -- for aesthetics
return nomsu comment_i += 1
return #nomsu.bits == 0 and '' or nomsu
inline, can_use_colon = options.inline, options.can_use_colon recurse = (t, opts)->
opts or= {}
opts.pop_comments = options.pop_comments
return @tree_to_nomsu(t, opts)
{:inline, :can_use_colon, :pop_comments} = options
switch tree.type switch tree.type
when "File" when "File"
return nil if inline return nil if inline
@ -504,7 +510,8 @@ with NomsuCompiler
if i > 1 if i > 1
nomsu\append "\n\n#{("~")\rep(80)}\n\n" nomsu\append "\n\n#{("~")\rep(80)}\n\n"
nomsu\append pop_comments(chunk.source.start) nomsu\append pop_comments(chunk.source.start)
nomsu\append @tree_to_nomsu(chunk) nomsu\append recurse(chunk)
nomsu\append pop_comments(tree.source.stop)
return nomsu return nomsu
when "Action" when "Action"
@ -516,7 +523,7 @@ with NomsuCompiler
nomsu\append " " nomsu\append " "
nomsu\append bit nomsu\append bit
else else
arg_nomsu = @tree_to_nomsu(bit,inline:true) arg_nomsu = recurse(bit,inline:true)
return nil unless arg_nomsu return nil unless arg_nomsu
if bit.type == "Action" or bit.type == "Block" if bit.type == "Action" or bit.type == "Block"
if bit.type == "Action" and i == #tree if bit.type == "Action" and i == #tree
@ -539,7 +546,7 @@ with NomsuCompiler
else else
arg_nomsu = if last_colon == i-1 and bit.type == "Action" then nil arg_nomsu = if last_colon == i-1 and bit.type == "Action" then nil
elseif bit.type == "Block" then nil elseif bit.type == "Block" then nil
else @tree_to_nomsu(bit,inline:true) else recurse(bit,inline:true)
if arg_nomsu and line_len + #tostring(arg_nomsu) < MAX_LINE if arg_nomsu and line_len + #tostring(arg_nomsu) < MAX_LINE
if bit.type == "Action" if bit.type == "Action"
@ -557,7 +564,7 @@ with NomsuCompiler
line_len += #next_space + #tostring(arg_nomsu) line_len += #next_space + #tostring(arg_nomsu)
next_space = " " next_space = " "
else else
arg_nomsu = @tree_to_nomsu(bit, can_use_colon:true) arg_nomsu = recurse(bit, can_use_colon:true)
return nil unless arg_nomsu return nil unless arg_nomsu
-- These types carry their own indentation -- These types carry their own indentation
if bit.type != "List" and bit.type != "Dict" and bit.type != "Text" if bit.type != "List" and bit.type != "Dict" and bit.type != "Text"
@ -577,9 +584,9 @@ with NomsuCompiler
return nomsu return nomsu
when "EscapedNomsu" when "EscapedNomsu"
nomsu = @tree_to_nomsu(tree[1], inline:true) nomsu = recurse(tree[1], inline:true)
if nomsu == nil and not inline if nomsu == nil and not inline
nomsu = @tree_to_nomsu(tree[1]) nomsu = recurse(tree[1])
return nomsu and NomsuCode tree.source, "\\:\n ", pop_comments(tree.source.start), nomsu return nomsu and NomsuCode tree.source, "\\:\n ", pop_comments(tree.source.start), nomsu
return nomsu and NomsuCode tree.source, "\\(", nomsu, ")" return nomsu and NomsuCode tree.source, "\\(", nomsu, ")"
@ -589,14 +596,14 @@ with NomsuCompiler
for i,line in ipairs tree for i,line in ipairs tree
if i > 1 if i > 1
nomsu\append "; " nomsu\append "; "
line_nomsu = @tree_to_nomsu(line,inline:true) line_nomsu = recurse(line,inline:true)
return nil unless line_nomsu return nil unless line_nomsu
nomsu\append line_nomsu nomsu\append line_nomsu
return nomsu return nomsu
nomsu = NomsuCode(tree.source) nomsu = NomsuCode(tree.source)
for i, line in ipairs tree for i, line in ipairs tree
nomsu\append pop_comments(line.source.start) nomsu\append pop_comments(line.source.start)
line = assert(@tree_to_nomsu(line, can_use_colon:true), "Could not convert line to nomsu") line = assert(recurse(line, can_use_colon:true), "Could not convert line to nomsu")
nomsu\append line nomsu\append line
if i < #tree if i < #tree
nomsu\append "\n" nomsu\append "\n"
@ -615,14 +622,14 @@ with NomsuCompiler
elseif bit.type == "Text" elseif bit.type == "Text"
nomsu\append(make_text(bit)) nomsu\append(make_text(bit))
else else
interp_nomsu = assert @tree_to_nomsu(bit, inline:true) interp_nomsu = assert recurse(bit, inline:true)
if bit.type != "Var" and bit.type != "List" and bit.type != "Dict" and bit.type != "Text" if bit.type != "Var" and bit.type != "List" and bit.type != "Dict" and bit.type != "Text"
interp_nomsu\parenthesize! interp_nomsu\parenthesize!
nomsu\append "\\", interp_nomsu nomsu\append "\\", interp_nomsu
return nomsu return nomsu
return NomsuCode(tree.source, '"', make_text(tree), '"') return NomsuCode(tree.source, '"', make_text(tree), '"')
else else
inline_version = @tree_to_nomsu(tree, inline:true) inline_version = recurse(tree, inline:true)
if inline_version and #inline_version <= MAX_LINE if inline_version and #inline_version <= MAX_LINE
return inline_version return inline_version
make_text = (tree)-> make_text = (tree)->
@ -652,13 +659,13 @@ with NomsuCompiler
elseif bit.type == "Text" elseif bit.type == "Text"
nomsu\append make_text(bit) nomsu\append make_text(bit)
else else
interp_nomsu = @tree_to_nomsu(bit, inline:true) interp_nomsu = recurse(bit, inline:true)
if interp_nomsu if interp_nomsu
if bit.type != "Var" and bit.type != "List" and bit.type != "Dict" and bit.type != "Text" if bit.type != "Var" and bit.type != "List" and bit.type != "Dict" and bit.type != "Text"
interp_nomsu\parenthesize! interp_nomsu\parenthesize!
nomsu\append "\\", interp_nomsu nomsu\append "\\", interp_nomsu
else else
interp_nomsu = assert(@tree_to_nomsu(bit)) interp_nomsu = assert(recurse(bit))
return nil unless interp_nomsu return nil unless interp_nomsu
nomsu\append "\\\n ", interp_nomsu nomsu\append "\\\n ", interp_nomsu
if i < #tree if i < #tree
@ -670,7 +677,7 @@ with NomsuCompiler
if inline if inline
nomsu = NomsuCode(tree.source, "[") nomsu = NomsuCode(tree.source, "[")
for i, item in ipairs tree for i, item in ipairs tree
item_nomsu = @tree_to_nomsu(item, inline:true) item_nomsu = recurse(item, inline:true)
return nil unless item_nomsu return nil unless item_nomsu
if i > 1 if i > 1
nomsu\append ", " nomsu\append ", "
@ -678,7 +685,7 @@ with NomsuCompiler
nomsu\append "]" nomsu\append "]"
return nomsu return nomsu
else else
inline_version = @tree_to_nomsu(tree, inline:true) inline_version = recurse(tree, inline:true)
if inline_version and #inline_version <= MAX_LINE if inline_version and #inline_version <= MAX_LINE
return inline_version return inline_version
nomsu = NomsuCode(tree.source, "[..]") nomsu = NomsuCode(tree.source, "[..]")
@ -687,14 +694,14 @@ with NomsuCompiler
pop_comments(tree[1].source.start) pop_comments(tree[1].source.start)
else '' else ''
for i, item in ipairs tree for i, item in ipairs tree
item_nomsu = @tree_to_nomsu(item, inline:true) item_nomsu = recurse(item, inline:true)
if item_nomsu and #tostring(line) + #", " + #item_nomsu <= MAX_LINE if item_nomsu and #tostring(line) + #", " + #item_nomsu <= MAX_LINE
if #line.bits > 1 if #line.bits > 1
line\append ", " line\append ", "
line\append item_nomsu line\append item_nomsu
else else
unless item_nomsu unless item_nomsu
item_nomsu = @tree_to_nomsu(item) item_nomsu = recurse(item)
return nil unless item_nomsu return nil unless item_nomsu
if #line.bits > 1 if #line.bits > 1
if #tostring(line_comments) > 0 if #tostring(line_comments) > 0
@ -713,7 +720,7 @@ with NomsuCompiler
if inline if inline
nomsu = NomsuCode(tree.source, "{") nomsu = NomsuCode(tree.source, "{")
for i, entry in ipairs tree for i, entry in ipairs tree
entry_nomsu = @tree_to_nomsu(entry, inline:true) entry_nomsu = recurse(entry, inline:true)
return nil unless entry_nomsu return nil unless entry_nomsu
if i > 1 if i > 1
nomsu\append ", " nomsu\append ", "
@ -721,7 +728,7 @@ with NomsuCompiler
nomsu\append "}" nomsu\append "}"
return nomsu return nomsu
else else
inline_version = @tree_to_nomsu(tree, inline:true) inline_version = recurse(tree, inline:true)
if inline_version then return inline_version if inline_version then return inline_version
nomsu = NomsuCode(tree.source, "{..}") nomsu = NomsuCode(tree.source, "{..}")
line = NomsuCode(tree.source, "\n ") line = NomsuCode(tree.source, "\n ")
@ -729,7 +736,7 @@ with NomsuCompiler
pop_comments(tree[1].source.start) pop_comments(tree[1].source.start)
else '' else ''
for i, entry in ipairs tree for i, entry in ipairs tree
entry_nomsu = @tree_to_nomsu(entry) entry_nomsu = recurse(entry)
return nil unless entry_nomsu return nil unless entry_nomsu
if #line + #tostring(entry_nomsu) <= MAX_LINE if #line + #tostring(entry_nomsu) <= MAX_LINE
if #line.bits > 1 if #line.bits > 1
@ -751,17 +758,17 @@ with NomsuCompiler
when "DictEntry" when "DictEntry"
key, value = tree[1], tree[2] key, value = tree[1], tree[2]
key_nomsu = @tree_to_nomsu(key, inline:true) key_nomsu = recurse(key, inline:true)
return nil unless key_nomsu return nil unless key_nomsu
if key.type == "Action" or key.type == "Block" if key.type == "Action" or key.type == "Block"
key_nomsu\parenthesize! key_nomsu\parenthesize!
value_nomsu = if value value_nomsu = if value
@tree_to_nomsu(value, inline:true) recurse(value, inline:true)
else NomsuCode(tree.source, "") else NomsuCode(tree.source, "")
if inline and not value_nomsu then return nil if inline and not value_nomsu then return nil
if not value_nomsu if not value_nomsu
return nil if inline return nil if inline
value_nomsu = @tree_to_nomsu(value) value_nomsu = recurse(value)
return nil unless value_nomsu return nil unless value_nomsu
return NomsuCode tree.source, key_nomsu, ":", value_nomsu return NomsuCode tree.source, key_nomsu, ":", value_nomsu
@ -775,7 +782,7 @@ with NomsuCompiler
-- TODO: support arbitrary words here, including operators and unicode -- TODO: support arbitrary words here, including operators and unicode
if bit[1]\match("[_a-zA-Z][_a-zA-Z0-9]*") if bit[1]\match("[_a-zA-Z][_a-zA-Z0-9]*")
bit_nomsu = bit[1] bit_nomsu = bit[1]
unless bit_nomsu then bit_nomsu = @tree_to_nomsu(bit, inline:true) unless bit_nomsu then bit_nomsu = recurse(bit, inline:true)
return nil unless bit_nomsu return nil unless bit_nomsu
switch bit.type switch bit.type
when "Action", "Block", "IndexChain" when "Action", "Block", "IndexChain"

View File

@ -26,8 +26,7 @@ local types = {
"DictEntry", "DictEntry",
"IndexChain", "IndexChain",
"Action", "Action",
"File", "File"
"Comment"
} }
for _index_0 = 1, #types do for _index_0 = 1, #types do
local name = types[_index_0] local name = types[_index_0]

View File

@ -10,7 +10,7 @@ AST.is_syntax_tree = (n, t=nil)->
type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n) and (t == nil or n.type == t) type(n) == 'table' and getmetatable(n) and AST[n.type] == getmetatable(n) and (t == nil or n.type == t)
types = {"Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry", types = {"Number", "Var", "Block", "EscapedNomsu", "Text", "List", "Dict", "DictEntry",
"IndexChain", "Action", "File", "Comment"} "IndexChain", "Action", "File"}
for name in *types for name in *types
cls = {} cls = {}
with cls with cls

View File

@ -26,6 +26,9 @@ do
_with_0.nl = P("\r") ^ -1 * P("\n") _with_0.nl = P("\r") ^ -1 * P("\n")
_with_0.ws = S(" \t") _with_0.ws = S(" \t")
_with_0.tonumber = tonumber _with_0.tonumber = tonumber
_with_0.table = function()
return { }
end
_with_0.unpack = unpack or table.unpack _with_0.unpack = unpack or table.unpack
local string_escapes = { local string_escapes = {
n = "\n", n = "\n",
@ -48,6 +51,10 @@ do
_with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191")) _with_0.utf8_char = (R("\194\223") * R("\128\191") + R("\224\239") * R("\128\191") * R("\128\191") + R("\240\244") * R("\128\191") * R("\128\191") * R("\128\191"))
_with_0.ident_char = R("az", "AZ", "09") + P("_") + _with_0.utf8_char _with_0.ident_char = R("az", "AZ", "09") + P("_") + _with_0.utf8_char
_with_0.userdata = Carg(1) _with_0.userdata = Carg(1)
_with_0.add_comment = function(src, end_pos, start_pos, comment, userdata)
userdata.comments[start_pos] = comment
return true
end
_with_0.error = function(src, end_pos, start_pos, err_msg, userdata) _with_0.error = function(src, end_pos, start_pos, err_msg, userdata)
local seen_errors = userdata.errors local seen_errors = userdata.errors
if seen_errors[start_pos] then if seen_errors[start_pos] then
@ -92,27 +99,8 @@ setmetatable(NOMSU_DEFS, {
value.source = Source(_with_0.filename, _with_0.start + start - 1, _with_0.start + stop - 1) value.source = Source(_with_0.filename, _with_0.start + start - 1, _with_0.start + stop - 1)
end end
end end
local comments = { }
for i = #value, 1, -1 do
local _continue_0 = false
repeat
if not (type(value[i]) == 'table') then
_continue_0 = true
break
end
if value[i].type == "Comment" then
insert(comments, remove(value, i))
end
_continue_0 = true
until true
if not _continue_0 then
break
end
end
if #comments > 0 then
value.comments = comments
end
setmetatable(value, AST[key]) setmetatable(value, AST[key])
value.comments = userdata.comments
if value.__init then if value.__init then
value:__init() value:__init()
end end
@ -164,9 +152,9 @@ Parser.parse = function(nomsu_code, source)
source = source or nomsu_code.source source = source or nomsu_code.source
nomsu_code = tostring(nomsu_code) nomsu_code = tostring(nomsu_code)
local userdata = { local userdata = {
indent = "",
errors = { }, errors = { },
source = source source = source,
comments = { }
} }
local tree = NOMSU_PATTERN:match(nomsu_code, nil, userdata) local tree = NOMSU_PATTERN:match(nomsu_code, nil, userdata)
if not (tree) then if not (tree) then

View File

@ -14,6 +14,7 @@ NOMSU_DEFS = with {}
.nl = P("\r")^-1 * P("\n") .nl = P("\r")^-1 * P("\n")
.ws = S(" \t") .ws = S(" \t")
.tonumber = tonumber .tonumber = tonumber
.table = -> {}
.unpack = unpack or table.unpack .unpack = unpack or table.unpack
string_escapes = n:"\n", t:"\t", b:"\b", a:"\a", v:"\v", f:"\f", r:"\r" string_escapes = n:"\n", t:"\t", b:"\b", a:"\a", v:"\v", f:"\f", r:"\r"
digit, hex = R('09'), R('09','af','AF') digit, hex = R('09'), R('09','af','AF')
@ -29,6 +30,10 @@ NOMSU_DEFS = with {}
.userdata = Carg(1) .userdata = Carg(1)
.add_comment = (src,end_pos,start_pos,comment,userdata)->
userdata.comments[start_pos] = comment
return true
.error = (src,end_pos,start_pos,err_msg,userdata)-> .error = (src,end_pos,start_pos,err_msg,userdata)->
seen_errors = userdata.errors seen_errors = userdata.errors
if seen_errors[start_pos] if seen_errors[start_pos]
@ -59,14 +64,8 @@ setmetatable(NOMSU_DEFS, {__index:(key)=>
if userdata.source if userdata.source
with userdata.source with userdata.source
value.source = Source(.filename, .start + start-1, .start + stop-1) value.source = Source(.filename, .start + start-1, .start + stop-1)
comments = {}
for i=#value,1,-1
continue unless type(value[i]) == 'table'
if value[i].type == "Comment"
insert comments, remove(value, i)
if #comments > 0
value.comments = comments
setmetatable(value, AST[key]) setmetatable(value, AST[key])
value.comments = userdata.comments
if value.__init then value\__init! if value.__init then value\__init!
return value return value
@ -105,7 +104,7 @@ Parser.parse = (nomsu_code, source=nil)->
source or= nomsu_code.source source or= nomsu_code.source
nomsu_code = tostring(nomsu_code) nomsu_code = tostring(nomsu_code)
userdata = { userdata = {
indent: "", errors: {}, :source errors: {}, :source, comments: {}
} }
tree = NOMSU_PATTERN\match(nomsu_code, nil, userdata) tree = NOMSU_PATTERN\match(nomsu_code, nil, userdata)
unless tree unless tree