Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
-- Taken from:
-- (find-dn5 "gab.lua" "old-parser")


--                            
--  _ __   __ _ _ __ ___  ___ 
-- | '_ \ / _` | '__/ __|/ _ \
-- | |_) | (_| | |  \__ \  __/
-- | .__/ \__,_|_|  |___/\___|
-- |_|                        

-- «precedence-table»  (to ".precedence-table")
-- «precedence»  (to ".precedence")
-- (find-dn5 "gab-tests.lua" "parse-2")
-- (find-dn5 "gab-tests.lua" "parse-3")
ops = {}
binop = function (op, top, l, r)
    ops[op] = {kind="binop", top=top, l=l, r=r}
  end
prefix = function (op, top, r)
    ops[op] = {kind="prefix", top=top, r=r}
  end
binop("*",  8, 7, 8)
binop("/",  8, 7, 8)
binop("+",  7, 6, 7)
binop("-",  7, 6, 7)
binop("==", 6, 6, 6)
binop("<=", 6, 6, 6)
binop(">=", 6, 6, 6)
binop("<",  6, 6, 6)
binop(">",  6, 6, 6)
binop("!=", 6, 6, 6)
binop("&",  4, 3, 4)
binop("|",  3, 2, 3)
binop("->", 2, 2, 2)
prefix("u-", 9, 100)
prefix("nt", 5, 4)

binop("in", 6, 6, 6)
binop("<-", 6, 6, 6)

-- «recursive-descent»  (to ".recursive-descent")
subj = split "2 + 3 * 4 + 5 * 6 * 7 (eof)"
pos  = 1
parse = function (str, b)
    subj = split(str)       -- token are separated by spaces
    pos = 1
    return pa_expr(b)
  end
pparse = function (str, b)  -- print the result of a parse
    local e = parse(str, b)
    print(e:tolisp())
    print(e:torect())
    return e
  end
pparsee = function (str, b) pparse(str):peval() end

-- Abbreviations:
--   "la"  = "looking at"
--   "pa"  = "parse"
--   "wos" = "without suffixes"

-- «parser-grammar»  (to ".parser-grammar")
-- We use a very simple recursive parser with one token of lookahead.
-- It operates on the array "subj", that at the moment is just an
-- array of strings obtained by running "split" on a given string -
-- to avoid lexing. Our grammar is:
--
--   parenexpr   ::= ( expr )
--   setexpr     ::= { }
--                 | { expr commaexpr^* }
--                 | { expr | expr commaexpr^* }
--   qlexpr      ::= Fa expr . expr
--                 | Ex expr . expr
--                 | \\ expr . expr
--   exprwos     ::= parenexpr
--                 | setexpr
--                 | qlexpr
--                 | prefixop expr
--                 | number
--                 | var
--   complement1 ::= suffixop
--                 | parenexpr
--                 | binop expr
--   expr        ::= exprwos complement1^*
--
-- Note that each alternative starts with a different token - we use
-- the "la_*" functions to choose which alternative to follow.

perror = function (str) error("(la = `"..la().."') "..str, 2) end

la  = function () return subj[pos] end
eat = function () pos = pos+1; return subj[pos-1] end
pa_forced = function (token)
    if la() ~= token then perror("Expected `"..token.."'") end
    return eat()
  end

under       = function (b, op) return (not b) or b <= ops[op].top end
la_op       = function (k) return ops[la()] and ops[la()].kind == k end
la_op_under = function (k, b) return la_op(k) and under(b, la()) end

la_binop  = function (b) return la_op_under("binop",  b) end
la_prefix = function (b) return la_op_under("prefix", b) end
la_suffix = function (b) return la_op_under("suffix", b) end

-- 

la_number = function () return (la():match"^[0-9]+$") end
pa_number = function () return Num(eat()+0) end

la_var = function () return (la():match"^[A-Za-z]+$") end
pa_var = function () return Var(eat()) end

la_paren      = function () return la() == "(" end
pa_parenclose = function () return pa_forced(")") end
pa_parenexpr  = function ()
    local o, e, c = eat(), pa_expr(), pa_parenclose()
    return e
  end
pa_parenexpr  = function ()
    local o, e, es, c = eat(), pa_expr(), pa_commaexprs(), pa_parenclose()
    if #es == 0 then return e else return Tuple(e, unpack(es)) end
  end

la_expr = function ()
    return la_number() or la_var() or la_paren() or la_set() or la_prefix()
  end
pa_exprwos = function ()
    -- PP("pa_exprwos with pos = "..pos)
    if     la_paren()  then return pa_parenexpr()
    elseif la_set()    then return pa_set()
    elseif la_ql()     then return pa_qlexpr()
    elseif la_prefix() then
      local op = eat()
      local e  = pa_expr(ops[op].r)
      return Expr {[0]=op, e}
    elseif la_number() then return pa_number()
    elseif la_var()    then return pa_var()
    end
    perror("Not an expr (in exprwos)")
  end

la_complement = function (b)
    return la_suffix(b) or la_paren() or la_binop(b)
  end
pa_expr = function (b)
    -- PP("pa_expr with pos = "..pos)
    local e = pa_exprwos()
    while la_complement(b) do
      if     la_suffix(b) then e = Expr {[0]=eat(), e}
      elseif la_paren()   then e = App(e, pa_parenexpr())
      elseif la_binop(b)  then
        local op = eat()
        local re = pa_expr(ops[op].r)
        e = Expr {[0]=op, e, re}
      else perror("Not an expr")
      end
    end
    return e
  end

-- (find-angg "LUA/lua50init.lua" "pack-and-unpack")
la_set      = function () return la() == "{" end
pa_setclose = function () return pa_forced("}") end
pa_commaexprs = function ()
    local es = {}
    while la() == "," do eat(); table.insert(es, pa_expr()) end
    return es
  end
pa_set = function ()
    eat()
    if     la() == "}" then eat(); return Set()
    elseif la_expr() then
      local e = pa_expr(4)
      if la() == "|" then
        local _, er, ers, _ = eat(), pa_expr(), pa_commaexprs(), pa_setclose()
        if e[0] == "<-" then
          local s = Subset(e, er, unpack(ers))
          table.insert(s, e[1])
          return s
        else 
          local s = Setof(er, unpack(ers))
          table.insert(s, e)
          return s
        end
      else local es, _ = pa_commaexprs(), pa_setclose()
        return Set(e, unpack(es))
      end
    end
    perror("Not a set")
  end

la_ql     = function () return la() == "Fa" or la() == "Ex" or la() == "\\" end
pa_dot    = function () return pa_forced(".") end
pa_qlexpr = function ()
    local ql, vare, dot, bodye = eat(), pa_expr(), pa_dot(), pa_expr()
    if ql == "\\" then return Lambda(vare, bodye) end
    if vare[0] == "<-" or vare[0] == "in" then
      return Expr {[0]=ql, vare[1], vare[2], bodye}
    else
      perror("varexpr must be `_ <- _' or `_ in _'")
    end 
  end





-- Local Variables:
-- coding:             raw-text-unix
-- ee-anchor-format:   "«%s»"
-- End: