|
It was thus said that the Great joy mondal once stated:
> Hi !
>
> This is the first time posting to a mailing list so I hope I do not get it
> wrong.
>
> I have trying to understand LPEG to help me build a full programming
> language, I really like moonscript and want to build something similar, I
> have a very basic question involving LPEG.
>
> https://gist.github.com/randrews/5eab368f35ab8e774433#gistcomment-2692302
>
> (Posting it in email would make it harder to read due to not having
> markdown support.)
>
> Are there other good resources like playwithlua.com for the specific
> purpose of building programming languages or would Andrew's series (Part
> 1,2,3,4) be enough.
You can read these two mailing list threads that go into LPeg:
http://lua-users.org/lists/lua-l/2017-10/msg00106.html
http://lua-users.org/lists/lua-l/2018-01/msg00298.html
There's also several Lua modules I wrote that use LPeg:
http://lua-users.org/lists/lua-l/2017-10/msg00126.html
As for the particular issue you are having, it appears you want to parse
text like:
3 * -foo + 2
Yes, LPeg can do this. Sorry to do this, but I'm about to dump some LPeg.
This is from an assembler I wrote [1] that does deal with identifiers in
expressions.
local function knownvalue(n)
return { value = n % 65536 , unknownpass1 = false , defined = true }
end
local WS = S" \t"^1
local BIN = R"01"
local OCT = R"07"
local DEC = R"09"
local HEX = R("09","AF","af")
local OPAREN = P"(" * WS^-1
local CPAREN = P")" * WS^-1
local COMMA = WS^-1 * P"," * WS^-1
local value_bin = BIN^1 / function(c) return tonumber(c, 2) end
local value_oct = OCT^1 / function(c) return tonumber(c, 8) end
local value_dec = (S"+-"^-1 * DEC^1) / function(c) return tonumber(c,10) end
local value_hex = HEX^1 / function(c) return tonumber(c,16) end
local value_id = (id * Carg(1))
/ function(name,info)
if not info.symbols[name] then
info.symbols[name] = {}
info.symbols[name].type = 'undef'
info.symbols[name].value = 0
info.symbols[name].linenum = 0
info.symbols[name].unknownpass1 = true
end
return {
value = info.symbols[name].value,
unknownpass1 = info.symbols[name].unknownpass1,
defined = info.symbols[name].type ~= 'undef',
}
end
local value = P"$" * value_hex / knownvalue
+ P"&" * value_oct / knownvalue
+ P"%" * value_bin / knownvalue
+ value_dec / knownvalue
+ P"*" * Carg(1) / function(info) return knownvalue(info.PC) end
+ value_id
+ P"-" * value_id / function(v) v.value = -v.value return v end
+ P"~" * value_id / function(v) v.value = -v.value - 1 return v end
+ P"'" * C(1) / function(c) return
knownvalue(string.byte(c)) end
local term_op = C(S"+-") * WS^-1
local factor_op = C(S "*/") * WS^-1
local function eval(v1,op,v2)
if op == '+' then v1.value = v1.value + v2.value
elseif op == '-' then v1.value = v1.value - v2.value
elseif op == '*' then v1.value = v1.value * v2.value
elseif op == '/' then v1.value = v1.value / v2.value end
v1.unknownpass1 = v1.unknownpass1 or v2.unknownpass1
v1.defined = v1.defined and v2.defined
v1.value = v1.value % 65536
return v1
end
local expr = P {
"exp",
exp = Cf(V"term" * Cg(term_op * V"term" )^0,eval),
term = Cf(V"factor" * Cg(factor_op * V"factor")^0,eval),
factor = value * WS^-1
+ OPAREN * V"exp" * CPAREN
}
Start at the bottom with "expr" and work your way back up. The code is
expecting to be called like
symbol_table = { ... }
result = parser:match(input,1,symbol_table)
The key part is the 'value' production, but I'm including the full bit for
context (and remember this is part of an assembler so keep that in mind).
-spc (It's a two-pass assembler by the way ... )
[1] A Motorola 6809 Assembler in case anyone cares.