mirror of
https://github.com/leafo/moonscript.git
synced 2024-11-22 02:44:23 +00:00
convert rest of parse helpers to moonscript
This commit is contained in:
parent
72d496dd66
commit
a1d9e39caa
@ -41,165 +41,24 @@ Num = Space * (Num / function(value) return {"number", value} end)
|
||||
local Indent = parse_util.Indent
|
||||
local Cut = parse_util.Cut
|
||||
local ensure = parse_util.ensure
|
||||
|
||||
local function extract_line(str, start_pos)
|
||||
str = str:sub(start_pos)
|
||||
local m = str:match"^(.-)\n"
|
||||
if m then return m end
|
||||
return str:match"^.-$"
|
||||
end
|
||||
|
||||
local function mark(name)
|
||||
return function(...)
|
||||
return {name, ...}
|
||||
end
|
||||
end
|
||||
|
||||
local function insert_pos(pos, value)
|
||||
if type(value) == "table" then
|
||||
value[-1] = pos
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
local function pos(patt)
|
||||
return (lpeg.Cp() * patt) / insert_pos
|
||||
end
|
||||
|
||||
local function got(what)
|
||||
return Cmt("", function(str, pos, ...)
|
||||
local cap = {...}
|
||||
print("++ got "..what, "["..extract_line(str, pos).."]")
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
local function flatten_or_mark(name)
|
||||
return function(tbl)
|
||||
if #tbl == 1 then return tbl[1] end
|
||||
table.insert(tbl, 1, name)
|
||||
return tbl
|
||||
end
|
||||
end
|
||||
|
||||
-- makes sure the last item in a chain is an index
|
||||
local _chain_assignable = { index = true, dot = true, slice = true }
|
||||
|
||||
local function is_assignable(node)
|
||||
if node == "..." then
|
||||
return false
|
||||
end
|
||||
|
||||
local t = ntype(node)
|
||||
return t == "ref" or t == "self" or t == "value" or t == "self_class" or
|
||||
t == "chain" and _chain_assignable[ntype(node[#node])] or
|
||||
t == "table"
|
||||
end
|
||||
|
||||
local function check_assignable(str, pos, value)
|
||||
if is_assignable(value) then
|
||||
return true, value
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local flatten_explist = flatten_or_mark"explist"
|
||||
local function format_assign(lhs_exps, assign)
|
||||
if not assign then
|
||||
return flatten_explist(lhs_exps)
|
||||
end
|
||||
|
||||
for _, assign_exp in ipairs(lhs_exps) do
|
||||
if not is_assignable(assign_exp) then
|
||||
error {assign_exp, "left hand expression is not assignable"}
|
||||
end
|
||||
end
|
||||
|
||||
local t = ntype(assign)
|
||||
if t == "assign" then
|
||||
return {"assign", lhs_exps, unpack(assign, 2)}
|
||||
elseif t == "update" then
|
||||
return {"update", lhs_exps[1], unpack(assign, 2)}
|
||||
end
|
||||
|
||||
error "unknown assign expression"
|
||||
end
|
||||
|
||||
-- the if statement only takes a single lhs, so we wrap in table to git to
|
||||
-- "assign" tuple format
|
||||
local function format_single_assign(lhs, assign)
|
||||
if assign then
|
||||
return format_assign({lhs}, assign)
|
||||
end
|
||||
return lhs
|
||||
end
|
||||
|
||||
local function sym(chars)
|
||||
return Space * chars
|
||||
end
|
||||
|
||||
-- Like sym but doesn't accept whitespace in front
|
||||
local function symx(chars)
|
||||
return chars
|
||||
end
|
||||
|
||||
local function simple_string(delim, allow_interpolation)
|
||||
local inner = P('\\'..delim) + "\\\\" + (1 - P(delim))
|
||||
if allow_interpolation then
|
||||
local inter = symx"#{" * V"Exp" * sym"}"
|
||||
inner = (C((inner - inter)^1) + inter / mark"interpolate")^0
|
||||
else
|
||||
inner = C(inner^0)
|
||||
end
|
||||
|
||||
return C(symx(delim)) *
|
||||
inner * sym(delim) / mark"string"
|
||||
end
|
||||
|
||||
local function wrap_func_arg(value)
|
||||
return {"call", {value}}
|
||||
end
|
||||
|
||||
-- DOCME
|
||||
local function flatten_func(callee, args)
|
||||
if #args == 0 then return callee end
|
||||
|
||||
args = {"call", args}
|
||||
if ntype(callee) == "chain" then
|
||||
-- check for colon stub that needs arguments
|
||||
if ntype(callee[#callee]) == "colon_stub" then
|
||||
local stub = callee[#callee]
|
||||
stub[1] = "colon"
|
||||
table.insert(stub, args)
|
||||
else
|
||||
table.insert(callee, args)
|
||||
end
|
||||
|
||||
return callee
|
||||
end
|
||||
|
||||
return {"chain", callee, args}
|
||||
end
|
||||
|
||||
local function flatten_string_chain(str, chain, args)
|
||||
if not chain then return str end
|
||||
return flatten_func({"chain", str, unpack(chain)}, args)
|
||||
end
|
||||
|
||||
-- transforms a statement that has a line decorator
|
||||
local function wrap_decorator(stm, dec)
|
||||
if not dec then return stm end
|
||||
return { "decorated", stm, dec }
|
||||
end
|
||||
|
||||
local function check_lua_string(str, pos, right, left)
|
||||
return #left == #right
|
||||
end
|
||||
|
||||
-- :name in table literal
|
||||
local function self_assign(name, pos)
|
||||
return {{"key_literal", name}, {"ref", name, [-1] = pos}}
|
||||
end
|
||||
local extract_line = parse_util.extract_line
|
||||
local mark = parse_util.mark
|
||||
local pos = parse_util.pos
|
||||
local got = parse_util.got
|
||||
local flatten_or_mark = parse_util.flatten_or_mark
|
||||
local is_assignable = parse_util.is_assignable
|
||||
local check_assignable = parse_util.check_assignable
|
||||
local format_assign = parse_util.format_assign
|
||||
local format_single_assign = parse_util.format_single_assign
|
||||
local sym = parse_util.sym
|
||||
local symx = parse_util.symx
|
||||
local simple_string = parse_util.simple_string
|
||||
local wrap_func_arg = parse_util.wrap_func_arg
|
||||
local flatten_func = parse_util.flatten_func
|
||||
local flatten_string_chain = parse_util.flatten_string_chain
|
||||
local wrap_decorator = parse_util.wrap_decorator
|
||||
local check_lua_string = parse_util.check_lua_string
|
||||
local self_assign = parse_util.self_assign
|
||||
|
||||
local err_msg = "Failed to parse:%s\n [%d] >> %s"
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
local P, C, S
|
||||
local unpack
|
||||
unpack = require("moonscript.util").unpack
|
||||
local P, C, S, Cp, Cmt, V
|
||||
do
|
||||
local _obj_0 = require("lpeg")
|
||||
P, C, S = _obj_0.P, _obj_0.C, _obj_0.S
|
||||
P, C, S, Cp, Cmt, V = _obj_0.P, _obj_0.C, _obj_0.S, _obj_0.Cp, _obj_0.Cmt, _obj_0.V
|
||||
end
|
||||
local ntype
|
||||
ntype = require("moonscript.types").ntype
|
||||
local Space
|
||||
Space = require("moonscript.parse.literals").Space
|
||||
local Indent = C(S("\t ") ^ 0) / function(str)
|
||||
do
|
||||
local sum = 0
|
||||
@ -24,8 +30,238 @@ local ensure
|
||||
ensure = function(patt, finally)
|
||||
return patt * finally + finally * Cut
|
||||
end
|
||||
local extract_line
|
||||
extract_line = function(str, start_pos)
|
||||
str = str:sub(start_pos)
|
||||
do
|
||||
local m = str:match("^(.-)\n")
|
||||
if m then
|
||||
return m
|
||||
end
|
||||
end
|
||||
return str:match("^.-$")
|
||||
end
|
||||
local mark
|
||||
mark = function(name)
|
||||
return function(...)
|
||||
return {
|
||||
name,
|
||||
...
|
||||
}
|
||||
end
|
||||
end
|
||||
local pos
|
||||
pos = function(patt)
|
||||
return (Cp() * patt) / function(pos, value)
|
||||
if type(value) == "table" then
|
||||
value[-1] = pos
|
||||
end
|
||||
return value
|
||||
end
|
||||
end
|
||||
local got
|
||||
got = function(what)
|
||||
return Cmt("", function(str, pos)
|
||||
print("++ got " .. tostring(what), "[" .. tostring(extract_line(str, pos)) .. "]")
|
||||
return true
|
||||
end)
|
||||
end
|
||||
local flatten_or_mark
|
||||
flatten_or_mark = function(name)
|
||||
return function(tbl)
|
||||
if #tbl == 1 then
|
||||
return tbl[1]
|
||||
end
|
||||
table.insert(tbl, 1, name)
|
||||
return tbl
|
||||
end
|
||||
end
|
||||
local is_assignable
|
||||
do
|
||||
local chain_assignable = {
|
||||
index = true,
|
||||
dot = true,
|
||||
slice = true
|
||||
}
|
||||
is_assignable = function(node)
|
||||
if node == "..." then
|
||||
return false
|
||||
end
|
||||
local _exp_0 = ntype(node)
|
||||
if "ref" == _exp_0 or "self" == _exp_0 or "value" == _exp_0 or "self_class" == _exp_0 or "table" == _exp_0 then
|
||||
return true
|
||||
elseif "chain" == _exp_0 then
|
||||
return chain_assignable[ntype(node[#node])]
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
local check_assignable
|
||||
check_assignable = function(str, pos, value)
|
||||
if is_assignable(value) then
|
||||
return true, value
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local format_assign
|
||||
do
|
||||
local flatten_explist = flatten_or_mark("explist")
|
||||
format_assign = function(lhs_exps, assign)
|
||||
if not (assign) then
|
||||
return flatten_explist(lhs_exps)
|
||||
end
|
||||
for _index_0 = 1, #lhs_exps do
|
||||
local assign_exp = lhs_exps[_index_0]
|
||||
if not (is_assignable(assign_exp)) then
|
||||
error({
|
||||
assign_exp,
|
||||
"left hand expression is not assignable"
|
||||
})
|
||||
end
|
||||
end
|
||||
local t = ntype(assign)
|
||||
local _exp_0 = t
|
||||
if "assign" == _exp_0 then
|
||||
return {
|
||||
"assign",
|
||||
lhs_exps,
|
||||
unpack(assign, 2)
|
||||
}
|
||||
elseif "update" == _exp_0 then
|
||||
return {
|
||||
"update",
|
||||
lhs_exps[1],
|
||||
unpack(assign, 2)
|
||||
}
|
||||
else
|
||||
return error("unknown assign expression: " .. tostring(t))
|
||||
end
|
||||
end
|
||||
end
|
||||
local format_single_assign
|
||||
format_single_assign = function(lhs, assign)
|
||||
if assign then
|
||||
return format_assign({
|
||||
lhs
|
||||
}, assign)
|
||||
else
|
||||
return lhs
|
||||
end
|
||||
end
|
||||
local sym
|
||||
sym = function(chars)
|
||||
return Space * chars
|
||||
end
|
||||
local symx
|
||||
symx = function(chars)
|
||||
return chars
|
||||
end
|
||||
local simple_string
|
||||
simple_string = function(delim, allow_interpolation)
|
||||
local inner = P("\\" .. tostring(delim)) + "\\\\" + (1 - P(delim))
|
||||
if allow_interpolation then
|
||||
local interp = symx('#{') * V("Exp") * sym('}')
|
||||
inner = (C((inner - interp) ^ 1) + interp / mark("interpolate")) ^ 0
|
||||
else
|
||||
inner = C(inner ^ 0)
|
||||
end
|
||||
return C(symx(delim)) * inner * sym(delim) / mark("string")
|
||||
end
|
||||
local wrap_func_arg
|
||||
wrap_func_arg = function(value)
|
||||
return {
|
||||
"call",
|
||||
{
|
||||
value
|
||||
}
|
||||
}
|
||||
end
|
||||
local flatten_func
|
||||
flatten_func = function(callee, args)
|
||||
if #args == 0 then
|
||||
return callee
|
||||
end
|
||||
args = {
|
||||
"call",
|
||||
args
|
||||
}
|
||||
if ntype(callee) == "chain" then
|
||||
local stub = callee[#callee]
|
||||
if ntype(stub) == "colon_stub" then
|
||||
stub[1] = "colon"
|
||||
table.insert(stub, args)
|
||||
else
|
||||
table.insert(callee, args)
|
||||
end
|
||||
return callee
|
||||
end
|
||||
return {
|
||||
"chain",
|
||||
callee,
|
||||
args
|
||||
}
|
||||
end
|
||||
local flatten_string_chain
|
||||
flatten_string_chain = function(str, chain, args)
|
||||
if not (chain) then
|
||||
return str
|
||||
end
|
||||
return flatten_func({
|
||||
"chain",
|
||||
str,
|
||||
unpack(chain)
|
||||
}, args)
|
||||
end
|
||||
local wrap_decorator
|
||||
wrap_decorator = function(stm, dec)
|
||||
if not (dec) then
|
||||
return stm
|
||||
end
|
||||
return {
|
||||
"decorated",
|
||||
stm,
|
||||
dec
|
||||
}
|
||||
end
|
||||
local check_lua_string
|
||||
check_lua_string = function(str, pos, right, left)
|
||||
return #left == #right
|
||||
end
|
||||
local self_assign
|
||||
self_assign = function(name, pos)
|
||||
return {
|
||||
{
|
||||
"key_literal",
|
||||
name
|
||||
},
|
||||
{
|
||||
"ref",
|
||||
name,
|
||||
[-1] = pos
|
||||
}
|
||||
}
|
||||
end
|
||||
return {
|
||||
Indent = Indent,
|
||||
Cut = Cut,
|
||||
ensure = ensure
|
||||
ensure = ensure,
|
||||
extract_line = extract_line,
|
||||
mark = mark,
|
||||
pos = pos,
|
||||
flatten_or_mark = flatten_or_mark,
|
||||
is_assignable = is_assignable,
|
||||
check_assignable = check_assignable,
|
||||
format_assign = format_assign,
|
||||
format_single_assign = format_single_assign,
|
||||
sym = sym,
|
||||
symx = symx,
|
||||
simple_string = simple_string,
|
||||
wrap_func_arg = wrap_func_arg,
|
||||
flatten_func = flatten_func,
|
||||
flatten_string_chain = flatten_string_chain,
|
||||
wrap_decorator = wrap_decorator,
|
||||
check_lua_string = check_lua_string,
|
||||
self_assign = self_assign
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
|
||||
import P, C, S from require "lpeg"
|
||||
import unpack from require "moonscript.util"
|
||||
import P, C, S, Cp, Cmt, V from require "lpeg"
|
||||
import ntype from require "moonscript.types"
|
||||
import Space from require "moonscript.parse.literals"
|
||||
|
||||
-- captures an indentation, returns indent depth
|
||||
Indent = C(S"\t "^0) / (str) ->
|
||||
@ -18,6 +21,147 @@ Cut = P -> false
|
||||
|
||||
-- ensures finally runs regardless of whether pattern fails or passes
|
||||
ensure = (patt, finally) ->
|
||||
patt * finally + finally * Cut
|
||||
patt * finally + finally * Cut
|
||||
|
||||
{ :Indent, :Cut, :ensure }
|
||||
-- take rest of line from pos out of str
|
||||
extract_line = (str, start_pos) ->
|
||||
str = str\sub start_pos
|
||||
if m = str\match "^(.-)\n"
|
||||
return m
|
||||
|
||||
str\match "^.-$"
|
||||
|
||||
-- used to identify a capture with a label
|
||||
mark = (name) ->
|
||||
(...) -> {name, ...}
|
||||
|
||||
-- wraps pattern to capture pos into node
|
||||
-- pos is the character offset from the buffer where the node was parsed from.
|
||||
-- Used to generate error messages
|
||||
pos = (patt) ->
|
||||
(Cp! * patt) / (pos, value) ->
|
||||
if type(value) == "table"
|
||||
value[-1] = pos
|
||||
value
|
||||
|
||||
-- generates a debug pattern that always succeeds and prints out where we are
|
||||
-- in the buffer with a label
|
||||
got = (what) ->
|
||||
Cmt "", (str, pos) ->
|
||||
print "++ got #{what}", "[#{extract_line str, pos}]"
|
||||
true
|
||||
|
||||
-- converts 1 element array to its value, otherwise marks it
|
||||
flatten_or_mark = (name) ->
|
||||
(tbl) ->
|
||||
return tbl[1] if #tbl == 1
|
||||
table.insert tbl, 1, name
|
||||
tbl
|
||||
|
||||
-- determines if node is able to be on left side of assignment
|
||||
is_assignable = do
|
||||
chain_assignable = { index: true, dot: true, slice: true }
|
||||
|
||||
(node) ->
|
||||
return false if node == "..."
|
||||
switch ntype node
|
||||
when "ref", "self", "value", "self_class", "table"
|
||||
true
|
||||
when "chain"
|
||||
chain_assignable[ntype node[#node]]
|
||||
else
|
||||
false
|
||||
|
||||
check_assignable = (str, pos, value) ->
|
||||
if is_assignable value
|
||||
true, value
|
||||
else
|
||||
false
|
||||
|
||||
-- joins the two parts of an assign parse into a single node
|
||||
format_assign = do
|
||||
flatten_explist = flatten_or_mark "explist"
|
||||
|
||||
(lhs_exps, assign) ->
|
||||
unless assign
|
||||
return flatten_explist lhs_exps
|
||||
|
||||
for assign_exp in *lhs_exps
|
||||
unless is_assignable assign_exp
|
||||
error {assign_exp, "left hand expression is not assignable"}
|
||||
|
||||
t = ntype assign
|
||||
switch t
|
||||
when "assign"
|
||||
{"assign", lhs_exps, unpack assign, 2}
|
||||
when "update"
|
||||
{"update", lhs_exps[1], unpack assign, 2}
|
||||
else
|
||||
error "unknown assign expression: #{t}"
|
||||
|
||||
-- helper for if statement, which only has single lhs
|
||||
format_single_assign = (lhs, assign) ->
|
||||
if assign
|
||||
format_assign {lhs}, assign
|
||||
else
|
||||
lhs
|
||||
|
||||
|
||||
-- a symbol
|
||||
sym = (chars) -> Space * chars
|
||||
-- a symbole that doesn't accept whitespace before it
|
||||
symx = (chars) -> chars
|
||||
|
||||
-- a constructor for quote delimited strings
|
||||
simple_string = (delim, allow_interpolation) ->
|
||||
inner = P("\\#{delim}") + "\\\\" + (1 - P delim)
|
||||
|
||||
inner = if allow_interpolation
|
||||
interp = symx'#{' * V"Exp" * sym'}'
|
||||
(C((inner - interp)^1) + interp / mark"interpolate")^0
|
||||
else
|
||||
C inner^0
|
||||
|
||||
C(symx(delim)) * inner * sym(delim) / mark"string"
|
||||
|
||||
-- wraps a single value in format needed to be passed as function arguments
|
||||
wrap_func_arg = (value) -> {"call", {value}}
|
||||
|
||||
-- flatten out the parsed function node
|
||||
flatten_func = (callee, args) ->
|
||||
return callee if #args == 0
|
||||
args = {"call", args}
|
||||
|
||||
if ntype(callee) == "chain"
|
||||
-- check for colon stub needing arguments
|
||||
stub = callee[#callee]
|
||||
if ntype(stub) == "colon_stub"
|
||||
stub[1] = "colon"
|
||||
table.insert stub, args
|
||||
else
|
||||
table.insert callee, args
|
||||
|
||||
return callee
|
||||
|
||||
{"chain", callee, args}
|
||||
|
||||
flatten_string_chain = (str, chain, args) ->
|
||||
return str unless chain
|
||||
flatten_func {"chain", str, unpack chain}, args
|
||||
|
||||
-- constructor for decorator node
|
||||
wrap_decorator = (stm, dec) ->
|
||||
return stm unless dec
|
||||
{"decorated", stm, dec}
|
||||
|
||||
check_lua_string = (str, pos, right, left) ->
|
||||
#left == #right
|
||||
|
||||
-- constructor for :name self assignments in table literals
|
||||
self_assign = (name, pos) ->
|
||||
{{"key_literal", name}, {"ref", name, [-1]: pos}}
|
||||
|
||||
{ :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 }
|
||||
|
Loading…
Reference in New Issue
Block a user