rparsec-ruby19 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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