Overhaul of comment handling, plus a few fixes (e.g. a fix for indented

text that begins with a nomsu comment)
This commit is contained in:
Bruce Hill 2018-07-17 14:12:11 -07:00
parent be06fc096a
commit 0442c8dd21
13 changed files with 232 additions and 122 deletions

View File

@ -105,11 +105,7 @@ do
self.trailing_line_len = #trailing_text self.trailing_line_len = #trailing_text
end end
else else
if #b.indents > 1 then self.trailing_line_len = math.min(self.trailing_line_len + #tostring(b), b.trailing_line_len)
self.trailing_line_len = b.trailing_line_len
else
self.trailing_line_len = self.trailing_line_len + #tostring(b)
end
if self.current_indent ~= 0 then if self.current_indent ~= 0 then
indents[#bits] = self.current_indent indents[#bits] = self.current_indent
end end

View File

@ -73,10 +73,7 @@ class Code
@current_indent = #spaces @current_indent = #spaces
@trailing_line_len = #trailing_text @trailing_line_len = #trailing_text
else else
if #b.indents > 1 @trailing_line_len = math.min(@trailing_line_len + #tostring(b), b.trailing_line_len)
@trailing_line_len = b.trailing_line_len
else
@trailing_line_len += #tostring(b)
if @current_indent != 0 if @current_indent != 0
indents[#bits] = @current_indent indents[#bits] = @current_indent
@__str = nil @__str = nil

View File

@ -164,12 +164,11 @@ compile [%tree with %t -> %replacement] to
\(%replacement as lua return) \(%replacement as lua return)
end) end)
compile [%tree with vars %v] to action [%tree with vars %replacements]
Lua value ".." =lua ".."
\(%tree as lua expr):map(function(t) \%tree:map(function(\%t)
local replacements = \(%v as lua expr) if \%t.type == "Var" then
if t.type == "Var" then return \%replacements[\%t[1]]
return replacements[t[1]]
end end
end) end)

View File

@ -1,6 +1,7 @@
-- Nomsu version 2 -- Nomsu version 2
file (FileChunks): file (FileChunks):
{:curr_indent: ' '* :} {:curr_indent: ' '* :}
("#!" (!"nomsu" [^%nl])* "nomsu" %ws+ "-V" %ws* {:version: ([0-9.]+ -> tonumber) :} [^%nl]*)?
comment? blank_lines? comment? blank_lines?
(chunk (nl_nodent chunk_delimeter nl_nodent chunk)*)? (chunk (nl_nodent chunk_delimeter nl_nodent chunk)*)?
blank_lines? blank_lines?
@ -100,12 +101,12 @@ inline_text_interpolation:
) )
indented_text (Text): indented_text (Text):
'".."' eol %nl {:curr_indent: indent :} '".."' eol %nl {%nl*} {:curr_indent: indent :}
(indented_plain_text / text_interpolation / {~ blank_lines (=curr_indent -> "") ~})* (indented_plain_text / text_interpolation / {~ %nl+ (=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 "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+ {~ (("\\" -> "\") / (("\" blank_lines =curr_indent "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+
(blank_lines (=curr_indent -> ""))* ~} (%nl+ (=curr_indent -> ""))* ~}
text_interpolation: text_interpolation:
inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..") inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..")

View File

