|
Warning: this is an htmlized version!
The original is here, and the conversion rules are here. |
-- This file:
-- http://angg.twu.net/LUA/Interpret.lua.html
-- http://angg.twu.net/LUA/Interpret.lua
-- (find-angg "LUA/Interpret.lua")
-- Author: Eduardo Ochs <eduardoochs@gmail.com>
--
-- (defun e () (interactive) (find-angg "LUA/Interpret.lua"))
-- (find-angg "SRF/srfx.lua" "tokenisation")
--
-- This is obsolete.
-- The new version is here:
-- (find-angg "SRF/srfa.lua")
-- «.re-grammar» (to "re-grammar")
-- «.Interpreter» (to "Interpreter")
-- «.Interpreter-tests» (to "Interpreter-tests")
--
-- _ __ ___ __ _ _ __ __ _ _ __ ___ _ __ ___ __ _ _ __
-- | '__/ _ \ / _` | '__/ _` | '_ ` _ \| '_ ` _ \ / _` | '__|
-- | | | __/ | (_| | | | (_| | | | | | | | | | | | (_| | |
-- |_| \___| \__, |_| \__,_|_| |_| |_|_| |_| |_|\__,_|_|
-- |___/
--
-- «re-grammar» (to ".re-grammar")
-- A parser for srfx tokens written as a grammar in lpeg.re
re = require "re"
srf_gram = [=[
s <- ' '
eol <- !.
eow <- &s / !.
c <- [^ ]
b <- {:b: {} :}
e <- {:e: {} :}
dqliteral0 <- '"' {:body: { [^"]* } :} '"'
sqliteral0 <- "'" {:body: { [^']* } :} "'"
decnumber0 <- {:body: { [-+]? [0-9]+ ('.' [0-9]+)? } :} {:base: "" -> "10" :}
hexnumber0 <- "0x" {:body: { [0-9A-Fa-f]+ } :} {:base: "" -> "16" :}
octnumber0 <- "o" {:body: { [0-7]+ } :} {:base: "" -> "8" :}
knownword0 <- {:body: { c+ } => known :}
word0 <- {:body: { c+ } :}
strlit1 <- {:kind: "" -> "strlit" :} (dqliteral0 / sqliteral0)
number1 <- {:kind: "" -> "numlit" :} (decnumber0 / hexnumber0 / octnumber0)
kword1 <- {:kind: "" -> "word" :} knownword0
word1 <- {:kind: "" -> "word" :} word0
rest1 <- {:kind: "" -> "word" :} word0
token <- {| s* b (strlit1 eow / number1 eow / kword1 eow) e |}
]=]
srf_defs = {
known = function (subj, pos, body) return true end,
}
srf_reP = Re { grammar = srf_gram, defs = srf_defs, print = PP }
srf_re0 = Re { grammar = srf_gram, defs = srf_defs }
srf_parsetoken = srf_re0:cc "top <- token"
srf_parseword = srf_re0:cc "top <- token"
srf_parserest = srf_re0:cc "top <- token"
-- ___ _ _
-- |_ _|_ __ | |_ ___ _ __ _ __ _ __ ___| |_ ___ _ __
-- | || '_ \| __/ _ \ '__| '_ \| '__/ _ \ __/ _ \ '__|
-- | || | | | || __/ | | |_) | | | __/ || __/ |
-- |___|_| |_|\__\___|_| | .__/|_| \___|\__\___|_|
-- |_|
--
-- «Interpreter» (to ".Interpreter")
Interpreter = Class {
type = "Interpreter",
new = function (line, pos)
return Interpreter {subj=line, pos=pos or 1}
end,
__index = {
--
-- Low-level parsers that expect patterns.
setlastparsedtoken = function (terp, o)
terp.lastparsedtoken = o
terp.pos = o.e
return o
end,
parsepat = function (terp, pat, kind)
local b,body,e = terp.subj:match(pat, terp.pos)
local o = {b=b, kind=kind, body=body, e=e}
if b then return terp:setlastparsedtoken(o) end
end,
parselpegpat = function (terp, lpegpat)
local o = lpegpat:match(terp.subj, terp.pos)
if o then return terp:setlastparsedtoken(o) end
end,
--
-- High-level parsers that use predefined patterns.
parseword = function (terp)
local pat = "%s*()(%S+)()"
return terp:parsepat(pat, "word")
end,
parsetoken = function (terp)
return terp:parselpegpat(srf_parsetoken.rec)
end,
--
-- Functions for testing and debugging.
carets = function (terp, usecopy, b, e)
b = b or terp.lastparsedtoken.b
e = e or terp.lastparsedtoken.e
local str = usecopy and terp.subj:sub(b, e-1) or ("^"):rep(e-b)
return (" "):rep(#terp.subj):replace(b-1, str)
end,
tokenshort = function (terp) -- short description of the last token
local o = terp.lastparsedtoken
local f = function (field, q)
if not o[field] then return "" end
return " "..field..":"..(q or "")..o[field]..(q or "")
end
return f("kind")..f("body", '"')..f("base")
end,
test = function (terp, verbose, method)
method = method or "parsetoken"
print(terp.subj)
local o = terp[method](terp)
while o do
print(terp:carets("usecopy")..terp:tokenshort())
if verbose then PP(o); print() end
o = terp[method](terp)
end
end,
},
}
-- «Interpreter-tests» (to ".Interpreter-tests")
--
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "Interpret.lua"
line = [=[ : 5* 5 * ; 'foo bar' + 0x23 ]=]
Interpreter.new(line):test()
Interpreter.new(line):test(nil, "parseword")
Interpreter.new(line):test("verbose")
line = [=[ : 5* 5 * ; 'foo bar' .. 0x23 ]=]
terp = Interpreter.new(line)
terp:parsetoken()
= terp.subj.."\n"..terp:carets()
= terp.subj.."\n"..terp:carets("useword")
--]==]