From fb977a913049d4e21d3f567fcca11bfe8f9222e6 Mon Sep 17 00:00:00 2001 From: Kyra Zimmer Date: Mon, 28 Sep 2015 13:40:32 +0200 Subject: [PATCH 1/2] implemented litmoon --- bin/moonc | 4 +- moonscript/base.lua | 48 ++-- moonscript/base.moon | 34 +-- moonscript/cmd/moonc.lua | 107 ++++---- moonscript/cmd/moonc.moon | 74 +++--- moonscript/parse.lua | 355 +++++++++++++------------ moonscript/parse.moon | 463 +++++++++++++++++---------------- moonscript/parse/literals.lua | 18 +- moonscript/parse/literals.moon | 14 +- spec/helpers.moon | 3 +- spec/moonscript_spec.moon | 3 +- 11 files changed, 601 insertions(+), 522 deletions(-) diff --git a/bin/moonc b/bin/moonc index 5de57204..8be965c2 100755 --- a/bin/moonc +++ b/bin/moonc @@ -74,7 +74,7 @@ local function scan_directory(root, collected) scan_directory(full_path, collected) end - if fname:match("%.moon$") then + if fname:match("%.moon$") or fname:match("%.litmoon$") then table.insert(collected, full_path) end end @@ -225,7 +225,7 @@ local function create_watcher(files) for _, ev in ipairs(events) do local fname = ev.name - if fname:match("%.moon$") then + if fname:match("%.moon$") or fname:match("%.litmoon$") then local dir = wd_table[ev.wd] if dir ~= "./" then fname = dir .. fname diff --git a/moonscript/base.lua b/moonscript/base.lua index 6bc0d49e..b1ee4320 100644 --- a/moonscript/base.lua +++ b/moonscript/base.lua @@ -14,7 +14,7 @@ local lua = { loadstring = loadstring, load = load } -local dirsep, line_tables, create_moonpath, to_lua, moon_loader, loadstring, loadfile, dofile, insert_loader, remove_loader +local dirsep, line_tables, create_moonpath, to_lua, moon_loader, loadstring_factory, loadstring, loadfile, dofile, insert_loader, remove_loader dirsep = "/" line_tables = require("moonscript.line_tables") create_moonpath = function(package_path) @@ -32,7 +32,7 @@ create_moonpath = function(package_path) _continue_0 = true break end - local _value_0 = prefix .. ".moon" + local _value_0 = prefix .. ".moon;" .. prefix .. ".litmoon" _accum_0[_len_0] = _value_0 _len_0 = _len_0 + 1 _continue_0 = true @@ -45,15 +45,18 @@ create_moonpath = function(package_path) end return concat(moonpaths, ";") end -to_lua = function(text, options) +to_lua = function(text, options, litmoon) if options == nil then options = { } end + if litmoon == nil then + litmoon = false + end if "string" ~= type(text) then local t = type(text) return nil, "expecting string (got " .. t .. ")" end - local tree, err = parse.string(text) + local tree, err = parse.string(text, litmoon) if not tree then return nil, err end @@ -76,7 +79,7 @@ moon_loader = function(name) if file then local text = file:read("*a") file:close() - local res, err = loadstring(text, "@" .. tostring(file_path)) + local res, err = loadstring_factory(file_path:sub(-8) == ".litmoon")(text, "@" .. tostring(file_path)) if not res then error(file_path .. ": " .. err) end @@ -84,21 +87,27 @@ moon_loader = function(name) end return nil, "Could not find moon file" end -loadstring = function(...) - local options, str, chunk_name, mode, env = get_options(...) - chunk_name = chunk_name or "=(moonscript.loadstring)" - local code, ltable_or_err = to_lua(str, options) - if not (code) then - return nil, ltable_or_err +loadstring_factory = function(litmoon) + if litmoon == nil then + litmoon = false end - if chunk_name then - line_tables[chunk_name] = ltable_or_err + return function(...) + local options, str, chunk_name, mode, env = get_options(...) + chunk_name = chunk_name or "=(moonscript.loadstring)" + local code, ltable_or_err = to_lua(str, options, litmoon) + if not (code) then + return nil, ltable_or_err + end + if chunk_name then + line_tables[chunk_name] = ltable_or_err + end + return (lua.loadstring or lua.load)(code, chunk_name, unpack({ + mode, + env + })) end - return (lua.loadstring or lua.load)(code, chunk_name, unpack({ - mode, - env - })) end +loadstring = loadstring_factory() loadfile = function(fname, ...) local file, err = io.open(fname) if not (file) then @@ -106,7 +115,7 @@ loadfile = function(fname, ...) end local text = assert(file:read("*a")) file:close() - return loadstring(text, "@" .. tostring(fname), ...) + return loadstring_factory(fname:sub(-8) == ".litmoon")(text, "@" .. tostring(fname), ...) end dofile = function(...) local f = assert(loadfile(...)) @@ -149,5 +158,6 @@ return { dofile = dofile, loadfile = loadfile, loadstring = loadstring, - create_moonpath = create_moonpath + create_moonpath = create_moonpath, + loadlitstring = loadstring_factory(true) } diff --git a/moonscript/base.moon b/moonscript/base.moon index 3a4502d4..b86cb053 100644 --- a/moonscript/base.moon +++ b/moonscript/base.moon @@ -16,15 +16,15 @@ create_moonpath = (package_path) -> moonpaths = for path in *split package_path, ";" prefix = path\match "^(.-)%.lua$" continue unless prefix - prefix .. ".moon" + prefix .. ".moon;"..prefix .. ".litmoon" concat moonpaths, ";" -to_lua = (text, options={}) -> +to_lua = (text, options={}, litmoon=false) -> if "string" != type text t = type text return nil, "expecting string (got ".. t ..")" - tree, err = parse.string text + tree, err = parse.string text, litmoon if not tree return nil, err @@ -46,7 +46,7 @@ moon_loader = (name) -> if file text = file\read "*a" file\close! - res, err = loadstring text, "@#{file_path}" + res, err = loadstring_factory(file_path\sub(-8)==".litmoon") text, "@#{file_path}" if not res error file_path .. ": " .. err @@ -55,24 +55,27 @@ moon_loader = (name) -> return nil, "Could not find moon file" -loadstring = (...) -> - options, str, chunk_name, mode, env = get_options ... - chunk_name or= "=(moonscript.loadstring)" +loadstring_factory = (litmoon=false)-> + (...) -> + options, str, chunk_name, mode, env = get_options ... + chunk_name or= "=(moonscript.loadstring)" - code, ltable_or_err = to_lua str, options - unless code - return nil, ltable_or_err + code, ltable_or_err = to_lua str, options, litmoon + unless code + return nil, ltable_or_err - line_tables[chunk_name] = ltable_or_err if chunk_name - -- the unpack prevents us from passing nil - (lua.loadstring or lua.load) code, chunk_name, unpack { mode, env } + line_tables[chunk_name] = ltable_or_err if chunk_name + -- the unpack prevents us from passing nil + (lua.loadstring or lua.load) code, chunk_name, unpack { mode, env } + +loadstring = loadstring_factory! loadfile = (fname, ...) -> file, err = io.open fname return nil, err unless file text = assert file\read "*a" file\close! - loadstring text, "@#{fname}", ... + loadstring_factory(fname\sub(-8)==".litmoon") text, "@#{fname}", ... -- throws errros dofile = (...) -> @@ -103,6 +106,7 @@ remove_loader = -> { _NAME: "moonscript" :insert_loader, :remove_loader, :to_lua, :moon_loader, :dirsep, - :dofile, :loadfile, :loadstring, :create_moonpath + :dofile, :loadfile, :loadstring, :create_moonpath, + loadlitstring: loadstring_factory true } diff --git a/moonscript/cmd/moonc.lua b/moonscript/cmd/moonc.lua index eae86380..6768d844 100644 --- a/moonscript/cmd/moonc.lua +++ b/moonscript/cmd/moonc.lua @@ -1,7 +1,7 @@ local lfs = require("lfs") local split split = require("moonscript.util").split -local dirsep, dirsep_chars, mkdir, normalize_dir, parse_dir, parse_file, convert_path, format_time, gettime, compile_file_text, write_file, compile_and_write, is_abs_path, path_to_target +local dirsep, dirsep_chars, mkdir, normalize_dir, parse_dir, parse_file, convert_path, format_time, gettime, compile_file_text_factory, compile_file_text, write_file, compile_and_write, is_abs_path, path_to_target dirsep = package.config:sub(1, 1) if dirsep == "\\" then dirsep_chars = "\\/" @@ -55,57 +55,63 @@ do end end end -compile_file_text = function(text, opts) - if opts == nil then - opts = { } - end - local parse = require("moonscript.parse") - local compile = require("moonscript.compile") - local parse_time - if opts.benchmark then - parse_time = assert(gettime()) - end - local tree, err = parse.string(text) - if not (tree) then - return nil, err - end - if parse_time then - parse_time = gettime() - parse_time +compile_file_text_factory = function(litmoon) + if litmoon == nil then + litmoon = false end - if opts.show_parse_tree then - local dump = require("moonscript.dump") - dump.tree(tree) - return true - end - local compile_time - if opts.benchmark then - compile_time = gettime() - end - local code, posmap_or_err, err_pos = compile.tree(tree) - if not (code) then - return nil, compile.format_error(posmap_or_err, err_pos, text) - end - if compile_time then - compile_time = gettime() - compile_time - end - if opts.show_posmap then - local debug_posmap - debug_posmap = require("moonscript.util").debug_posmap - print("Pos", "Lua", ">>", "Moon") - print(debug_posmap(posmap_or_err, text, code)) - return true - end - if opts.benchmark then - print(table.concat({ - opts.fname or "stdin", - "Parse time \t" .. format_time(parse_time), - "Compile time\t" .. format_time(compile_time), - "" - }, "\n")) - return nil + return function(text, opts) + if opts == nil then + opts = { } + end + local parse = require("moonscript.parse") + local compile = require("moonscript.compile") + local parse_time + if opts.benchmark then + parse_time = assert(gettime()) + end + local tree, err = parse.string(text, litmoon) + if not (tree) then + return nil, err + end + if parse_time then + parse_time = gettime() - parse_time + end + if opts.show_parse_tree then + local dump = require("moonscript.dump") + dump.tree(tree) + return true + end + local compile_time + if opts.benchmark then + compile_time = gettime() + end + local code, posmap_or_err, err_pos = compile.tree(tree) + if not (code) then + return nil, compile.format_error(posmap_or_err, err_pos, text) + end + if compile_time then + compile_time = gettime() - compile_time + end + if opts.show_posmap then + local debug_posmap + debug_posmap = require("moonscript.util").debug_posmap + print("Pos", "Lua", ">>", "Moon") + print(debug_posmap(posmap_or_err, text, code)) + return true + end + if opts.benchmark then + print(table.concat({ + opts.fname or "stdin", + "Parse time \t" .. format_time(parse_time), + "Compile time\t" .. format_time(compile_time), + "" + }, "\n")) + return nil + end + return code end - return code end +compile_file_text = compile_file_text_factory() write_file = function(fname, code) mkdir(parse_dir(fname)) local f, err = io.open(fname, "w") @@ -127,7 +133,7 @@ compile_and_write = function(src, dest, opts) end local text = assert(f:read("*a")) f:close() - local code, err = compile_file_text(text, opts) + local code, err = compile_file_text_factory(src:sub(-8) == ".litmoon")(text, opts) if not code then return nil, err end @@ -187,5 +193,6 @@ return { format_time = format_time, path_to_target = path_to_target, compile_file_text = compile_file_text, + compile_file_text_factory = compile_file_text_factory, compile_and_write = compile_and_write } diff --git a/moonscript/cmd/moonc.moon b/moonscript/cmd/moonc.moon index a680eaa7..c7179afa 100644 --- a/moonscript/cmd/moonc.moon +++ b/moonscript/cmd/moonc.moon @@ -63,51 +63,54 @@ gettime = do -- compiles file to lua, returns lua code -- returns nil, error on error -- returns true if some option handled the output instead -compile_file_text = (text, opts={}) -> - parse = require "moonscript.parse" - compile = require "moonscript.compile" +compile_file_text_factory = (litmoon=false) -> + (text, opts={}) -> + parse = require "moonscript.parse" + compile = require "moonscript.compile" - parse_time = if opts.benchmark - assert gettime! + parse_time = if opts.benchmark + assert gettime! - tree, err = parse.string text - return nil, err unless tree + tree, err = parse.string text, litmoon + return nil, err unless tree - if parse_time - parse_time = gettime! - parse_time + if parse_time + parse_time = gettime! - parse_time - if opts.show_parse_tree - dump = require "moonscript.dump" - dump.tree tree - return true + if opts.show_parse_tree + dump = require "moonscript.dump" + dump.tree tree + return true - compile_time = if opts.benchmark - gettime! + compile_time = if opts.benchmark + gettime! - code, posmap_or_err, err_pos = compile.tree tree + code, posmap_or_err, err_pos = compile.tree tree - unless code - return nil, compile.format_error posmap_or_err, err_pos, text + unless code + return nil, compile.format_error posmap_or_err, err_pos, text - if compile_time - compile_time = gettime() - compile_time + if compile_time + compile_time = gettime() - compile_time - if opts.show_posmap - import debug_posmap from require "moonscript.util" - print "Pos", "Lua", ">>", "Moon" - print debug_posmap posmap_or_err, text, code - return true + if opts.show_posmap + import debug_posmap from require "moonscript.util" + print "Pos", "Lua", ">>", "Moon" + print debug_posmap posmap_or_err, text, code + return true + + if opts.benchmark + print table.concat { + opts.fname or "stdin", + "Parse time \t" .. format_time(parse_time), + "Compile time\t" .. format_time(compile_time), + "" + }, "\n" + return nil - if opts.benchmark - print table.concat { - opts.fname or "stdin", - "Parse time \t" .. format_time(parse_time), - "Compile time\t" .. format_time(compile_time), - "" - }, "\n" - return nil + code - code +compile_file_text=compile_file_text_factory! write_file = (fname, code) -> mkdir parse_dir fname @@ -128,7 +131,7 @@ compile_and_write = (src, dest, opts={}) -> text = assert f\read("*a") f\close! - code, err = compile_file_text text, opts + code, err = compile_file_text_factory(src\sub(-8)==".litmoon") text, opts if not code return nil, err @@ -188,5 +191,6 @@ path_to_target = (path, target_dir=nil, base_dir=nil) -> :path_to_target :compile_file_text + :compile_file_text_factory :compile_and_write } diff --git a/moonscript/parse.lua b/moonscript/parse.lua index d3d8c226..f2acb41f 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -15,10 +15,10 @@ local wrap_env wrap_env = require("moonscript.parse.env").wrap_env local R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc R, S, V, P, C, Ct, Cmt, Cg, Cb, Cc = lpeg.R, lpeg.S, lpeg.V, lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc -local White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name +local White, Break, Stop, LitmoonCommentLine, AlphaNum, Num, Shebang, Comment, Space, SomeSpace, SpaceBreak, mkEmptyLine, _Name do local _obj_0 = require("moonscript.parse.literals") - White, Break, Stop, Comment, Space, SomeSpace, SpaceBreak, EmptyLine, AlphaNum, Num, Shebang, _Name = _obj_0.White, _obj_0.Break, _obj_0.Stop, _obj_0.Comment, _obj_0.Space, _obj_0.SomeSpace, _obj_0.SpaceBreak, _obj_0.EmptyLine, _obj_0.AlphaNum, _obj_0.Num, _obj_0.Shebang, _obj_0.Name + White, Break, Stop, LitmoonCommentLine, AlphaNum, Num, Shebang, Comment, Space, SomeSpace, SpaceBreak, mkEmptyLine, _Name = _obj_0.White, _obj_0.Break, _obj_0.Stop, _obj_0.LitmoonCommentLine, _obj_0.AlphaNum, _obj_0.Num, _obj_0.Shebang, _obj_0.Comment, _obj_0.Space, _obj_0.SomeSpace, _obj_0.SpaceBreak, _obj_0.mkEmptyLine, _obj_0.Name end local SpaceName = Space * _Name Num = Space * (Num / function(v) @@ -32,177 +32,197 @@ do local _obj_0 = require("moonscript.parse.util") Indent, Cut, ensure, extract_line, mark, pos, flatten_or_mark, is_assignable, check_assignable, format_assign, format_single_assign, sym, symx, simple_string, wrap_func_arg, flatten_func, flatten_string_chain, wrap_decorator, check_lua_string, self_assign = _obj_0.Indent, _obj_0.Cut, _obj_0.ensure, _obj_0.extract_line, _obj_0.mark, _obj_0.pos, _obj_0.flatten_or_mark, _obj_0.is_assignable, _obj_0.check_assignable, _obj_0.format_assign, _obj_0.format_single_assign, _obj_0.sym, _obj_0.symx, _obj_0.simple_string, _obj_0.wrap_func_arg, _obj_0.flatten_func, _obj_0.flatten_string_chain, _obj_0.wrap_decorator, _obj_0.check_lua_string, _obj_0.self_assign end -local build_grammar = wrap_env(debug_grammar, function(root) - local _indent = Stack(0) - local _do_stack = Stack(0) - local state = { - last_pos = 0 - } - local check_indent - check_indent = function(str, pos, indent) - state.last_pos = pos - return _indent:top() == indent +local build_grammar_factory +build_grammar_factory = function(litmoon) + if litmoon == nil then + litmoon = false end - local advance_indent - advance_indent = function(str, pos, indent) - local top = _indent:top() - if top ~= -1 and indent > top then + local EmptyLine = mkEmptyLine(litmoon) + return wrap_env(debug_grammar, function(root) + local _indent = Stack((litmoon and 4 or 0)) + local _do_stack = Stack(0) + local state = { + last_pos = 0 + } + local check_indent + check_indent = function(str, pos, indent) + state.last_pos = pos + return _indent:top() == indent + end + local advance_indent + advance_indent = function(str, pos, indent) + local top = _indent:top() + if top ~= -1 and indent > top then + _indent:push(indent) + return true + end + end + local push_indent + push_indent = function(str, pos, indent) _indent:push(indent) return true end - end - local push_indent - push_indent = function(str, pos, indent) - _indent:push(indent) - return true - end - local pop_indent - pop_indent = function() - assert(_indent:pop(), "unexpected outdent") - return true - end - local check_do - check_do = function(str, pos, do_node) - local top = _do_stack:top() - if top == nil or top then - return true, do_node + local pop_indent + pop_indent = function() + assert(_indent:pop(), "unexpected outdent") + return true end - return false - end - local disable_do - disable_do = function() - _do_stack:push(false) - return true - end - local pop_do - pop_do = function() - assert(_do_stack:pop() ~= nil, "unexpected do pop") - return true - end - local DisableDo = Cmt("", disable_do) - local PopDo = Cmt("", pop_do) - local keywords = { } - local key - key = function(chars) - keywords[chars] = true - return Space * chars * -AlphaNum - end - local op - op = function(chars) - local patt = Space * C(chars) - if chars:match("^%w*$") then + local check_do + check_do = function(str, pos, do_node) + local top = _do_stack:top() + if top == nil or top then + return true, do_node + end + return false + end + local disable_do + disable_do = function() + _do_stack:push(false) + return true + end + local pop_do + pop_do = function() + assert(_do_stack:pop() ~= nil, "unexpected do pop") + return true + end + local DisableDo = Cmt("", disable_do) + local PopDo = Cmt("", pop_do) + local keywords = { } + local key + key = function(chars) keywords[chars] = true - patt = patt * -AlphaNum + return Space * chars * -AlphaNum end - return patt - end - local Name = Cmt(SpaceName, function(str, pos, name) - if keywords[name] then - return false + local op + op = function(chars) + local patt = Space * C(chars) + if chars:match("^%w*$") then + keywords[chars] = true + patt = patt * -AlphaNum + end + return patt end - return true - end) / trim - local SelfName = Space * "@" * ("@" * (_Name / mark("self_class") + Cc("self.__class")) + _Name / mark("self") + Cc("self")) - local KeyName = SelfName + Space * _Name / mark("key_literal") - local VarArg = Space * P("...") / trim - local g = P({ - root or File, - File = Shebang ^ -1 * (Block + Ct("")), - Block = Ct(Line * (Break ^ 1 * Line) ^ 0), - CheckIndent = Cmt(Indent, check_indent), - Line = (CheckIndent * Statement + Space * #Stop), - Statement = pos(Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign) ^ -1 / format_assign) * Space * ((key("if") * Exp * (key("else") * Exp) ^ -1 * Space / mark("if") + key("unless") * Exp / mark("unless") + CompInner / mark("comprehension")) * Space) ^ -1 / wrap_decorator, - Body = Space ^ -1 * Break * EmptyLine ^ 0 * InBlock + Ct(Statement), - Advance = #Cmt(Indent, advance_indent), - PushIndent = Cmt(Indent, push_indent), - PreventIndent = Cmt(Cc(-1), push_indent), - PopIndent = Cmt("", pop_indent), - InBlock = Advance * Block * PopIndent, - Local = key("local") * ((op("*") + op("^")) / mark("declare_glob") + Ct(NameList) / mark("declare_with_shadows")), - Import = key("import") * Ct(ImportNameList) * SpaceBreak ^ 0 * key("from") * Exp / mark("import"), - ImportName = (sym("\\") * Ct(Cc("colon_stub") * Name) + Name), - ImportNameList = SpaceBreak ^ 0 * ImportName * ((SpaceBreak ^ 1 + sym(",") * SpaceBreak ^ 0) * ImportName) ^ 0, - BreakLoop = Ct(key("break") / trim) + Ct(key("continue") / trim), - Return = key("return") * (ExpListLow / mark("explist") + C("")) / mark("return"), - WithExp = Ct(ExpList) * Assign ^ -1 / format_assign, - With = key("with") * DisableDo * ensure(WithExp, PopDo) * key("do") ^ -1 * Body / mark("with"), - Switch = key("switch") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Space ^ -1 * Break * SwitchBlock / mark("switch"), - SwitchBlock = EmptyLine ^ 0 * Advance * Ct(SwitchCase * (Break ^ 1 * SwitchCase) ^ 0 * (Break ^ 1 * SwitchElse) ^ -1) * PopIndent, - SwitchCase = key("when") * Ct(ExpList) * key("then") ^ -1 * Body / mark("case"), - SwitchElse = key("else") * Body / mark("else"), - IfCond = Exp * Assign ^ -1 / format_single_assign, - If = key("if") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("elseif") * pos(IfCond) * key("then") ^ -1 * Body / mark("elseif")) ^ 0 * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("if"), - Unless = key("unless") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("unless"), - While = key("while") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Body / mark("while"), - For = key("for") * DisableDo * ensure(Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1), PopDo) * key("do") ^ -1 * Body / mark("for"), - ForEach = key("for") * Ct(AssignableNameList) * key("in") * DisableDo * ensure(Ct(sym("*") * Exp / mark("unpack") + ExpList), PopDo) * key("do") ^ -1 * Body / mark("foreach"), - Do = key("do") * Body / mark("do"), - Comprehension = sym("[") * Exp * CompInner * sym("]") / mark("comprehension"), - TblComprehension = sym("{") * Ct(Exp * (sym(",") * Exp) ^ -1) * CompInner * sym("}") / mark("tblcomprehension"), - CompInner = Ct((CompForEach + CompFor) * CompClause ^ 0), - CompForEach = key("for") * Ct(NameList) * key("in") * (sym("*") * Exp / mark("unpack") + Exp) / mark("foreach"), - CompFor = key("for" * Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1) / mark("for")), - CompClause = CompFor + CompForEach + key("when") * Exp / mark("when"), - Assign = sym("=") * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark("assign"), - Update = ((sym("..=") + sym("+=") + sym("-=") + sym("*=") + sym("/=") + sym("%=") + sym("or=") + sym("and=")) / trim) * Exp / mark("update"), - CharOperators = Space * C(S("+-*/%^><")), - WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op(".."), - BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0, - Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName, - Exp = Ct(Value * (BinaryOperator * Value) ^ 0) / flatten_or_mark("exp"), - SimpleValue = If + Unless + Switch + With + ClassDecl + ForEach + For + While + Cmt(Do, check_do) + sym("-") * -SomeSpace * Exp / mark("minus") + sym("#") * Exp / mark("length") + key("not") * Exp / mark("not") + TblComprehension + TableLit + Comprehension + FunLit + Num, - ChainValue = StringChain + ((Chain + DotChain + Callable) * Ct(InvokeArgs ^ -1)) / flatten_func, - Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue), - SliceValue = SimpleValue + ChainValue, - StringChain = String * (Ct((ColonCall + ColonSuffix) * ChainTail ^ -1) * Ct(InvokeArgs ^ -1)) ^ -1 / flatten_string_chain, - String = Space * DoubleString + Space * SingleString + LuaString, - SingleString = simple_string("'"), - DoubleString = simple_string('"', true), - LuaString = Cg(LuaStringOpen, "string_open") * Cb("string_open") * Break ^ -1 * C((1 - Cmt(C(LuaStringClose) * Cb("string_open"), check_lua_string)) ^ 0) * LuaStringClose / mark("string"), - LuaStringOpen = sym("[") * P("=") ^ 0 * "[" / trim, - LuaStringClose = "]" * P("=") ^ 0 * "]", - Callable = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"), - Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"), - FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(ExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""), - ChainTail = ChainItem ^ 1 * ColonSuffix ^ -1 + ColonSuffix, - Chain = Callable * ChainTail / mark("chain"), - DotChain = (sym(".") * Cc(-1) * (_Name / mark("dot")) * ChainTail ^ -1) / mark("chain") + (sym("\\") * Cc(-1) * ((_Name * Invoke / mark("colon")) * ChainTail ^ -1 + (_Name / mark("colon_stub")))) / mark("chain"), - ChainItem = Invoke + Slice + symx("[") * Exp / mark("index") * sym("]") + symx(".") * _Name / mark("dot") + ColonCall, - Slice = symx("[") * (SliceValue + Cc(1)) * sym(",") * (SliceValue + Cc("")) * (sym(",") * SliceValue) ^ -1 * sym("]") / mark("slice"), - ColonCall = symx("\\") * (_Name * Invoke) / mark("colon"), - ColonSuffix = symx("\\") * _Name / mark("colon_stub"), - Invoke = FnArgs / mark("call") + SingleString / wrap_func_arg + DoubleString / wrap_func_arg + LuaString / wrap_func_arg, - TableValue = KeyValue + Ct(Exp), - TableLit = sym("{") * Ct(TableValueList ^ -1 * sym(",") ^ -1 * (SpaceBreak * TableLitLine * (sym(",") ^ -1 * SpaceBreak * TableLitLine) ^ 0 * sym(",") ^ -1) ^ -1) * White * sym("}") / mark("table"), - TableValueList = TableValue * (sym(",") * TableValue) ^ 0, - TableLitLine = PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space, - TableBlockInner = Ct(KeyValueLine * (SpaceBreak ^ 1 * KeyValueLine) ^ 0), - TableBlock = SpaceBreak ^ 1 * Advance * ensure(TableBlockInner, PopIndent) / mark("table"), - ClassDecl = key("class") * -P(":") * (Assignable + Cc(nil)) * (key("extends") * PreventIndent * ensure(Exp, PopIndent) + C("")) ^ -1 * (ClassBlock + Ct("")) / mark("class"), - ClassBlock = SpaceBreak ^ 1 * Advance * Ct(ClassLine * (SpaceBreak ^ 1 * ClassLine) ^ 0) * PopIndent, - ClassLine = CheckIndent * ((KeyValueList / mark("props") + Statement / mark("stm") + Exp / mark("stm")) * sym(",") ^ -1), - Export = key("export") * (Cc("class") * ClassDecl + op("*") + op("^") + Ct(NameList) * (sym("=") * Ct(ExpListLow)) ^ -1) / mark("export"), - KeyValue = (sym(":") * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym("[") * Exp * sym("]") + DoubleString + SingleString) * symx(":") * (Exp + TableBlock + SpaceBreak ^ 1 * Exp)), - KeyValueList = KeyValue * (sym(",") * KeyValue) ^ 0, - KeyValueLine = CheckIndent * KeyValueList * sym(",") ^ -1, - FnArgsDef = sym("(") * Ct(FnArgDefList ^ -1) * (key("using") * Ct(NameList + Space * "nil") + Ct("")) * sym(")") + Ct("") * Ct(""), - FnArgDefList = FnArgDef * (sym(",") * FnArgDef) ^ 0 * (sym(",") * Ct(VarArg)) ^ 0 + Ct(VarArg), - FnArgDef = Ct((Name + SelfName) * (sym("=") * Exp) ^ -1), - FunLit = FnArgsDef * (sym("->") * Cc("slim") + sym("=>") * Cc("fat")) * (Body + Ct("")) / mark("fndef"), - NameList = Name * (sym(",") * Name) ^ 0, - NameOrDestructure = Name + TableLit, - AssignableNameList = NameOrDestructure * (sym(",") * NameOrDestructure) ^ 0, - ExpList = Exp * (sym(",") * Exp) ^ 0, - ExpListLow = Exp * ((sym(",") + sym(";")) * Exp) ^ 0, - InvokeArgs = -P("-") * (ExpList * (sym(",") * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock ^ -1) + TableBlock) ^ -1 + TableBlock), - ArgBlock = ArgLine * (sym(",") * SpaceBreak * ArgLine) ^ 0 * PopIndent, - ArgLine = CheckIndent * ExpList - }) - return g, state -end) + local Name = Cmt(SpaceName, function(str, pos, name) + if keywords[name] then + return false + end + return true + end) / trim + local SelfName = Space * "@" * ("@" * (_Name / mark("self_class") + Cc("self.__class")) + _Name / mark("self") + Cc("self")) + local KeyName = SelfName + Space * _Name / mark("key_literal") + local VarArg = Space * P("...") / trim + local expAnd + expAnd = function(a, b) + return -((-a) + (-b)) + end + local g = P({ + root or File, + File = Shebang ^ -1 * (Block + Ct("")), + Block = Ct(Line * (Break ^ 1 * Line) ^ 0), + CheckIndent = Cmt(Indent, check_indent), + Line = EmptyLine + CheckIndent * Statement + Space * #Stop, + Statement = pos(Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign) ^ -1 / format_assign) * Space * ((key("if") * Exp * (key("else") * Exp) ^ -1 * Space / mark("if") + key("unless") * Exp / mark("unless") + CompInner / mark("comprehension")) * Space) ^ -1 / wrap_decorator, + Body = Space ^ -1 * Break * EmptyLine ^ 0 * InBlock + Ct(Statement), + Advance = #Cmt(Indent, advance_indent), + PushIndent = Cmt(Indent, push_indent), + PreventIndent = Cmt(Cc(-1), push_indent), + PopIndent = Cmt("", pop_indent), + InBlock = Advance * Block * PopIndent, + Local = key("local") * ((op("*") + op("^")) / mark("declare_glob") + Ct(NameList) / mark("declare_with_shadows")), + Import = key("import") * Ct(ImportNameList) * SpaceBreak ^ 0 * key("from") * Exp / mark("import"), + ImportName = (sym("\\") * Ct(Cc("colon_stub") * Name) + Name), + ImportNameList = SpaceBreak ^ 0 * ImportName * ((SpaceBreak ^ 1 + sym(",") * SpaceBreak ^ 0) * ImportName) ^ 0, + BreakLoop = Ct(key("break") / trim) + Ct(key("continue") / trim), + Return = key("return") * (ExpListLow / mark("explist") + C("")) / mark("return"), + WithExp = Ct(ExpList) * Assign ^ -1 / format_assign, + With = key("with") * DisableDo * ensure(WithExp, PopDo) * key("do") ^ -1 * Body / mark("with"), + Switch = key("switch") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Space ^ -1 * Break * SwitchBlock / mark("switch"), + SwitchBlock = EmptyLine ^ 0 * Advance * Ct(SwitchCase * (Break ^ 1 * SwitchCase) ^ 0 * (Break ^ 1 * SwitchElse) ^ -1) * PopIndent, + SwitchCase = key("when") * Ct(ExpList) * key("then") ^ -1 * Body / mark("case"), + SwitchElse = key("else") * Body / mark("else"), + IfCond = Exp * Assign ^ -1 / format_single_assign, + If = key("if") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("elseif") * pos(IfCond) * key("then") ^ -1 * Body / mark("elseif")) ^ 0 * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("if"), + Unless = key("unless") * IfCond * key("then") ^ -1 * Body * ((Break * CheckIndent) ^ -1 * EmptyLine ^ 0 * key("else") * Body / mark("else")) ^ -1 / mark("unless"), + While = key("while") * DisableDo * ensure(Exp, PopDo) * key("do") ^ -1 * Body / mark("while"), + For = key("for") * DisableDo * ensure(Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1), PopDo) * key("do") ^ -1 * Body / mark("for"), + ForEach = key("for") * Ct(AssignableNameList) * key("in") * DisableDo * ensure(Ct(sym("*") * Exp / mark("unpack") + ExpList), PopDo) * key("do") ^ -1 * Body / mark("foreach"), + Do = key("do") * Body / mark("do"), + Comprehension = sym("[") * Exp * CompInner * sym("]") / mark("comprehension"), + TblComprehension = sym("{") * Ct(Exp * (sym(",") * Exp) ^ -1) * CompInner * sym("}") / mark("tblcomprehension"), + CompInner = Ct((CompForEach + CompFor) * CompClause ^ 0), + CompForEach = key("for") * Ct(NameList) * key("in") * (sym("*") * Exp / mark("unpack") + Exp) / mark("foreach"), + CompFor = key("for" * Name * sym("=") * Ct(Exp * sym(",") * Exp * (sym(",") * Exp) ^ -1) / mark("for")), + CompClause = CompFor + CompForEach + key("when") * Exp / mark("when"), + Assign = sym("=") * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark("assign"), + Update = ((sym("..=") + sym("+=") + sym("-=") + sym("*=") + sym("/=") + sym("%=") + sym("or=") + sym("and=")) / trim) * Exp / mark("update"), + CharOperators = Space * C(S("+-*/%^><")), + WordOperators = op("or") + op("and") + op("<=") + op(">=") + op("~=") + op("!=") + op("==") + op(".."), + BinaryOperator = (WordOperators + CharOperators) * SpaceBreak ^ 0, + Assignable = Cmt(DotChain + Chain, check_assignable) + Name + SelfName, + Exp = Ct(Value * (BinaryOperator * Value) ^ 0) / flatten_or_mark("exp"), + SimpleValue = If + Unless + Switch + With + ClassDecl + ForEach + For + While + Cmt(Do, check_do) + sym("-") * -SomeSpace * Exp / mark("minus") + sym("#") * Exp / mark("length") + key("not") * Exp / mark("not") + TblComprehension + TableLit + Comprehension + FunLit + Num, + ChainValue = StringChain + ((Chain + DotChain + Callable) * Ct(InvokeArgs ^ -1)) / flatten_func, + Value = pos(SimpleValue + Ct(KeyValueList) / mark("table") + ChainValue), + SliceValue = SimpleValue + ChainValue, + StringChain = String * (Ct((ColonCall + ColonSuffix) * ChainTail ^ -1) * Ct(InvokeArgs ^ -1)) ^ -1 / flatten_string_chain, + String = Space * DoubleString + Space * SingleString + LuaString, + SingleString = simple_string("'"), + DoubleString = simple_string('"', true), + LuaString = Cg(LuaStringOpen, "string_open") * Cb("string_open") * Break ^ -1 * C((1 - Cmt(C(LuaStringClose) * Cb("string_open"), check_lua_string)) ^ 0) * LuaStringClose / mark("string"), + LuaStringOpen = sym("[") * P("=") ^ 0 * "[" / trim, + LuaStringClose = "]" * P("=") ^ 0 * "]", + Callable = pos(Name / mark("ref")) + SelfName + VarArg + Parens / mark("parens"), + Parens = sym("(") * SpaceBreak ^ 0 * Exp * SpaceBreak ^ 0 * sym(")"), + FnArgs = symx("(") * SpaceBreak ^ 0 * Ct(ExpList ^ -1) * SpaceBreak ^ 0 * sym(")") + sym("!") * -P("=") * Ct(""), + ChainTail = ChainItem ^ 1 * ColonSuffix ^ -1 + ColonSuffix, + Chain = Callable * ChainTail / mark("chain"), + DotChain = (sym(".") * Cc(-1) * (_Name / mark("dot")) * ChainTail ^ -1) / mark("chain") + (sym("\\") * Cc(-1) * ((_Name * Invoke / mark("colon")) * ChainTail ^ -1 + (_Name / mark("colon_stub")))) / mark("chain"), + ChainItem = Invoke + Slice + symx("[") * Exp / mark("index") * sym("]") + symx(".") * _Name / mark("dot") + ColonCall, + Slice = symx("[") * (SliceValue + Cc(1)) * sym(",") * (SliceValue + Cc("")) * (sym(",") * SliceValue) ^ -1 * sym("]") / mark("slice"), + ColonCall = symx("\\") * (_Name * Invoke) / mark("colon"), + ColonSuffix = symx("\\") * _Name / mark("colon_stub"), + Invoke = FnArgs / mark("call") + SingleString / wrap_func_arg + DoubleString / wrap_func_arg + LuaString / wrap_func_arg, + TableValue = KeyValue + Ct(Exp), + TableLit = sym("{") * Ct(TableValueList ^ -1 * sym(",") ^ -1 * (SpaceBreak * TableLitLine * (sym(",") ^ -1 * SpaceBreak * TableLitLine) ^ 0 * sym(",") ^ -1) ^ -1) * White * sym("}") / mark("table"), + TableValueList = TableValue * (sym(",") * TableValue) ^ 0, + TableLitLine = PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space, + TableBlockInner = Ct(KeyValueLine * (SpaceBreak ^ 1 * KeyValueLine) ^ 0), + TableBlock = SpaceBreak ^ 1 * Advance * ensure(TableBlockInner, PopIndent) / mark("table"), + ClassDecl = key("class") * -P(":") * (Assignable + Cc(nil)) * (key("extends") * PreventIndent * ensure(Exp, PopIndent) + C("")) ^ -1 * (ClassBlock + Ct("")) / mark("class"), + ClassBlock = SpaceBreak ^ 1 * Advance * Ct(ClassLine * (SpaceBreak ^ 1 * ClassLine) ^ 0) * PopIndent, + ClassLine = CheckIndent * ((KeyValueList / mark("props") + Statement / mark("stm") + Exp / mark("stm")) * sym(",") ^ -1), + Export = key("export") * (Cc("class") * ClassDecl + op("*") + op("^") + Ct(NameList) * (sym("=") * Ct(ExpListLow)) ^ -1) / mark("export"), + KeyValue = (sym(":") * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym("[") * Exp * sym("]") + DoubleString + SingleString) * symx(":") * (Exp + TableBlock + SpaceBreak ^ 1 * Exp)), + KeyValueList = KeyValue * (sym(",") * KeyValue) ^ 0, + KeyValueLine = CheckIndent * KeyValueList * sym(",") ^ -1, + FnArgsDef = sym("(") * Ct(FnArgDefList ^ -1) * (key("using") * Ct(NameList + Space * "nil") + Ct("")) * sym(")") + Ct("") * Ct(""), + FnArgDefList = FnArgDef * (sym(",") * FnArgDef) ^ 0 * (sym(",") * Ct(VarArg)) ^ 0 + Ct(VarArg), + FnArgDef = Ct((Name + SelfName) * (sym("=") * Exp) ^ -1), + FunLit = FnArgsDef * (sym("->") * Cc("slim") + sym("=>") * Cc("fat")) * (Body + Ct("")) / mark("fndef"), + NameList = Name * (sym(",") * Name) ^ 0, + NameOrDestructure = Name + TableLit, + AssignableNameList = NameOrDestructure * (sym(",") * NameOrDestructure) ^ 0, + ExpList = Exp * (sym(",") * Exp) ^ 0, + ExpListLow = Exp * ((sym(",") + sym(";")) * Exp) ^ 0, + InvokeArgs = -P("-") * (ExpList * (sym(",") * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock ^ -1) + TableBlock) ^ -1 + TableBlock), + ArgBlock = ArgLine * (sym(",") * SpaceBreak * ArgLine) ^ 0 * PopIndent, + ArgLine = CheckIndent * ExpList + }) + return g, state + end) +end +local build_grammar = build_grammar_factory() local file_parser -file_parser = function() - local g, state = build_grammar() +file_parser = function(litmoon) + if litmoon == nil then + litmoon = false + end + local g, state + if litmoon then + g, state = build_grammar_factory(true)() + else + g, state = build_grammar() + end local file_grammar = White * g * White * -1 return { match = function(self, str) @@ -237,7 +257,10 @@ end return { extract_line = extract_line, build_grammar = build_grammar, - string = function(str) - return file_parser():match(str) + string = function(str, litmoon) + if litmoon == nil then + litmoon = false + end + return file_parser(litmoon):match(str) end } diff --git a/moonscript/parse.moon b/moonscript/parse.moon index 7b81bb39..933d0611 100644 --- a/moonscript/parse.moon +++ b/moonscript/parse.moon @@ -15,12 +15,11 @@ import wrap_env from require "moonscript.parse.env" } = lpeg { - :White, :Break, :Stop, :Comment, :Space, :SomeSpace, :SpaceBreak, :EmptyLine, - :AlphaNum, :Num, :Shebang + :White, :Break, :Stop, :LitmoonCommentLine, + :AlphaNum, :Num, :Shebang,:Comment,:Space,:SomeSpace,:SpaceBreak, :mkEmptyLine Name: _Name } = require "moonscript.parse.literals" - SpaceName = Space * _Name Num = Space * (Num / (v) -> {"number", v}) @@ -32,297 +31,307 @@ Num = Space * (Num / (v) -> {"number", v}) } = require "moonscript.parse.util" -build_grammar = wrap_env debug_grammar, (root) -> - _indent = Stack 0 - _do_stack = Stack 0 +build_grammar_factory = (litmoon=false) -> + EmptyLine=mkEmptyLine litmoon + wrap_env debug_grammar, (root) -> + _indent = Stack (litmoon and 4 or 0) + _do_stack = Stack 0 - state = { - -- last pos we saw, used to report error location - last_pos: 0 - } + state = { + -- last pos we saw, used to report error location + last_pos: 0 + } + + check_indent = (str, pos, indent) -> + state.last_pos = pos + _indent\top! == indent - check_indent = (str, pos, indent) -> - state.last_pos = pos - _indent\top! == indent + advance_indent = (str, pos, indent) -> + top = _indent\top! + if top != -1 and indent > top + _indent\push indent + true - advance_indent = (str, pos, indent) -> - top = _indent\top! - if top != -1 and indent > top + push_indent = (str, pos, indent) -> _indent\push indent true - push_indent = (str, pos, indent) -> - _indent\push indent - true + pop_indent = -> + assert _indent\pop!, "unexpected outdent" + true - pop_indent = -> - assert _indent\pop!, "unexpected outdent" - true + check_do = (str, pos, do_node) -> + top = _do_stack\top! + if top == nil or top + return true, do_node + false - check_do = (str, pos, do_node) -> - top = _do_stack\top! - if top == nil or top - return true, do_node - false + disable_do = -> + _do_stack\push false + true - disable_do = -> - _do_stack\push false - true + pop_do = -> + assert _do_stack\pop! != nil, "unexpected do pop" + true - pop_do = -> - assert _do_stack\pop! != nil, "unexpected do pop" - true + DisableDo = Cmt "", disable_do + PopDo = Cmt "", pop_do - DisableDo = Cmt "", disable_do - PopDo = Cmt "", pop_do + keywords = {} + key = (chars) -> + keywords[chars] = true + Space * chars * -AlphaNum - keywords = {} - key = (chars) -> - keywords[chars] = true - Space * chars * -AlphaNum + op = (chars) -> + patt = Space * C chars + -- it's a word, treat like keyword + if chars\match "^%w*$" + keywords[chars] = true + patt *= -AlphaNum - op = (chars) -> - patt = Space * C chars - -- it's a word, treat like keyword - if chars\match "^%w*$" - keywords[chars] = true - patt *= -AlphaNum + patt - patt + Name = Cmt(SpaceName, (str, pos, name) -> + return false if keywords[name] + true + ) / trim - Name = Cmt(SpaceName, (str, pos, name) -> - return false if keywords[name] - true - ) / trim + SelfName = Space * "@" * ( + "@" * (_Name / mark"self_class" + Cc"self.__class") + + _Name / mark"self" + + Cc"self" -- @ by itself + ) - SelfName = Space * "@" * ( - "@" * (_Name / mark"self_class" + Cc"self.__class") + - _Name / mark"self" + - Cc"self" -- @ by itself - ) + KeyName = SelfName + Space * _Name / mark"key_literal" + VarArg = Space * P"..." / trim - KeyName = SelfName + Space * _Name / mark"key_literal" - VarArg = Space * P"..." / trim + expAnd= (a,b) -> -((-a)+(-b)) - g = P { - root or File - File: Shebang^-1 * (Block + Ct"") - Block: Ct(Line * (Break^1 * Line)^0) - CheckIndent: Cmt(Indent, check_indent), -- validates line is in correct indent - Line: (CheckIndent * Statement + Space * #Stop) + g = P { + root or File + File: Shebang^-1 * (Block + Ct"") + Block: Ct(Line * (Break^1 * Line)^0) + CheckIndent: Cmt(Indent, check_indent), -- validates line is in correct indent + Line: EmptyLine + CheckIndent * Statement + Space * #Stop - Statement: pos( - Import + While + With + For + ForEach + Switch + Return + - Local + Export + BreakLoop + - Ct(ExpList) * (Update + Assign)^-1 / format_assign - ) * Space * (( - -- statement decorators - key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" + - key"unless" * Exp / mark"unless" + - CompInner / mark"comprehension" - ) * Space)^-1 / wrap_decorator + Statement: pos( + Import + While + With + For + ForEach + Switch + Return + + Local + Export + BreakLoop + + Ct(ExpList) * (Update + Assign)^-1 / format_assign + ) * Space * (( + -- statement decorators + key"if" * Exp * (key"else" * Exp)^-1 * Space / mark"if" + + key"unless" * Exp / mark"unless" + + CompInner / mark"comprehension" + ) * Space)^-1 / wrap_decorator - Body: Space^-1 * Break * EmptyLine^0 * InBlock + Ct(Statement), -- either a statement, or an indented block + Body: Space^-1 * Break * EmptyLine^0 * InBlock + Ct(Statement), -- either a statement, or an indented block - Advance: #Cmt(Indent, advance_indent), -- Advances the indent, gives back whitespace for CheckIndent - PushIndent: Cmt(Indent, push_indent) - PreventIndent: Cmt(Cc(-1), push_indent) - PopIndent: Cmt("", pop_indent) - InBlock: Advance * Block * PopIndent + Advance: #Cmt(Indent, advance_indent), -- Advances the indent, gives back whitespace for CheckIndent + PushIndent: Cmt(Indent, push_indent) + PreventIndent: Cmt(Cc(-1), push_indent) + PopIndent: Cmt("", pop_indent) + InBlock: Advance * Block * PopIndent - Local: key"local" * ((op"*" + op"^") / mark"declare_glob" + Ct(NameList) / mark"declare_with_shadows") + Local: key"local" * ((op"*" + op"^") / mark"declare_glob" + Ct(NameList) / mark"declare_with_shadows") - Import: key"import" * Ct(ImportNameList) * SpaceBreak^0 * key"from" * Exp / mark"import" - ImportName: (sym"\\" * Ct(Cc"colon_stub" * Name) + Name) - ImportNameList: SpaceBreak^0 * ImportName * ((SpaceBreak^1 + sym"," * SpaceBreak^0) * ImportName)^0 + Import: key"import" * Ct(ImportNameList) * SpaceBreak^0 * key"from" * Exp / mark"import" + ImportName: (sym"\\" * Ct(Cc"colon_stub" * Name) + Name) + ImportNameList: SpaceBreak^0 * ImportName * ((SpaceBreak^1 + sym"," * SpaceBreak^0) * ImportName)^0 - BreakLoop: Ct(key"break"/trim) + Ct(key"continue"/trim) + BreakLoop: Ct(key"break"/trim) + Ct(key"continue"/trim) - Return: key"return" * (ExpListLow/mark"explist" + C"") / mark"return" + Return: key"return" * (ExpListLow/mark"explist" + C"") / mark"return" - WithExp: Ct(ExpList) * Assign^-1 / format_assign - With: key"with" * DisableDo * ensure(WithExp, PopDo) * key"do"^-1 * Body / mark"with" + WithExp: Ct(ExpList) * Assign^-1 / format_assign + With: key"with" * DisableDo * ensure(WithExp, PopDo) * key"do"^-1 * Body / mark"with" - Switch: key"switch" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Space^-1 * Break * SwitchBlock / mark"switch" + Switch: key"switch" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Space^-1 * Break * SwitchBlock / mark"switch" - SwitchBlock: EmptyLine^0 * Advance * Ct(SwitchCase * (Break^1 * SwitchCase)^0 * (Break^1 * SwitchElse)^-1) * PopIndent - SwitchCase: key"when" * Ct(ExpList) * key"then"^-1 * Body / mark"case" - SwitchElse: key"else" * Body / mark"else" + SwitchBlock: EmptyLine^0 * Advance * Ct(SwitchCase * (Break^1 * SwitchCase)^0 * (Break^1 * SwitchElse)^-1) * PopIndent + SwitchCase: key"when" * Ct(ExpList) * key"then"^-1 * Body / mark"case" + SwitchElse: key"else" * Body / mark"else" - IfCond: Exp * Assign^-1 / format_single_assign + IfCond: Exp * Assign^-1 / format_single_assign - If: key"if" * IfCond * key"then"^-1 * Body * - ((Break * CheckIndent)^-1 * EmptyLine^0 * key"elseif" * pos(IfCond) * key"then"^-1 * Body / mark"elseif")^0 * - ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"if" + If: key"if" * IfCond * key"then"^-1 * Body * + ((Break * CheckIndent)^-1 * EmptyLine^0 * key"elseif" * pos(IfCond) * key"then"^-1 * Body / mark"elseif")^0 * + ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"if" - Unless: key"unless" * IfCond * key"then"^-1 * Body * - ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"unless" + Unless: key"unless" * IfCond * key"then"^-1 * Body * + ((Break * CheckIndent)^-1 * EmptyLine^0 * key"else" * Body / mark"else")^-1 / mark"unless" - While: key"while" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Body / mark"while" + While: key"while" * DisableDo * ensure(Exp, PopDo) * key"do"^-1 * Body / mark"while" - For: key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) * - key"do"^-1 * Body / mark"for" + For: key"for" * DisableDo * ensure(Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1), PopDo) * + key"do"^-1 * Body / mark"for" - ForEach: key"for" * Ct(AssignableNameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach" + ForEach: key"for" * Ct(AssignableNameList) * key"in" * DisableDo * ensure(Ct(sym"*" * Exp / mark"unpack" + ExpList), PopDo) * key"do"^-1 * Body / mark"foreach" - Do: key"do" * Body / mark"do" + Do: key"do" * Body / mark"do" - Comprehension: sym"[" * Exp * CompInner * sym"]" / mark"comprehension" + Comprehension: sym"[" * Exp * CompInner * sym"]" / mark"comprehension" - TblComprehension: sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension" + TblComprehension: sym"{" * Ct(Exp * (sym"," * Exp)^-1) * CompInner * sym"}" / mark"tblcomprehension" - CompInner: Ct((CompForEach + CompFor) * CompClause^0) - CompForEach: key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"foreach" - CompFor: key "for" * Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1) / mark"for" - CompClause: CompFor + CompForEach + key"when" * Exp / mark"when" + CompInner: Ct((CompForEach + CompFor) * CompClause^0) + CompForEach: key"for" * Ct(NameList) * key"in" * (sym"*" * Exp / mark"unpack" + Exp) / mark"foreach" + CompFor: key "for" * Name * sym"=" * Ct(Exp * sym"," * Exp * (sym"," * Exp)^-1) / mark"for" + CompClause: CompFor + CompForEach + key"when" * Exp / mark"when" - Assign: sym"=" * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark"assign" - Update: ((sym"..=" + sym"+=" + sym"-=" + sym"*=" + sym"/=" + sym"%=" + sym"or=" + sym"and=") / trim) * Exp / mark"update" + Assign: sym"=" * (Ct(With + If + Switch) + Ct(TableBlock + ExpListLow)) / mark"assign" + Update: ((sym"..=" + sym"+=" + sym"-=" + sym"*=" + sym"/=" + sym"%=" + sym"or=" + sym"and=") / trim) * Exp / mark"update" - CharOperators: Space * C(S"+-*/%^><") - WordOperators: op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." - BinaryOperator: (WordOperators + CharOperators) * SpaceBreak^0 + CharOperators: Space * C(S"+-*/%^><") + WordOperators: op"or" + op"and" + op"<=" + op">=" + op"~=" + op"!=" + op"==" + op".." + BinaryOperator: (WordOperators + CharOperators) * SpaceBreak^0 - Assignable: Cmt(DotChain + Chain, check_assignable) + Name + SelfName - Exp: Ct(Value * (BinaryOperator * Value)^0) / flatten_or_mark"exp" + Assignable: Cmt(DotChain + Chain, check_assignable) + Name + SelfName + Exp: Ct(Value * (BinaryOperator * Value)^0) / flatten_or_mark"exp" - SimpleValue: - If + Unless + - Switch + - With + - ClassDecl + - ForEach + For + While + - Cmt(Do, check_do) + - sym"-" * -SomeSpace * Exp / mark"minus" + - sym"#" * Exp / mark"length" + - key"not" * Exp / mark"not" + - TblComprehension + - TableLit + - Comprehension + - FunLit + - Num + SimpleValue: + If + Unless + + Switch + + With + + ClassDecl + + ForEach + For + While + + Cmt(Do, check_do) + + sym"-" * -SomeSpace * Exp / mark"minus" + + sym"#" * Exp / mark"length" + + key"not" * Exp / mark"not" + + TblComprehension + + TableLit + + Comprehension + + FunLit + + Num - ChainValue: -- a function call or an object access - StringChain + - ((Chain + DotChain + Callable) * Ct(InvokeArgs^-1)) / flatten_func + ChainValue: -- a function call or an object access + StringChain + + ((Chain + DotChain + Callable) * Ct(InvokeArgs^-1)) / flatten_func - Value: pos( - SimpleValue + - Ct(KeyValueList) / mark"table" + - ChainValue) + Value: pos( + SimpleValue + + Ct(KeyValueList) / mark"table" + + ChainValue) - SliceValue: SimpleValue + ChainValue + SliceValue: SimpleValue + ChainValue - StringChain: String * - (Ct((ColonCall + ColonSuffix) * ChainTail^-1) * Ct(InvokeArgs^-1))^-1 / flatten_string_chain + StringChain: String * + (Ct((ColonCall + ColonSuffix) * ChainTail^-1) * Ct(InvokeArgs^-1))^-1 / flatten_string_chain - String: Space * DoubleString + Space * SingleString + LuaString - SingleString: simple_string("'") - DoubleString: simple_string('"', true) + String: Space * DoubleString + Space * SingleString + LuaString + SingleString: simple_string("'") + DoubleString: simple_string('"', true) - LuaString: Cg(LuaStringOpen, "string_open") * Cb"string_open" * Break^-1 * - C((1 - Cmt(C(LuaStringClose) * Cb"string_open", check_lua_string))^0) * - LuaStringClose / mark"string" + LuaString: Cg(LuaStringOpen, "string_open") * Cb"string_open" * Break^-1 * + C((1 - Cmt(C(LuaStringClose) * Cb"string_open", check_lua_string))^0) * + LuaStringClose / mark"string" - LuaStringOpen: sym"[" * P"="^0 * "[" / trim - LuaStringClose: "]" * P"="^0 * "]" + LuaStringOpen: sym"[" * P"="^0 * "[" / trim + LuaStringClose: "]" * P"="^0 * "]" - Callable: pos(Name / mark"ref") + SelfName + VarArg + Parens / mark"parens" - Parens: sym"(" * SpaceBreak^0 * Exp * SpaceBreak^0 * sym")" + Callable: pos(Name / mark"ref") + SelfName + VarArg + Parens / mark"parens" + Parens: sym"(" * SpaceBreak^0 * Exp * SpaceBreak^0 * sym")" - FnArgs: symx"(" * SpaceBreak^0 * Ct(ExpList^-1) * SpaceBreak^0 * sym")" + sym"!" * -P"=" * Ct"" + FnArgs: symx"(" * SpaceBreak^0 * Ct(ExpList^-1) * SpaceBreak^0 * sym")" + sym"!" * -P"=" * Ct"" - ChainTail: ChainItem^1 * ColonSuffix^-1 + ColonSuffix + ChainTail: ChainItem^1 * ColonSuffix^-1 + ColonSuffix - -- a list of funcalls and indexes on a callable - Chain: Callable * ChainTail / mark"chain" + -- a list of funcalls and indexes on a callable + Chain: Callable * ChainTail / mark"chain" - -- shorthand dot call for use in with statement - DotChain: - (sym"." * Cc(-1) * (_Name / mark"dot") * ChainTail^-1) / mark"chain" + - (sym"\\" * Cc(-1) * ( - (_Name * Invoke / mark"colon") * ChainTail^-1 + - (_Name / mark"colon_stub") - )) / mark"chain" + -- shorthand dot call for use in with statement + DotChain: + (sym"." * Cc(-1) * (_Name / mark"dot") * ChainTail^-1) / mark"chain" + + (sym"\\" * Cc(-1) * ( + (_Name * Invoke / mark"colon") * ChainTail^-1 + + (_Name / mark"colon_stub") + )) / mark"chain" - ChainItem: - Invoke + - Slice + - symx"[" * Exp/mark"index" * sym"]" + - symx"." * _Name/mark"dot" + - ColonCall + ChainItem: + Invoke + + Slice + + symx"[" * Exp/mark"index" * sym"]" + + symx"." * _Name/mark"dot" + + ColonCall - Slice: symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") * - (sym"," * SliceValue)^-1 *sym"]" / mark"slice" + Slice: symx"[" * (SliceValue + Cc(1)) * sym"," * (SliceValue + Cc"") * + (sym"," * SliceValue)^-1 *sym"]" / mark"slice" - ColonCall: symx"\\" * (_Name * Invoke) / mark"colon" - ColonSuffix: symx"\\" * _Name / mark"colon_stub" + ColonCall: symx"\\" * (_Name * Invoke) / mark"colon" + ColonSuffix: symx"\\" * _Name / mark"colon_stub" - Invoke: FnArgs/mark"call" + - SingleString / wrap_func_arg + - DoubleString / wrap_func_arg + - LuaString / wrap_func_arg + Invoke: FnArgs/mark"call" + + SingleString / wrap_func_arg + + DoubleString / wrap_func_arg + + LuaString / wrap_func_arg - TableValue: KeyValue + Ct(Exp) + TableValue: KeyValue + Ct(Exp) - TableLit: sym"{" * Ct( - TableValueList^-1 * sym","^-1 * - (SpaceBreak * TableLitLine * (sym","^-1 * SpaceBreak * TableLitLine)^0 * sym","^-1)^-1 - ) * White * sym"}" / mark"table" - - TableValueList: TableValue * (sym"," * TableValue)^0 - TableLitLine: PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space - - -- the unbounded table - TableBlockInner: Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0) - TableBlock: SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table" - - ClassDecl: key"class" * -P":" * (Assignable + Cc(nil)) * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * (ClassBlock + Ct("")) / mark"class" - - ClassBlock: SpaceBreak^1 * Advance * - Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent - ClassLine: CheckIndent * (( - KeyValueList / mark"props" + - Statement / mark"stm" + - Exp / mark"stm" - ) * sym","^-1) - - Export: key"export" * ( - Cc"class" * ClassDecl + - op"*" + op"^" + - Ct(NameList) * (sym"=" * Ct(ExpListLow))^-1) / mark"export" - - KeyValue: (sym":" * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym"[" * Exp * sym"]" + DoubleString + SingleString) * symx":" * (Exp + TableBlock + SpaceBreak^1 * Exp)) - KeyValueList: KeyValue * (sym"," * KeyValue)^0 - KeyValueLine: CheckIndent * KeyValueList * sym","^-1 + TableLit: sym"{" * Ct( + TableValueList^-1 * sym","^-1 * + (SpaceBreak * TableLitLine * (sym","^-1 * SpaceBreak * TableLitLine)^0 * sym","^-1)^-1 + ) * White * sym"}" / mark"table" + + TableValueList: TableValue * (sym"," * TableValue)^0 + TableLitLine: PushIndent * ((TableValueList * PopIndent) + (PopIndent * Cut)) + Space + + -- the unbounded table + TableBlockInner: Ct(KeyValueLine * (SpaceBreak^1 * KeyValueLine)^0) + TableBlock: SpaceBreak^1 * Advance * ensure(TableBlockInner, PopIndent) / mark"table" + + ClassDecl: key"class" * -P":" * (Assignable + Cc(nil)) * (key"extends" * PreventIndent * ensure(Exp, PopIndent) + C"")^-1 * (ClassBlock + Ct("")) / mark"class" + + ClassBlock: SpaceBreak^1 * Advance * + Ct(ClassLine * (SpaceBreak^1 * ClassLine)^0) * PopIndent + ClassLine: CheckIndent * (( + KeyValueList / mark"props" + + Statement / mark"stm" + + Exp / mark"stm" + ) * sym","^-1) + + Export: key"export" * ( + Cc"class" * ClassDecl + + op"*" + op"^" + + Ct(NameList) * (sym"=" * Ct(ExpListLow))^-1) / mark"export" + + KeyValue: (sym":" * -SomeSpace * Name * lpeg.Cp()) / self_assign + Ct((KeyName + sym"[" * Exp * sym"]" + DoubleString + SingleString) * symx":" * (Exp + TableBlock + SpaceBreak^1 * Exp)) + KeyValueList: KeyValue * (sym"," * KeyValue)^0 + KeyValueLine: CheckIndent * KeyValueList * sym","^-1 - FnArgsDef: sym"(" * Ct(FnArgDefList^-1) * - (key"using" * Ct(NameList + Space * "nil") + Ct"") * - sym")" + Ct"" * Ct"" + FnArgsDef: sym"(" * Ct(FnArgDefList^-1) * + (key"using" * Ct(NameList + Space * "nil") + Ct"") * + sym")" + Ct"" * Ct"" - FnArgDefList: FnArgDef * (sym"," * FnArgDef)^0 * (sym"," * Ct(VarArg))^0 + Ct(VarArg) - FnArgDef: Ct((Name + SelfName) * (sym"=" * Exp)^-1) + FnArgDefList: FnArgDef * (sym"," * FnArgDef)^0 * (sym"," * Ct(VarArg))^0 + Ct(VarArg) + FnArgDef: Ct((Name + SelfName) * (sym"=" * Exp)^-1) - FunLit: FnArgsDef * - (sym"->" * Cc"slim" + sym"=>" * Cc"fat") * - (Body + Ct"") / mark"fndef" + FunLit: FnArgsDef * + (sym"->" * Cc"slim" + sym"=>" * Cc"fat") * + (Body + Ct"") / mark"fndef" - NameList: Name * (sym"," * Name)^0 - NameOrDestructure: Name + TableLit - AssignableNameList: NameOrDestructure * (sym"," * NameOrDestructure)^0 + NameList: Name * (sym"," * Name)^0 + NameOrDestructure: Name + TableLit + AssignableNameList: NameOrDestructure * (sym"," * NameOrDestructure)^0 - ExpList: Exp * (sym"," * Exp)^0 - ExpListLow: Exp * ((sym"," + sym";") * Exp)^0 + ExpList: Exp * (sym"," * Exp)^0 + ExpListLow: Exp * ((sym"," + sym";") * Exp)^0 - InvokeArgs: -P"-" * (ExpList * (sym"," * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock^-1) + TableBlock)^-1 + TableBlock) - ArgBlock: ArgLine * (sym"," * SpaceBreak * ArgLine)^0 * PopIndent - ArgLine: CheckIndent * ExpList - } + InvokeArgs: -P"-" * (ExpList * (sym"," * (TableBlock + SpaceBreak * Advance * ArgBlock * TableBlock^-1) + TableBlock)^-1 + TableBlock) + ArgBlock: ArgLine * (sym"," * SpaceBreak * ArgLine)^0 * PopIndent + ArgLine: CheckIndent * ExpList + } + + g, state - g, state +build_grammar = build_grammar_factory! -file_parser = -> - g, state = build_grammar! +file_parser = (litmoon=false)-> + local g,state + if litmoon + g, state = build_grammar_factory(true)! + else + g, state = build_grammar! file_grammar = White * g * White * -1 { @@ -359,6 +368,6 @@ file_parser = -> -- parse a string as a file -- returns tree, or nil and error message - string: (str) -> file_parser!\match str + string: (str,litmoon=false) -> file_parser(litmoon)\match str } diff --git a/moonscript/parse/literals.lua b/moonscript/parse/literals.lua index 61d6e2b8..083d27ff 100644 --- a/moonscript/parse/literals.lua +++ b/moonscript/parse/literals.lua @@ -9,11 +9,23 @@ local White = S(" \t\r\n") ^ 0 local plain_space = S(" \t") ^ 0 local Break = P("\r") ^ -1 * P("\n") local Stop = Break + -1 +local LitmoonCommentLine = -(P(" ") ^ 4 + P("\t") ^ 1) * (1 - S("\r\n")) ^ 1 * #Stop local Comment = P("--") * (1 - S("\r\n")) ^ 0 * #Stop local Space = plain_space * Comment ^ -1 local SomeSpace = S(" \t") ^ 1 * Comment ^ -1 local SpaceBreak = Space * Break -local EmptyLine = SpaceBreak +local mkEmptyLine +mkEmptyLine = function(litmoon) + if litmoon == nil then + litmoon = false + end + if litmoon then + return SpaceBreak + LitmoonCommentLine + else + return SpaceBreak + end +end +local EmptyLine = mkEmptyLine() local AlphaNum = R("az", "AZ", "09", "__") local Name = C(R("az", "AZ", "__") * AlphaNum ^ 0) local Num = P("0x") * R("09", "af", "AF") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) ^ -1 + R("09") ^ 1 * (S("uU") ^ -1 * S("lL") ^ 2) + (R("09") ^ 1 * (P(".") * R("09") ^ 1) ^ -1 + P(".") * R("09") ^ 1) * (S("eE") * P("-") ^ -1 * R("09") ^ 1) ^ -1 @@ -30,5 +42,7 @@ return safe_module("moonscript.parse.literals", { AlphaNum = AlphaNum, Name = Name, Num = Num, - Shebang = Shebang + Shebang = Shebang, + LitmoonCommentLine = LitmoonCommentLine, + mkEmptyLine = mkEmptyLine }) diff --git a/moonscript/parse/literals.moon b/moonscript/parse/literals.moon index 8f0d8cd6..739dde48 100644 --- a/moonscript/parse/literals.moon +++ b/moonscript/parse/literals.moon @@ -8,12 +8,20 @@ plain_space = S" \t"^0 Break = P"\r"^-1 * P"\n" Stop = Break + -1 +LitmoonCommentLine = -(P" "^4 + P("\t")^1) * (1 - S"\r\n")^1 * #Stop + Comment = P"--" * (1 - S"\r\n")^0 * #Stop Space = plain_space * Comment^-1 SomeSpace = S" \t"^1 * Comment^-1 - SpaceBreak = Space * Break -EmptyLine = SpaceBreak + +mkEmptyLine=(litmoon=false)-> + if litmoon + return SpaceBreak + LitmoonCommentLine + else + return SpaceBreak + +EmptyLine=mkEmptyLine! AlphaNum = R "az", "AZ", "09", "__" @@ -30,5 +38,5 @@ Shebang = P"#!" * P(1 - Stop)^0 safe_module "moonscript.parse.literals", { :White, :Break, :Stop, :Comment, :Space, :SomeSpace, :SpaceBreak, :EmptyLine, - :AlphaNum, :Name, :Num, :Shebang + :AlphaNum, :Name, :Num, :Shebang, :LitmoonCommentLine, :mkEmptyLine } diff --git a/spec/helpers.moon b/spec/helpers.moon index 42d578b3..4b8005f6 100644 --- a/spec/helpers.moon +++ b/spec/helpers.moon @@ -26,8 +26,7 @@ with_dev = (fn) -> _G.require = (mod) -> return dev_cache[mod] if dev_cache[mod] - testable = mod\match("moonscript%.") or mod == "moonscript" or - mod\match("moon%.") or mod == "moon" + testable = mod\match("moonscript%.") or mod == "moonscript" or mod\match("moon%.") or mod == "moon" if testable dev_cache[mod] = assert(loadfile(assert loader mod))! diff --git a/spec/moonscript_spec.moon b/spec/moonscript_spec.moon index b7e5271b..72d5d467 100644 --- a/spec/moonscript_spec.moon +++ b/spec/moonscript_spec.moon @@ -8,5 +8,6 @@ describe "moonscript.base", -> it "should create moonpath", -> path = ";./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib/lua/5.1/?.luac;/home/leafo/.luarocks/lua/5.1/?.lua" import create_moonpath from require "moonscript.base" - assert.same "./?.moon;/usr/share/lua/5.1/?.moon;/usr/share/lua/5.1/?/init.moon;/home/leafo/.luarocks/lua/5.1/?.moon", create_moonpath(path) + assert.same "./?.moon;./?.litmoon;/usr/share/lua/5.1/?.moon;/usr/share/lua/5.1/?.litmoon;/usr/share/lua/5.1/?/init.moon;/usr/share/lua/5.1/?/init.litmoon;/home/leafo/.luarocks/lua/5.1/?.moon;/home/leafo/.luarocks/lua/5.1/?.litmoon", create_moonpath(path) + From 32bff9ae839280b1b062859e0318a79eed7a2d66 Mon Sep 17 00:00:00 2001 From: Kyra Zimmer Date: Mon, 28 Sep 2015 13:55:45 +0200 Subject: [PATCH 2/2] messed up priorities --- moonscript/parse.lua | 2 +- moonscript/parse.moon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/moonscript/parse.lua b/moonscript/parse.lua index f2acb41f..77da55a0 100644 --- a/moonscript/parse.lua +++ b/moonscript/parse.lua @@ -120,7 +120,7 @@ build_grammar_factory = function(litmoon) File = Shebang ^ -1 * (Block + Ct("")), Block = Ct(Line * (Break ^ 1 * Line) ^ 0), CheckIndent = Cmt(Indent, check_indent), - Line = EmptyLine + CheckIndent * Statement + Space * #Stop, + Line = (CheckIndent * Statement + Space * #Stop) + EmptyLine, Statement = pos(Import + While + With + For + ForEach + Switch + Return + Local + Export + BreakLoop + Ct(ExpList) * (Update + Assign) ^ -1 / format_assign) * Space * ((key("if") * Exp * (key("else") * Exp) ^ -1 * Space / mark("if") + key("unless") * Exp / mark("unless") + CompInner / mark("comprehension")) * Space) ^ -1 / wrap_decorator, Body = Space ^ -1 * Break * EmptyLine ^ 0 * InBlock + Ct(Statement), Advance = #Cmt(Indent, advance_indent), diff --git a/moonscript/parse.moon b/moonscript/parse.moon index 933d0611..9ae91d33 100644 --- a/moonscript/parse.moon +++ b/moonscript/parse.moon @@ -112,7 +112,7 @@ build_grammar_factory = (litmoon=false) -> File: Shebang^-1 * (Block + Ct"") Block: Ct(Line * (Break^1 * Line)^0) CheckIndent: Cmt(Indent, check_indent), -- validates line is in correct indent - Line: EmptyLine + CheckIndent * Statement + Space * #Stop + Line: (CheckIndent * Statement + Space * #Stop) + EmptyLine Statement: pos( Import + While + With + For + ForEach + Switch + Return +