Module: GoogleDataSource::DataSource::Sql::Parser
- Extended by:
- Parsers
- Includes:
- Functors, Parsers, RParsec
- Included in:
- GoogleDataSource::DataSource::SqlParser
- Defined in:
- lib/google_data_source/sql/parser.rb
Constant Summary collapse
- MyKeywords =
TODO drop keywords
Keywords.case_insensitive(%w{ select from where group by having order desc asc inner left right full outer inner join on cross union all distinct as exists in between limit offset case when else end and or not true false })
- MyOperators =
Operators.new(%w{+ - * / % = > < >= <= <> != : ( ) . ,})
- Comparators =
operators(*%w{= > < >= <= <> !=})
- StringLiteral =
char(?') >> ((str("\\\\")|str("\\'")|not_char(?')).many_.fragment).map("e_mapper) << char(?')
- QuotedName =
char(?`) >> not_char(?`).many_.fragment << char(?`)
- Variable =
char(?$) >> word
- MyLexer =
number.token(:number) | StringLiteral.token(:string) | Variable.token(:var) | QuotedName.token(:word) | MyKeywords.lexer | MyOperators.lexer
- MyLexeme =
MyLexer.lexeme(whitespaces | comment_line('#')) << eof
Class Method Summary collapse
Instance Method Summary collapse
- #assemble ⇒ Object
- #calculate_full_cases(cases, default) ⇒ Object
-
#calculate_simple_cases(val, cases, default) ⇒ Object
expression parser ###############################.
- #comma ⇒ Object
- #ctor(cls) ⇒ Object
-
#expression ⇒ Object
put together ###############################.
-
#keyword ⇒ Object
utilities #########################################.
- #list(expr) ⇒ Object
-
#logical_operator(op) ⇒ Object
predicate parser #############################.
- #make(parser) ⇒ Object
- #make_between(expr) ⇒ Object
- #make_between_clause(expr, &maker) ⇒ Object
- #make_comparison_predicate(expr, rel) ⇒ Object
- #make_exists(rel) ⇒ Object
- #make_expression(predicate, rel) ⇒ Object
- #make_in(expr) ⇒ Object
- #make_in_relation(rel) ⇒ Object
- #make_not_between(expr) ⇒ Object
- #make_not_exists(rel) ⇒ Object
- #make_not_in(expr) ⇒ Object
- #make_not_in_relation(rel) ⇒ Object
- #make_predicate(expr, rel) ⇒ Object
-
#make_relation(expr, pred) ⇒ Object
relation parser ###############################.
- #operator ⇒ Object
- #paren(parser) ⇒ Object
- #predicate ⇒ Object
- #rctor(cls, arity = 2) ⇒ Object
- #relation ⇒ Object
- #word(&block) ⇒ Object
Class Method Details
.operators(*ops) ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/google_data_source/sql/parser.rb', line 21 def self.operators(*ops) result = [] ops.each do |op| result << (MyOperators[op] >> op.to_sym) end sum(*result) end |
Instance Method Details
#assemble ⇒ Object
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/google_data_source/sql/parser.rb', line 222 def assemble pred = nil rel = nil lazy_predicate = lazy{pred} lazy_rel = lazy{rel} expr = make_expression lazy_predicate, lazy_rel pred = make_predicate expr, lazy_rel rel = make_relation expr, pred return expr, pred, rel end |
#calculate_full_cases(cases, default) ⇒ Object
161 162 163 |
# File 'lib/google_data_source/sql/parser.rb', line 161 def calculate_full_cases(cases, default) CaseExpr.new(cases, default) end |
#calculate_simple_cases(val, cases, default) ⇒ Object
expression parser ###############################
157 158 159 |
# File 'lib/google_data_source/sql/parser.rb', line 157 def calculate_simple_cases(val, cases, default) SimpleCaseExpr.new(val, cases, default) end |
#comma ⇒ Object
51 52 53 |
# File 'lib/google_data_source/sql/parser.rb', line 51 def comma operator[','] end |
#ctor(cls) ⇒ Object
71 72 73 |
# File 'lib/google_data_source/sql/parser.rb', line 71 def ctor cls cls.method :new end |
#expression ⇒ Object
put together ###############################
211 212 213 |
# File 'lib/google_data_source/sql/parser.rb', line 211 def expression assemble[0] end |
#keyword ⇒ Object
utilities #########################################
43 44 45 |
# File 'lib/google_data_source/sql/parser.rb', line 43 def keyword MyKeywords end |
#list(expr) ⇒ Object
55 56 57 |
# File 'lib/google_data_source/sql/parser.rb', line 55 def list expr paren(expr.delimited(comma)) end |
#logical_operator(op) ⇒ Object
predicate parser #############################
80 81 82 |
# File 'lib/google_data_source/sql/parser.rb', line 80 def logical_operator op proc{|a,b|CompoundPredicate.new(a,op,b)} end |
#make(parser) ⇒ Object
233 234 235 |
# File 'lib/google_data_source/sql/parser.rb', line 233 def make parser MyLexeme.nested(parser << eof) end |
#make_between(expr) ⇒ Object
124 125 126 |
# File 'lib/google_data_source/sql/parser.rb', line 124 def make_between expr make_between_clause(expr, &ctor(BetweenPredicate)) end |
#make_between_clause(expr, &maker) ⇒ Object
147 148 149 150 151 152 153 154 |
# File 'lib/google_data_source/sql/parser.rb', line 147 def make_between_clause expr, &maker factory = proc do |a,_,b| proc {|v|maker.call(v,a,b)} end variant1 = keyword[:between] >> paren(sequence(expr, comma, expr, &factory)) variant2 = keyword[:between] >> sequence(expr, keyword[:and], expr, &factory) variant1 | variant2 end |
#make_comparison_predicate(expr, rel) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/google_data_source/sql/parser.rb', line 132 def make_comparison_predicate expr, rel comparison = sequence(Comparators, expr) do |op,e2| proc{|e1|ComparePredicate.new(e1, op, e2)} end in_clause = make_in expr not_in_clause = make_not_in expr in_relation = make_in_relation rel not_in_relation = make_not_in_relation rel between = make_between expr not_between = make_not_between expr compare_with = comparison | in_clause | not_in_clause | in_relation | not_in_relation | between | not_between sequence(expr, compare_with, &Feed) end |
#make_exists(rel) ⇒ Object
100 101 102 |
# File 'lib/google_data_source/sql/parser.rb', line 100 def make_exists rel keyword[:exists] >> rel.map(&ctor(ExistsPredicate)) end |
#make_expression(predicate, rel) ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/google_data_source/sql/parser.rb', line 165 def make_expression predicate, rel expr = nil lazy_expr = lazy{expr} wildcard = operator[:*] >> WildcardExpr::Instance lit = token(:number, :string, &ctor(LiteralExpr)) | token(:var, &ctor(VarExpr)) atom = lit | wildcard | word(&ctor(WordExpr)) term = atom | (operator['('] >> lazy_expr << operator[')']) table = OperatorTable.new. infixl(operator['+'] >> Plus, 20). infixl(operator['-'] >> Minus, 20). infixl(operator['*'] >> Mul, 30). infixl(operator['/'] >> Div, 30). infixl(operator['%'] >> Mod, 30). prefix(operator['-'] >> Neg, 50) expr = Expressions.build(term, table) end |
#make_in(expr) ⇒ Object
108 109 110 |
# File 'lib/google_data_source/sql/parser.rb', line 108 def make_in expr keyword[:in] >> list(expr) >> map(&rctor(InPredicate)) end |
#make_in_relation(rel) ⇒ Object
116 117 118 |
# File 'lib/google_data_source/sql/parser.rb', line 116 def make_in_relation rel keyword[:in] >> rel.map(&rctor(InRelationPredicate)) end |
#make_not_between(expr) ⇒ Object
128 129 130 |
# File 'lib/google_data_source/sql/parser.rb', line 128 def make_not_between expr keyword[:not] >> make_between_clause(expr, &ctor(NotBetweenPredicate)) end |
#make_not_exists(rel) ⇒ Object
104 105 106 |
# File 'lib/google_data_source/sql/parser.rb', line 104 def make_not_exists rel keyword[:not] >> keyword[:exists] >> rel.map(&ctor(NotExistsPredicate)) end |
#make_not_in(expr) ⇒ Object
112 113 114 |
# File 'lib/google_data_source/sql/parser.rb', line 112 def make_not_in expr keyword[:not] >> keyword[:in] >> list(expr) >> map(&rctor(NotInPredicate)) end |
#make_not_in_relation(rel) ⇒ Object
120 121 122 |
# File 'lib/google_data_source/sql/parser.rb', line 120 def make_not_in_relation rel keyword[:not] >> keyword[:in] >> rel.map(&rctor(NotInRelationPredicate)) end |
#make_predicate(expr, rel) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/google_data_source/sql/parser.rb', line 84 def make_predicate expr, rel expr_list = list expr comparison = make_comparison_predicate expr, rel group_comparison = sequence(expr_list, Comparators, expr_list, &ctor(GroupComparisonPredicate)) bool = nil lazy_bool = lazy{bool} bool_term = keyword[:true] >> true | keyword[:false] >> false | comparison | group_comparison | paren(lazy_bool) | make_exists(rel) | make_not_exists(rel) bool_table = OperatorTable.new. infixl(keyword[:or] >> logical_operator(:or), 20). infixl(keyword[:and] >> logical_operator(:and), 30). prefix(keyword[:not] >> ctor(NotPredicate), 40) bool = Expressions.build(bool_term, bool_table) end |
#make_relation(expr, pred) ⇒ Object
relation parser ###############################
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/google_data_source/sql/parser.rb', line 185 def make_relation expr, pred where_clause = keyword[:where] >> pred order_element = sequence(expr, (keyword[:asc] >> true | keyword[:desc] >> false).optional(true), &ctor(OrderElement)) order_elements = order_element.separated1(comma) exprs = expr.separated1(comma) # setup clauses select_clause = keyword[:select] >> exprs order_by_clause = keyword[:order] >> keyword[:by] >> order_elements group_by = keyword[:group] >> keyword[:by] >> exprs group_by_clause = sequence(group_by, (keyword[:having] >> pred).optional, &ctor(GroupByClause)) limit_clause = keyword[:limit] >> token(:number, &To_i) offset_clause = keyword[:offset] >> token(:number, &To_i) # build relation relation = sequence( select_clause.optional([WildcardExpr.new]), where_clause.optional, group_by_clause.optional, order_by_clause.optional, limit_clause.optional, offset_clause.optional ) do |select, where, groupby, orderby, limit, offset| SelectRelation.new(select, where, groupby, orderby, limit, offset) end end |
#operator ⇒ Object
47 48 49 |
# File 'lib/google_data_source/sql/parser.rb', line 47 def operator MyOperators end |
#paren(parser) ⇒ Object
67 68 69 |
# File 'lib/google_data_source/sql/parser.rb', line 67 def paren parser operator['('] >> parser << operator[')'] end |
#predicate ⇒ Object
218 219 220 |
# File 'lib/google_data_source/sql/parser.rb', line 218 def predicate assemble[1] end |
#rctor(cls, arity = 2) ⇒ Object
75 76 77 |
# File 'lib/google_data_source/sql/parser.rb', line 75 def rctor cls, arity=2 ctor(cls).reverse_curry arity end |
#relation ⇒ Object
215 216 217 |
# File 'lib/google_data_source/sql/parser.rb', line 215 def relation assemble[2] end |
#word(&block) ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/google_data_source/sql/parser.rb', line 59 def word(&block) if block.nil? token(:word, &Id) else token(:word, &block) end end |