expr-parse.lua - gsl-shell.git - gsl-shell

index : gsl-shell.git
gsl-shell
summary refs log tree commit diff
path: root/expr-parse.lua
blob: a8e72481eca07d35776002431592c9ef9f197e66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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 == 'literal' then
 local x = token.value
 lexer:next()
 return actions.literal(x)
 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 function schema_multivar(lexer, actions)
 local y = expr_list(lexer, actions, 0)
 expect(lexer, '~')
 local x = expr_list(lexer, actions)
 local enums = 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.schema_multivar(formula, actions)
 local l = expr_lexer.new(formula)
 return schema_multivar(l, actions)
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月11日 08:50:50 +0000

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