rparsec-ruby19 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,268 @@
1
+ require 'import'
2
+ import :misc
3
+
4
+ include RParsec
5
+ class Module
6
+ include DefHelper
7
+ end
8
+ class Expr
9
+ def self.binary(*ops)
10
+ ops.each do |op|
11
+ define_method(op) do |other|
12
+ BinaryExpr.new(self, op, other)
13
+ end
14
+ end
15
+ end
16
+ binary :+,:-,:*,:/,:%
17
+ def -@
18
+ PrefixExpr.new(:-, self)
19
+ end
20
+ def self.compare(*ops)
21
+ ops.each do |op|
22
+ define_method(op) do |other|
23
+ ComparePredicate.new(self, op, other)
24
+ end
25
+ end
26
+ end
27
+ compare :'==', :'>', :'<', :'>=', :'<='
28
+ end
29
+ class LiteralExpr < Expr
30
+ def_readable :lit
31
+ def to_s
32
+ @lit.to_s
33
+ end
34
+ end
35
+ class VarExpr < Expr
36
+ def_readable :name
37
+ def to_s
38
+ "$#{name}"
39
+ end
40
+ end
41
+ class WordExpr < Expr
42
+ def_readable :name
43
+ def to_s
44
+ name
45
+ end
46
+ end
47
+ class QualifiedColumnExpr < Expr
48
+ def_readable :owner, :col
49
+ def to_s
50
+ "#{owner}.#{col}"
51
+ end
52
+ end
53
+ class WildcardExpr < Expr
54
+ Instance = WildcardExpr.new
55
+ def to_s
56
+ '*'
57
+ end
58
+ end
59
+ class BinaryExpr < Expr
60
+ def_readable :left, :op, :right
61
+ def to_s
62
+ "(#{left} #{op} #{right})"
63
+ end
64
+ end
65
+ class PostfixExpr < Expr
66
+ def_readable :expr, :op
67
+ def to_s
68
+ "(#{expr} #{op})"
69
+ end
70
+ end
71
+ class PrefixExpr < Expr
72
+ def_readable :op, :expr
73
+ def to_s
74
+ "(#{op} #{expr})"
75
+ end
76
+ end
77
+ def cases_string cases, default, result
78
+ cases.each do |cond, val|
79
+ result << " when #{cond}: #{val}"
80
+ end
81
+ unless default.nil?
82
+ result << " else #{default}"
83
+ end
84
+ result << " end"
85
+ result
86
+ end
87
+ class SimpleCaseExpr < Expr
88
+ def_readable :expr, :cases, :default
89
+ def to_s
90
+ cases_string cases, default, "case #{expr}"
91
+ end
92
+ end
93
+ class CaseExpr < Expr
94
+ def_readable :cases, :default
95
+ def to_s
96
+ cases_string cases, default, 'case'
97
+ end
98
+ end
99
+
100
+
101
+ ############Predicate########################
102
+ class Predicate
103
+ end
104
+
105
+ class ComparePredicate < Predicate
106
+ def_readable :left, :op, :right
107
+ def to_s
108
+ "#{left} #{op_name} #{right}"
109
+ end
110
+ def op_name
111
+ case op when :"!=": "<>" else op.to_s end
112
+ end
113
+ end
114
+ class CompoundPredicate < Predicate
115
+ def_readable :left, :op, :right
116
+ def to_s
117
+ "(#{left} #{op} #{right})"
118
+ end
119
+ end
120
+ class NotPredicate < Predicate
121
+ def_readable :predicate
122
+ def to_s
123
+ "(not #{predicate})"
124
+ end
125
+ end
126
+ class ExistsPredicate < Predicate
127
+ def_readable :relation
128
+ def to_s
129
+ "exists(#{relation})"
130
+ end
131
+ end
132
+ class NotExistsPredicate < Predicate
133
+ def_readable :relation
134
+ def to_s
135
+ "not exists(#{relation})"
136
+ end
137
+ end
138
+ class InRelationPredicate < Predicate
139
+ def_readable :expr, :relation
140
+ def to_s
141
+ "#{expr} in (#{relation})"
142
+ end
143
+ end
144
+ class NotInRelationPredicate < Predicate
145
+ def_readable :expr, :relation
146
+ def to_s
147
+ "#{expr} not in (#{relation})"
148
+ end
149
+ end
150
+ class InPredicate < Predicate
151
+ def_readable :expr, :vals
152
+ def to_s
153
+ "#{expr} in (#{vals.join(', ')})"
154
+ end
155
+ end
156
+ class NotInPredicate < Predicate
157
+ def_readable :expr, :vals
158
+ def to_s
159
+ "#{expr} not in (#{vals.join(', ')})"
160
+ end
161
+ end
162
+ class BetweenPredicate < Predicate
163
+ def_readable :expr, :from, :to
164
+ def to_s
165
+ "#{expr} between #{from} and #{to}"
166
+ end
167
+ end
168
+ class NotBetweenPredicate < Predicate
169
+ def_readable :expr, :from, :to
170
+ def to_s
171
+ "#{expr} not between #{from} and #{to}"
172
+ end
173
+ end
174
+ class GroupComparisonPredicate < Predicate
175
+ def_readable :group1, :op, :group2
176
+ def to_s
177
+ "#{list_exprs group1} #{op} #{list_exprs group2}"
178
+ end
179
+ def list_exprs exprs
180
+ "(#{exprs.join(', ')})"
181
+ end
182
+ end
183
+ #############Relations######################
184
+
185
+ class OrderElement
186
+ def_readable :expr, :asc
187
+ def to_s
188
+ result = "#{expr}"
189
+ unless asc
190
+ result << ' desc'
191
+ end
192
+ result
193
+ end
194
+ end
195
+ class GroupByClause
196
+ def_readable :exprs, :having
197
+ def to_s
198
+ result = exprs.join(', ')
199
+ unless having.nil?
200
+ result << " having #{having}"
201
+ end
202
+ result
203
+ end
204
+ end
205
+ class Relation
206
+ def as_inner
207
+ to_s
208
+ end
209
+ end
210
+ class TableRelation < Relation
211
+ def_readable :table
212
+ def to_s
213
+ table
214
+ end
215
+ end
216
+ class SelectRelation < Relation
217
+ def_readable :select, :distinct, :from, :where, :groupby, :orderby
218
+ def to_s
219
+ result = "select "
220
+ if distinct
221
+ result << 'distinct '
222
+ end
223
+ result << "#{select.join(', ')} from #{from.as_inner}"
224
+ unless where.nil?
225
+ result << " where #{where}"
226
+ end
227
+ unless groupby.nil?
228
+ result << " group by #{groupby}"
229
+ end
230
+ unless orderby.nil?
231
+ result << " order by #{orderby.join(', ')}"
232
+ end
233
+ result
234
+ end
235
+ def as_inner
236
+ "(#{self})"
237
+ end
238
+ end
239
+ class LimitRelation < Relation
240
+ def_readable :rel, :limit
241
+ def to_s
242
+ "#{rel} limit #{limit}"
243
+ end
244
+ end
245
+ class JoinRelation < Relation
246
+ def_readable :kind, :left, :right, :on
247
+ def to_s
248
+ "#{left} #{kind} join #{right} on #{on}"
249
+ end
250
+ end
251
+ class CrossJoinRelation < Relation
252
+ def_readable :left, :right
253
+ def to_s
254
+ "#{left} cross join #{right}"
255
+ end
256
+ end
257
+ class AliasRelation < Relation
258
+ def_readable :relation, :name
259
+ def to_s
260
+ "#{relation.as_inner} AS #{name}"
261
+ end
262
+ end
263
+ class UnionRelation < Relation
264
+ def_readable :left, :all, :right
265
+ def to_s
266
+ "#{left} union #{case when all: 'all ' else '' end}#{right}"
267
+ end
268
+ end
@@ -0,0 +1,258 @@
1
+ require 'import'
2
+ import :parsers, :keywords, :operators, :functors, :expressions
3
+
4
+ include RParsec
5
+
6
+ class Method
7
+ include FunctorMixin
8
+ end
9
+ class Proc
10
+ include FunctorMixin
11
+ end
12
+ module SqlParser
13
+ include Functors
14
+ include Parsers
15
+ extend Parsers
16
+ MyKeywords = Keywords.case_insensitive(%w{
17
+ select from where group by having order desc asc
18
+ inner left right full outer inner join on cross
19
+ union all distinct as exists in between limit
20
+ case when else end and or not true false
21
+ })
22
+ MyOperators = Operators.new(%w{+ - * / % = > < >= <= <> != : ( ) . ,})
23
+ def self.operators(*ops)
24
+ result = []
25
+ ops.each do |op|
26
+ result << (MyOperators[op] >> op.to_sym)
27
+ end
28
+ sum(*result)
29
+ end
30
+ Comparators = operators(*%w{= > < >= <= <> !=})
31
+ StringLiteral = (char(?') >> (not_char(?')|str("''")).many_.fragment << char(?')).
32
+ map do |raw|
33
+ raw.gsub!(/''/,"'")
34
+ end
35
+ QuotedName = char(?[) >> not_char(?]).many_.fragment << char(?])
36
+ Variable = char(?$) >> word
37
+ MyLexer = number.token(:number) | StringLiteral.token(:string) | Variable.token(:var) | QuotedName.token(:word) |
38
+ MyKeywords.lexer | MyOperators.lexer
39
+ MyLexeme = MyLexer.lexeme(whitespaces | comment_line('#')) << eof
40
+
41
+
42
+ ######################################### utilities #########################################
43
+ def keyword
44
+ MyKeywords
45
+ end
46
+ def operator
47
+ MyOperators
48
+ end
49
+ def comma
50
+ operator[',']
51
+ end
52
+ def list expr
53
+ paren(expr.delimited(comma))
54
+ end
55
+ def word(&block)
56
+ if block.nil?
57
+ token(:word, &Id)
58
+ else
59
+ token(:word, &block)
60
+ end
61
+ end
62
+ def paren parser
63
+ operator['('] >> parser << operator[')']
64
+ end
65
+ def ctor cls
66
+ cls.method :new
67
+ end
68
+ def rctor cls, arity=2
69
+ ctor(cls).reverse_curry arity
70
+ end
71
+ ################################### predicate parser #############################
72
+ def logical_operator op
73
+ proc{|a,b|CompoundPredicate.new(a,op,b)}
74
+ end
75
+ def make_predicate expr, rel
76
+ expr_list = list expr
77
+ comparison = make_comparison_predicate expr, rel
78
+ group_comparison = sequence(expr_list, Comparators, expr_list, &ctor(GroupComparisonPredicate))
79
+ bool = nil
80
+ lazy_bool = lazy{bool}
81
+ bool_term = keyword[:true] >> true | keyword[:false] >> false |
82
+ comparison | group_comparison | paren(lazy_bool) |
83
+ make_exists(rel) | make_not_exists(rel)
84
+ bool_table = OperatorTable.new.
85
+ infixl(keyword[:or] >> logical_operator(:or), 20).
86
+ infixl(keyword[:and] >> logical_operator(:and), 30).
87
+ prefix(keyword[:not] >> ctor(NotPredicate), 40)
88
+ bool = Expressions.build(bool_term, bool_table)
89
+ end
90
+ def make_exists rel
91
+ keyword[:exists] >> rel.map(&ctor(ExistsPredicate))
92
+ end
93
+ def make_not_exists rel
94
+ keyword[:not] >> keyword[:exists] >> rel.map(&ctor(NotExistsPredicate))
95
+ end
96
+ def make_in expr
97
+ keyword[:in] >> list(expr) >> map(&rctor(InPredicate))
98
+ end
99
+ def make_not_in expr
100
+ keyword[:not] >> keyword[:in] >> list(expr) >> map(&rctor(NotInPredicate))
101
+ end
102
+ def make_in_relation rel
103
+ keyword[:in] >> rel.map(&rctor(InRelationPredicate))
104
+ end
105
+ def make_not_in_relation rel
106
+ keyword[:not] >> keyword[:in] >> rel.map(&rctor(NotInRelationPredicate))
107
+ end
108
+ def make_between expr
109
+ make_between_clause(expr, &ctor(BetweenPredicate))
110
+ end
111
+ def make_not_between expr
112
+ keyword[:not] >> make_between_clause(expr, &ctor(NotBetweenPredicate))
113
+ end
114
+ def make_comparison_predicate expr, rel
115
+ comparison = sequence(Comparators, expr) do |op,e2|
116
+ proc{|e1|ComparePredicate.new(e1, op, e2)}
117
+ end
118
+ in_clause = make_in expr
119
+ not_in_clause = make_not_in expr
120
+ in_relation = make_in_relation rel
121
+ not_in_relation = make_not_in_relation rel
122
+ between = make_between expr
123
+ not_between = make_not_between expr
124
+ compare_with = comparison | in_clause | not_in_clause |
125
+ in_relation | not_in_relation | between | not_between
126
+ sequence(expr, compare_with, &Feed)
127
+ end
128
+ def make_between_clause expr, &maker
129
+ factory = proc do |a,_,b|
130
+ proc {|v|maker.call(v,a,b)}
131
+ end
132
+ variant1 = keyword[:between] >> paren(sequence(expr, comma, expr, &factory))
133
+ variant2 = keyword[:between] >> sequence(expr, keyword[:and], expr, &factory)
134
+ variant1 | variant2
135
+ end
136
+
137
+ ################################ expression parser ###############################
138
+ def calculate_simple_cases(val, cases, default)
139
+ SimpleCaseExpr.new(val, cases, default)
140
+ end
141
+ def calculate_full_cases(cases, default)
142
+ CaseExpr.new(cases, default)
143
+ end
144
+ def make_expression predicate, rel
145
+ expr = nil
146
+ lazy_expr = lazy{expr}
147
+ simple_case = sequence(keyword[:when], lazy_expr, operator[':'], lazy_expr) do |_,cond,_,val|
148
+ [cond, val]
149
+ end
150
+ full_case = sequence(keyword[:when], predicate, operator[':'], lazy_expr) do |_,cond,_,val|
151
+ [cond, val]
152
+ end
153
+ default_case = (keyword[:else] >> lazy_expr).optional
154
+ simple_when_then = sequence(lazy_expr, simple_case.many, default_case,
155
+ keyword[:end]) do |val, cases, default, _|
156
+ calculate_simple_cases(val, cases, default)
157
+ end
158
+ full_when_then = sequence(full_case.many, default_case, keyword[:end]) do |cases, default, _|
159
+ calculate_full_cases(cases, default)
160
+ end
161
+ case_expr = keyword[:case] >> (simple_when_then | full_when_then)
162
+ wildcard = operator[:*] >> WildcardExpr::Instance
163
+ lit = token(:number, :string, &ctor(LiteralExpr)) | token(:var, &ctor(VarExpr))
164
+ atom = lit | wildcard |
165
+ sequence(word, operator['.'], word|wildcard) {|owner, _, col| QualifiedColumnExpr.new owner, col} |
166
+ word(&ctor(WordExpr))
167
+ term = atom | (operator['('] >> lazy_expr << operator[')']) | case_expr
168
+ table = OperatorTable.new.
169
+ infixl(operator['+'] >> Plus, 20).
170
+ infixl(operator['-'] >> Minus, 20).
171
+ infixl(operator['*'] >> Mul, 30).
172
+ infixl(operator['/'] >> Div, 30).
173
+ infixl(operator['%'] >> Mod, 30).
174
+ prefix(operator['-'] >> Neg, 50)
175
+ expr = Expressions.build(term, table)
176
+ end
177
+
178
+ ################################ relation parser ###############################
179
+ def make_relation expr, pred
180
+ exprs = expr.delimited1(comma)
181
+ relation = nil
182
+ lazy_relation = lazy{relation}
183
+ term_relation = word {|w|TableRelation.new w} | operator['('] >> lazy_relation << operator[')']
184
+ sub_relation = sequence(term_relation, (keyword[:as].optional >> word).optional) do |rel, name|
185
+ case when name.nil?: rel else AliasRelation.new(rel, name) end
186
+ end
187
+ joined_relation = sub_relation.postfix(join_maker(lazy{joined_relation}, pred))
188
+ where_clause = keyword[:where] >> pred
189
+ order_element = sequence(expr, (keyword[:asc] >> true | keyword[:desc] >> false).optional(true),
190
+ &ctor(OrderElement))
191
+ order_elements = order_element.separated1(comma)
192
+ exprs = expr.separated1(comma)
193
+ order_by_clause = keyword[:order] >> keyword[:by] >> order_elements
194
+ group_by = keyword[:group] >> keyword[:by] >> exprs
195
+ group_by_clause = sequence(group_by, (keyword[:having] >> pred).optional, &ctor(GroupByClause))
196
+ relation = sub_relation | sequence(keyword[:select],
197
+ keyword[:distinct].optional(false), exprs,
198
+ keyword[:from], joined_relation,
199
+ where_clause.optional, group_by_clause.optional, order_by_clause.optional
200
+ ) do |_, distinct, projected, _, from, where, groupby, orderby|
201
+ SelectRelation.new(projected, distinct, from, where, groupby, orderby)
202
+ end
203
+ relation = sequence(relation, (keyword[:limit] >> token(:number, &To_i)).optional) do |rel, limit|
204
+ case when limit.nil?: rel else LimitRelation.new(rel, limit) end
205
+ end
206
+ relation = relation.infixl(union_maker)
207
+ end
208
+ def union_maker
209
+ keyword[:union] >> (keyword[:all]>>true|false).map do |all|
210
+ proc {|r1, r2|UnionRelation.new(r1, all, r2)}
211
+ end
212
+ end
213
+ def join_maker rel, pred
214
+ crossjoin = keyword[:cross] >> keyword[:join] >> rel.map(&rctor(CrossJoinRelation))
215
+ leftjoin = outer_join :left
216
+ rightjoin = outer_join :right
217
+ fulljoin = outer_join :full
218
+ innerjoin = keyword[:inner].optional >> keyword[:join] >> :inner
219
+ join_with_condition = sequence(sum(leftjoin, rightjoin, innerjoin), rel,
220
+ keyword[:on], pred) do |kind, r, _, on|
221
+ proc{|r0|JoinRelation.new(kind, r0, r, on)}
222
+ end
223
+ sum(crossjoin, join_with_condition)
224
+ end
225
+ def outer_join kind
226
+ keyword[kind] >> keyword[:outer].optional >> keyword[:join] >> kind
227
+ end
228
+
229
+
230
+
231
+ ########################## put together ###############################
232
+ def expression
233
+ assemble[0]
234
+ end
235
+
236
+ def relation
237
+ assemble[2]
238
+ end
239
+ def predicate
240
+ assemble[1]
241
+ end
242
+
243
+ def assemble
244
+ pred = nil
245
+ rel = nil
246
+ lazy_predicate = lazy{pred}
247
+ lazy_rel = lazy{rel}
248
+ expr = make_expression lazy_predicate, lazy_rel
249
+ pred = make_predicate expr, lazy_rel
250
+ rel = make_relation expr, pred
251
+ return expr, pred, rel
252
+ end
253
+
254
+
255
+ def make parser
256
+ MyLexeme.nested(parser << eof)
257
+ end
258
+ end