@ -1,6 +1,7 @@
-- Nomsu version 2 -- Nomsu version 2
file (FileChunks): file (FileChunks):
{:curr_indent: ' '* :} {:curr_indent: ' '* :}
("#!" (!"nomsu" [^%nl])* "nomsu" %ws+ "-V" %ws* {:version: ([0-9.]+ -> tonumber) :} [^%nl]*)?
comment? blank_lines? comment? blank_lines?
(chunk (nl_nodent section_division nl_nodent chunk)*)? (chunk (nl_nodent section_division nl_nodent chunk)*)?
blank_lines? blank_lines?
@ -61,13 +62,16 @@ 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):
!section_division !section_division
( (inline_expression (%ws* (inline_expression / word))+) ( ((smushed_action / inline_expression) (%ws* (smushed_action / inline_expression / word))+)
/ (word (%ws* (inline_expression / word))*)) / (word (%ws* (smushed_action / inline_expression / word))*))
(%ws* inline_block)? (%ws* inline_block)?
action (Action): action (Action):
!section_division !section_division
( (expression ((nl_nodent "..")? %ws* (expression / word))+) ( ((smushed_action / expression) ((nl_nodent "..")? %ws* (smushed_action / expression / word))+)
/ (word ((nl_nodent "..")? %ws* (expression / word))*)) / (word ((nl_nodent "..")? %ws* (smushed_action / expression / word))*))
smushed_action (Action):
!section_division
(index_chain / noindex_inline_expression / word+) (index_chain / noindex_inline_expression / word+ / "(" %ws* ")")+
word: !number { %operator_char+ / %ident_char+ } word: !number { %operator_char+ / %ident_char+ }
@ -93,20 +97,20 @@ inline_text_interpolation:
) )
indented_text (Text): indented_text (Text):
'".."' eol %nl {:curr_indent: indent :} '".."' eol %nl {%nl*} {:curr_indent: indent :}
(indented_plain_text / text_interpolation / {~ blank_lines (=curr_indent -> "") ~})* (indented_plain_text / text_interpolation / {~ %nl+ (=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 "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+ {~ (("\\" -> "\") / (("\" blank_lines =curr_indent "..") -> "") / (!text_interpolation "\") / [^%nl\]+)+
(blank_lines (=curr_indent -> ""))* ~} (%nl+ (=curr_indent -> ""))* ~}
text_interpolation: text_interpolation:
inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..") inline_text_interpolation / ("\" indented_expression blank_lines =curr_indent "..")
number (Number): (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonumber) number (Number): (("-"? (([0-9]+ "." [0-9]+) / ("." [0-9]+) / ([0-9]+)))-> tonumber)
-- Variables can be nameless (i.e. just %) and can't contain operators like apostrophe -- Variables can be nameless (i.e. just %) and can only contain identifier chars.
-- which is a hack to allow %'s to parse as "%" and "' s" separately -- This ensures you don't get weird parsings of `%x+%y` or `%'s thing`.
variable (Var): "%" {(%ident_char+ ((!"'" %operator_char+) / %ident_char+)*)?} variable (Var): "%" {%ident_char*}
inline_list (List): inline_list (List):
!('[..]') !('[..]')

View File

@ -271,10 +271,11 @@ run = function()
end end
end end
if #file_queue == 0 then if #file_queue == 0 then
nomsu:run([[use "core" nomsu:run([[#!/usr/bin/env nomsu -V2
use "core"
use "lib/consolecolor.nom" use "lib/consolecolor.nom"
action [quit, exit]: lua> "os.exit(0)" action [quit, exit]: lua> "os.exit(0)"
action [help] action [help]:
say ".." say ".."
This is the Nomsu v\(Nomsu version) interactive console. This is the Nomsu v\(Nomsu version) interactive console.
You can type in Nomsu code here and hit 'enter' twice to run it. You can type in Nomsu code here and hit 'enter' twice to run it.

View File

@ -175,10 +175,11 @@ run = ->
if #file_queue == 0 if #file_queue == 0
-- Run in interactive mode (REPL) -- Run in interactive mode (REPL)
nomsu\run [[ nomsu\run [[
#!/usr/bin/env nomsu -V2
use "core" use "core"
use "lib/consolecolor.nom" use "lib/consolecolor.nom"
action [quit, exit]: lua> "os.exit(0)" action [quit, exit]: lua> "os.exit(0)"
action [help] action [help]:
say ".." say ".."
This is the Nomsu v\(Nomsu version) interactive console. This is the Nomsu v\(Nomsu version) interactive console.
You can type in Nomsu code here and hit 'enter' twice to run it. You can type in Nomsu code here and hit 'enter' twice to run it.

View File

@ -722,60 +722,67 @@ do
local MIN_COLON_LEN = 20 local MIN_COLON_LEN = 20
NomsuCompiler.tree_to_nomsu = function(self, tree, options) NomsuCompiler.tree_to_nomsu = function(self, tree, options)
options = options or { } options = options or { }
if not (options.pop_comments) then options.consumed_comments = options.consumed_comments or { }
local comments local pop_comments
do pop_comments = function(pos, prefix, suffix)
local _accum_0 = { }
local _len_0 = 1
for p, c in pairs(tree.comments or { }) do
if tree.source.start <= p and p <= tree.source.stop then
_accum_0[_len_0] = {
comment = c,
pos = p
}
_len_0 = _len_0 + 1
end
end
comments = _accum_0
end
table.sort(comments, function(a, b)
return a.pos < b.pos
end)
local comment_i = 1
options.pop_comments = function(pos, prefix)
if prefix == nil then if prefix == nil then
prefix = '' prefix = ''
end end
if suffix == nil then
suffix = ''
end
local find_comments
find_comments = function(t)
if t.comments and t.source.filename == tree.source.filename then
local _list_0 = t.comments
for _index_0 = 1, #_list_0 do
local c = _list_0[_index_0]
if not (options.consumed_comments[c]) then
coroutine.yield(c)
end
end
end
for _index_0 = 1, #t do
local x = t[_index_0]
if AST.is_syntax_tree(x) then
find_comments(x)
end
end
end
local nomsu = NomsuCode(tree.source) local nomsu = NomsuCode(tree.source)
while comments[comment_i] and comments[comment_i].pos <= pos do for comment in coroutine.wrap(function()
local comment = comments[comment_i].comment return find_comments(tree)
nomsu:append("#" .. (gsub(comment, "\n", "\n ")) .. "\n") end) do
if comment:match("^\n.") then if comment.pos > pos then
break
end
options.consumed_comments[comment] = true
nomsu:append("#" .. (gsub(comment.comment, "\n", "\n ")) .. "\n")
if comment.comment:match("^\n.") then
nomsu:append("\n") nomsu:append("\n")
end end
comment_i = comment_i + 1
end end
if #nomsu.bits == 0 then if #nomsu.bits == 0 then
return '' return ''
end end
nomsu:prepend(prefix) nomsu:prepend(prefix)
nomsu:append(suffix)
return nomsu return nomsu
end end
end
local recurse local recurse
recurse = function(t, opts) recurse = function(t, opts)
opts = opts or { } opts = opts or { }
opts.pop_comments = options.pop_comments opts.consumed_comments = options.consumed_comments
return self:tree_to_nomsu(t, opts) return self:tree_to_nomsu(t, opts)
end end
local inline, pop_comments local inline
inline, pop_comments = options.inline, options.pop_comments inline = options.inline
local _exp_0 = tree.type local _exp_0 = tree.type
if "FileChunks" == _exp_0 then if "FileChunks" == _exp_0 then
if inline then if inline then
error("Cannot inline a FileChunks") error("Cannot inline a FileChunks")
end end
local nomsu = NomsuCode(tree.source) local nomsu = NomsuCode(tree.source, pop_comments(tree.source.start))
for i, chunk in ipairs(tree) do for i, chunk in ipairs(tree) do
if i > 1 then if i > 1 then
nomsu:append("\n\n" .. tostring(("~"):rep(80)) .. "\n\n") nomsu:append("\n\n" .. tostring(("~"):rep(80)) .. "\n\n")
@ -785,7 +792,7 @@ do
top = true top = true
})) }))
end end
nomsu:append(pop_comments(tree.source.stop)) nomsu:append(pop_comments(tree.source.stop, '\n'))
return nomsu return nomsu
elseif "Action" == _exp_0 then elseif "Action" == _exp_0 then
if inline then if inline then
@ -803,7 +810,7 @@ do
if not (arg_nomsu) then if not (arg_nomsu) then
return nil return nil
end end
if not (i == 1) then if not (i == 1 or (bit.type == "Block" and not (#bit > 1 or i < #tree))) then
nomsu:append(" ") nomsu:append(" ")
end end
if bit.type == "Action" or (bit.type == "Block" and (#bit > 1 or i < #tree)) then if bit.type == "Action" or (bit.type == "Block" and (#bit > 1 or i < #tree)) then
@ -814,9 +821,13 @@ do
end end
return nomsu return nomsu
else else
local nomsu = NomsuCode(tree.source) local pos = tree.source.start
local nomsu = NomsuCode(tree.source, pop_comments(pos))
local next_space = "" local next_space = ""
for i, bit in ipairs(tree) do for i, bit in ipairs(tree) do
if match(next_space, '\n') then
nomsu:append(pop_comments(pos, '\n'))
end
if type(bit) == "string" then if type(bit) == "string" then
nomsu:append(next_space, bit) nomsu:append(next_space, bit)
next_space = " " next_space = " "
@ -853,11 +864,13 @@ do
end end
next_space = "\n.." next_space = "\n.."
end end
pos = bit.source.stop
end end
if next_space == " " and nomsu.trailing_line_len > MAX_LINE then if next_space == " " and nomsu.trailing_line_len > MAX_LINE then
next_space = "\n.." next_space = "\n.."
end end
end end
nomsu:append(pop_comments(pos, '\n'))
return nomsu return nomsu
end end
elseif "EscapedNomsu" == _exp_0 then elseif "EscapedNomsu" == _exp_0 then
@ -885,7 +898,7 @@ do
end end
return nomsu return nomsu
end end
local nomsu = NomsuCode(tree.source) local nomsu = NomsuCode(tree.source, pop_comments(tree.source.start))
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(recurse(line), "Could not convert line to nomsu") line = assert(recurse(line), "Could not convert line to nomsu")
@ -897,6 +910,7 @@ do
end end
end end
end end
nomsu:append(pop_comments(tree.source.stop, '\n'))
return options.top and nomsu or NomsuCode(tree.source, ":\n ", nomsu) return options.top and nomsu or NomsuCode(tree.source, ":\n ", nomsu)
elseif "Text" == _exp_0 then elseif "Text" == _exp_0 then
if inline then if inline then

View File

@ -481,36 +481,40 @@ with NomsuCompiler
MIN_COLON_LEN = 20 -- For beautification purposes, don't bother using colon syntax for short bits MIN_COLON_LEN = 20 -- For beautification purposes, don't bother using colon syntax for short bits
.tree_to_nomsu = (tree, options)=> .tree_to_nomsu = (tree, options)=>
options or= {} options or= {}
unless options.pop_comments options.consumed_comments or= {}
comments = [{comment:c, pos:p} for p,c in pairs(tree.comments or {}) when tree.source.start <= p and p <= tree.source.stop] pop_comments = (pos, prefix='', suffix='')->
table.sort comments, (a,b)-> a.pos < b.pos find_comments = (t)->
comment_i = 1 if t.comments and t.source.filename == tree.source.filename
options.pop_comments = (pos, prefix='')-> for c in *t.comments
coroutine.yield(c) unless options.consumed_comments[c]
for x in *t
find_comments(x) if AST.is_syntax_tree x
nomsu = NomsuCode(tree.source) nomsu = NomsuCode(tree.source)
while comments[comment_i] and comments[comment_i].pos <= pos for comment in coroutine.wrap(-> find_comments(tree))
comment = comments[comment_i].comment break if comment.pos > pos
nomsu\append("#"..(gsub(comment, "\n", "\n ")).."\n") options.consumed_comments[comment] = true
if comment\match("^\n.") then nomsu\append("\n") -- for aesthetics nomsu\append("#"..(gsub(comment.comment, "\n", "\n ")).."\n")
comment_i += 1 if comment.comment\match("^\n.") then nomsu\append("\n") -- for aesthetics
return '' if #nomsu.bits == 0 return '' if #nomsu.bits == 0
nomsu\prepend prefix nomsu\prepend prefix
nomsu\append suffix
return nomsu return nomsu
recurse = (t, opts)-> recurse = (t, opts)->
opts or= {} opts or= {}
opts.pop_comments = options.pop_comments opts.consumed_comments = options.consumed_comments
return @tree_to_nomsu(t, opts) return @tree_to_nomsu(t, opts)
{:inline, :pop_comments} = options {:inline} = options
switch tree.type switch tree.type
when "FileChunks" when "FileChunks"
error("Cannot inline a FileChunks") if inline error("Cannot inline a FileChunks") if inline
nomsu = NomsuCode(tree.source) nomsu = NomsuCode(tree.source, pop_comments(tree.source.start))
for i, chunk in ipairs tree for i, chunk in ipairs tree
nomsu\append "\n\n#{("~")\rep(80)}\n\n" if i > 1 nomsu\append "\n\n#{("~")\rep(80)}\n\n" if i > 1
nomsu\append pop_comments(chunk.source.start) nomsu\append pop_comments(chunk.source.start)
nomsu\append recurse(chunk, top:true) nomsu\append recurse(chunk, top:true)
nomsu\append pop_comments(tree.source.stop) nomsu\append pop_comments(tree.source.stop, '\n')
return nomsu return nomsu
when "Action" when "Action"
@ -523,16 +527,19 @@ with NomsuCompiler
else else
arg_nomsu = recurse(bit,inline:true) arg_nomsu = recurse(bit,inline:true)
return nil unless arg_nomsu return nil unless arg_nomsu
unless i == 1 unless i == 1 or (bit.type == "Block" and not (#bit > 1 or i < #tree))
nomsu\append " " nomsu\append " "
if bit.type == "Action" or (bit.type == "Block" and (#bit > 1 or i < #tree)) if bit.type == "Action" or (bit.type == "Block" and (#bit > 1 or i < #tree))
arg_nomsu\parenthesize! arg_nomsu\parenthesize!
nomsu\append arg_nomsu nomsu\append arg_nomsu
return nomsu return nomsu
else else
nomsu = NomsuCode(tree.source) pos = tree.source.start
nomsu = NomsuCode(tree.source, pop_comments(pos))
next_space = "" next_space = ""
for i,bit in ipairs tree for i,bit in ipairs tree
if match(next_space, '\n')
nomsu\append pop_comments(pos, '\n')
if type(bit) == "string" if type(bit) == "string"
nomsu\append next_space, bit nomsu\append next_space, bit
next_space = " " next_space = " "
@ -557,9 +564,11 @@ with NomsuCompiler
else else
nomsu\append arg_nomsu nomsu\append arg_nomsu
next_space = "\n.." next_space = "\n.."
pos = bit.source.stop
if next_space == " " and nomsu.trailing_line_len > MAX_LINE if next_space == " " and nomsu.trailing_line_len > MAX_LINE
next_space = "\n.." next_space = "\n.."
nomsu\append pop_comments(pos, '\n')
return nomsu return nomsu
when "EscapedNomsu" when "EscapedNomsu"
@ -580,7 +589,7 @@ with NomsuCompiler
nomsu\append(i == 1 and " " or "; ") nomsu\append(i == 1 and " " or "; ")
nomsu\append assert(recurse(line, inline:true)) nomsu\append assert(recurse(line, inline:true))
return nomsu return nomsu
nomsu = NomsuCode(tree.source) nomsu = NomsuCode(tree.source, pop_comments(tree.source.start))
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(recurse(line), "Could not convert line to nomsu") line = assert(recurse(line), "Could not convert line to nomsu")
@ -589,6 +598,7 @@ with NomsuCompiler
nomsu\append "\n" nomsu\append "\n"
if match(tostring(line), "\n") if match(tostring(line), "\n")
nomsu\append "\n" nomsu\append "\n"
nomsu\append pop_comments(tree.source.stop, '\n')
return options.top and nomsu or NomsuCode(tree.source, ":\n ", nomsu) return options.top and nomsu or NomsuCode(tree.source, ":\n ", nomsu)
when "Text" when "Text"

View File

@ -53,24 +53,52 @@ for _index_0 = 1, #types do
end end
cls.map = function(self, fn) cls.map = function(self, fn)
local replacement = fn(self) local replacement = fn(self)
if replacement ~= nil then if replacement == false then
return replacement or nil return nil
end end
if replacement then
replacement = (replacement.__class)(self.source, unpack(replacement))
else
local replacements = { } local replacements = { }
local changes = false local changes = false
for i, v in ipairs(self) do for i, v in ipairs(self) do
local _continue_0 = false
repeat
replacements[#replacements + 1] = v
if AST.is_syntax_tree(v) then if AST.is_syntax_tree(v) then
replacement = v:map(fn) local r = v:map(fn)
else if r == v or r == nil then
replacement = v _continue_0 = true
break
end
changes = true
replacements[#replacements] = r
end
_continue_0 = true
until true
if not _continue_0 then
break
end end
changes = changes or (replacement ~= v)
replacements[#replacements + 1] = replacement
end end
if not (changes) then if not (changes) then
return self return self
end end
return (self.__class)(self.source, unpack(replacements)) replacement = (self.__class)(self.source, unpack(replacements))
end
if self.comments then
do
local _accum_0 = { }
local _len_0 = 1
local _list_0 = self.comments
for _index_1 = 1, #_list_0 do
local c = _list_0[_index_1]
_accum_0[_len_0] = c
_len_0 = _len_0 + 1
end
replacement.comments = _accum_0
end
end
return replacement
end end
end end
AST[name] = setmetatable(cls, { AST[name] = setmetatable(cls, {

View File

@ -22,17 +22,24 @@ for name in *types
.__tostring = => "#{@type}(#{repr tostring(@source)}, #{concat([repr(v) for v in *@], ', ')})" .__tostring = => "#{@type}(#{repr tostring(@source)}, #{concat([repr(v) for v in *@], ', ')})"
.map = (fn)=> .map = (fn)=>
replacement = fn(@) replacement = fn(@)
if replacement != nil then return replacement or nil if replacement == false then return nil
if replacement
-- Clone the replacement, but give it a proper source
replacement = (replacement.__class)(@source, unpack(replacement))
else
replacements = {} replacements = {}
changes = false changes = false
for i,v in ipairs(@) for i,v in ipairs(@)
replacement = if AST.is_syntax_tree(v) replacements[#replacements+1] = v
v\map(fn) if AST.is_syntax_tree(v)
else v r = v\map(fn)
changes or= replacement != v continue if r == v or r == nil
replacements[#replacements+1] = replacement changes = true
replacements[#replacements] = r
return @ unless changes return @ unless changes
return (@__class)(@source, unpack(replacements)) replacement = (@__class)(@source, unpack(replacements))
replacement.comments = [c for c in *@comments] if @comments
return replacement
AST[name] = setmetatable cls, AST[name] = setmetatable cls,
__tostring: => @name __tostring: => @name

View File

@ -100,7 +100,6 @@ setmetatable(NOMSU_DEFS, {
end end
end 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
@ -190,6 +189,43 @@ Parser.parse = function(nomsu_code, source, version)
end end
error("Errors occurred while parsing (v" .. tostring(version) .. "):\n\n" .. table.concat(errors, "\n\n"), 0) error("Errors occurred while parsing (v" .. tostring(version) .. "):\n\n" .. table.concat(errors, "\n\n"), 0)
end end
local comments
do
local _accum_0 = { }
local _len_0 = 1
for p, c in pairs(userdata.comments) do
_accum_0[_len_0] = {
comment = c,
pos = p
}
_len_0 = _len_0 + 1
end
comments = _accum_0
end
table.sort(comments, function(a, b)
return a.pos > b.pos
end)
local comment_i = 1
local walk_tree
walk_tree = function(t)
local comment_buff = { }
while comments[#comments] and comments[#comments].pos <= t.source.start do
table.insert(comment_buff, table.remove(comments))
end
for _index_0 = 1, #t do
local x = t[_index_0]
if AST.is_syntax_tree(x) then
walk_tree(x)
end
end
while comments[#comments] and comments[#comments].pos <= t.source.stop do
table.insert(comment_buff, table.remove(comments))
end
if #comment_buff > 0 then
t.comments = comment_buff
end
end
walk_tree(tree)
tree.version = userdata.version tree.version = userdata.version
return tree return tree
end end

View File

@ -65,7 +65,6 @@ setmetatable(NOMSU_DEFS, {__index:(key)=>
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)
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
@ -120,6 +119,23 @@ Parser.parse = (nomsu_code, source=nil, version=nil)->
errors = [userdata.errors[k] for k in *keys] errors = [userdata.errors[k] for k in *keys]
error("Errors occurred while parsing (v#{version}):\n\n"..table.concat(errors, "\n\n"), 0) error("Errors occurred while parsing (v#{version}):\n\n"..table.concat(errors, "\n\n"), 0)
comments = [{comment:c, pos:p} for p,c in pairs(userdata.comments)]
-- Sort in descending order so we can pop the first comments off the end one at a time
table.sort comments, (a,b)-> a.pos > b.pos
comment_i = 1
walk_tree = (t)->
export comment_i
comment_buff = {}
while comments[#comments] and comments[#comments].pos <= t.source.start
table.insert(comment_buff, table.remove(comments))
for x in *t
if AST.is_syntax_tree x
walk_tree x
while comments[#comments] and comments[#comments].pos <= t.source.stop
table.insert(comment_buff, table.remove(comments))
t.comments = comment_buff if #comment_buff > 0
walk_tree tree
tree.version = userdata.version tree.version = userdata.version
return tree return tree