WIP: factorization of lexer and parser implementation - gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
path: root/expr-parse.lua
diff options
context:
space:
mode:
authorFrancesco Abbate <francesco.bbt@gmail.com>2013年05月10日 18:07:56 +0200
committerFrancesco Abbate <francesco.bbt@gmail.com>2013年05月10日 18:07:56 +0200
commit204fa404431f9c619f0dfc5ae3efc463749fa8ed (patch)
tree825fc39707d7c7b3e734c5ffb3fd04af8f325530 /expr-parse.lua
parent58dd27ba0c1776644db561cc4d565a281e2f7b2b (diff)
downloadgsl-shell-204fa404431f9c619f0dfc5ae3efc463749fa8ed.tar.gz
WIP: factorization of lexer and parser implementation
Diffstat (limited to 'expr-parse.lua')
-rw-r--r--expr-parse.lua 150
1 files changed, 150 insertions, 0 deletions
diff --git a/expr-parse.lua b/expr-parse.lua
new file mode 100644
index 00000000..20129478
--- /dev/null
+++ b/expr-parse.lua
@@ -0,0 +1,150 @@
+local expr_lexer = require 'expr-lexer'
+
+local function accept(lexer, token_type)
+ if lexer.token.type == token_type then
+ lexer:next()
+ return true
+ end
+ return false
+end
+
+local function expect(lexer, token_type)
+ if not accept(lexer, token_type) then
+ lexer:local_error("expecting " .. token_type)
+ end
+end
+
+local expr
+
+local function factor(lexer, actions)
+ local token = lexer.token
+ if token.type == 'ident' then
+ local id = token.value
+ lexer:next()
+ if accept(lexer, '(') then
+ local arg = expr(lexer, actions, 0)
+ expect(lexer, ')')
+ return actions.func_eval(id, arg)
+ else
+ return actions.ident(id)
+ end
+ elseif token.type == 'number' then
+ local x = token.value
+ lexer:next()
+ return actions.number(x)
+ elseif token.type == '(' then
+ lexer:next()
+ local a = expr(lexer, actions, 0)
+ expect(lexer, ')')
+ return a
+ elseif token.type == 'operator' and token.symbol == '%' then
+ lexer:next()
+ if lexer.token.type ~= 'ident' then
+ lexer:local_error("expecting identifier:")
+ end
+ local id = lexer.token.value
+ lexer:next()
+ return actions.enum(id)
+ end
+ lexer:local_error('unexpected symbol:')
+end
+
+local function ident_singleton(lexer, actions)
+ local token = lexer.token
+ if token.type == 'ident' then
+ local id = token.value
+ lexer:next()
+ if accept(lexer, '(') then
+ lexer:local_error('expecting simple identifier')
+ end
+ return actions.ident(id)
+ else
+ lexer:local_error('expecting simple identifier')
+ end
+end
+
+local max_oper_prio = expr_lexer.max_oper_prio
+
+expr = function(lexer, actions, prio)
+ if prio > max_oper_prio then
+ return factor(lexer, actions)
+ end
+
+ local a
+ local token = lexer.token
+ if prio == 0 and token.type == 'operator' and token.symbol == '-' then
+ local symbol = token.symbol
+ lexer:next()
+ local b = expr(lexer, actions, prio + 1)
+ a = actions.prefix(symbol, b)
+ else
+ a = expr(lexer, actions, prio + 1)
+ end
+
+ token = lexer.token
+ while token.type == 'operator' and token.priority >= prio do
+ local symbol = token.symbol
+ accept(lexer, 'operator')
+ local b = expr(lexer, actions, prio + 1)
+ a, token = actions.infix(symbol, a, b), lexer.token
+ end
+ return a
+end
+
+local function expr_list(lexer, actions)
+ local a = expr(lexer, actions, 0)
+ local els = actions.exprlist(a)
+ while accept(lexer, ',') do
+ local b = expr(lexer, actions, 0)
+ els = actions.exprlist(b, els)
+ end
+ return els
+end
+
+local function ident_list(lexer, actions)
+ local a = ident_singleton(lexer, actions)
+ local els = actions.exprlist(a)
+ while accept(lexer, ',') do
+ local b = ident_singleton(lexer, actions)
+ els = actions.exprlist(b, els)
+ end
+ return els
+end
+
+local function enums(lexer, actions)
+ if accept(lexer, '|') then
+ return ident_list(lexer, actions)
+ end
+ return {}
+end
+
+local function conditions(lexer, actions)
+ if accept(lexer, ':') then
+ return expr_list(lexer, actions)
+ end
+ return {}
+end
+
+local function schema(lexer, actions, accept_enums)
+ local y = expr(lexer, actions, 0)
+ expect(lexer, '~')
+ local x = expr_list(lexer, actions)
+ local enums = accept_enums and enums(lexer, actions)
+ local conds = conditions(lexer, actions)
+ expect(lexer, 'EOF')
+ return actions.schema(x, y, conds, enums)
+end
+
+local expr_parse = {}
+
+function expr_parse.schema(formula, actions, accept_enums)
+ local l = expr_lexer.new(formula)
+ return schema(l, actions, accept_enums)
+end
+
+function expr_parse.expr(formula, actions)
+ local l = expr_lexer.new(formula)
+ return expr(l, actions, 0)
+end
+
+return expr_parse
generated by cgit v1.2.3 (git 2.39.1) at 2025年09月13日 23:18:01 +0000

AltStyle によって変換されたページ (->オリジナル) /