lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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.