diff options
Diffstat (limited to 'piecemeal.lua')
| -rw-r--r-- | piecemeal.lua | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/piecemeal.lua b/piecemeal.lua new file mode 100644 index 0000000..0f6dd6c --- /dev/null +++ b/piecemeal.lua @@ -0,0 +1,106 @@ +--[[ + A parser has the signature: (list, sindex) -> eindex [, output] + If the parser "fails", it must return exactly nil. + If the parser "succeeds", it must return at least the eindex, and may also return some output. +]]-- + +return { + lexeme = function (type) + return function (l, i) + if l[i] and l[i].type == type then + return i+1, l[i] + end + return nil + end + end, + value = function (value) + return function (l, i) + if l[i] and l[i].value == value then + return i+1, l[i] + end + return nil + end + end, + all = function (...) + local args = {...} + return function (l, i) + local res = {} + local eind, out + for _, v in ipairs(args) do + eind, out = v(l, i) + if not eind then return nil end + i = eind + table.insert(res, out) + end + return i, res + end + end, + alt = function (...) + local args = {...} + return function (l, i) + local eind, out + for _, v in ipairs(args) do + eind, out = v(l, i) + if eind then + return eind, out + end + end + return nil + end + end, + opt = function (p) + return function (l, i) + local eind, out = p(l, i) + if eind + then return eind, out + else return i + end + end + end, + plus = function (p) + return function (l, i) + local res = {} + local eind, out = p(l, i) + if not eind then return nil end + repeat + i = eind + table.insert(res, out) + eind, out = p(l, i) + until not eind + return i, res + end + end, + star = function (p) + return function (l, i) + local res = {} + local eind, out + repeat + eind, out = p(l, i) + if eind then + table.insert(res, out) + i = eind + end + until not eind + return i, res + end + end, + + postp = function (p, f) + return function (l, i) + local eind, out = p(l, i) + if out then out = f(out) end + return eind, out + end + end, + + parse = function (text, lexer, parser) + local tokens = {} + lexer:reset(text) + local next + repeat + next = lexer:next() + if next then table.insert(tokens, next) end + until next == nil + return parser(tokens, 1) + end, +} |
