yaparc 0.1.0 → 0.1.3
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.
- data/README +21 -22
- data/lib/yaparc.rb +30 -41
- data/tests/test_calc.rb +65 -114
- data/tests/test_parser.rb +12 -230
- data/tests/test_sql.rb +324 -0
- metadata +4 -2
data/README
CHANGED
@@ -15,7 +15,7 @@ There are several implementations of parser combinator in ruby. This is a yet an
|
|
15
15
|
|
16
16
|
In combinator parser, each parser is construct as a function taking input string as arguments. Larger parsers are built from smaller parsers. Although combinators are higher-order functions in ordinary functional languages, they are constructed as classes in yaparc, because Ruby has more object-oriented than functional property.
|
17
17
|
|
18
|
-
All parsers has 'parse' method, each of which takes input string as its arguments except SatisfyParser.
|
18
|
+
All parsers has 'parse' method, each of which takes input string as its arguments except SatisfyParser. Every parser returns either Result::OK or Result::Fail as their result of parsing. An instance of Result::Fail denotes faiilure, and instance of Result::OK indicates success.
|
19
19
|
|
20
20
|
== Primitive Parsers
|
21
21
|
|
@@ -29,25 +29,25 @@ All parsers has 'parse' method, each of which takes input string as its argument
|
|
29
29
|
The parser SucceedParser always succeeds with the result value, without consuming any of the input string.
|
30
30
|
In the following example, SucceedParser#parse takes an input string "blah, blah, blah" and returns the singleton array [[1, "blah, blah, blah"]].
|
31
31
|
|
32
|
-
parser = SucceedParser.new(1)
|
32
|
+
parser = Yaparc::SucceedParser.new(1)
|
33
33
|
parser.parse("blah, blah, blah")
|
34
|
-
=>
|
34
|
+
=> #<Yaparc::Result::OK:0xb7aaaf5c @input="blah, blah, blah", @value=1>
|
35
35
|
|
36
36
|
=== FailParser class
|
37
37
|
|
38
38
|
The parser FailParser always fails, regardless of the contents of the input string.
|
39
39
|
|
40
|
-
parser = FailParser.new
|
40
|
+
parser = Yaparc::FailParser.new
|
41
41
|
parser.parse("abc")
|
42
|
-
=>
|
42
|
+
=> #<Yaparc::Result::Fail:0xb7aa56b0 @value=nil>
|
43
43
|
|
44
44
|
=== ItemParser class
|
45
45
|
|
46
46
|
The parser ItemParser fails if the input string is empty, and succeeds with the first character as the result value otherwise.
|
47
47
|
|
48
|
-
parser =
|
48
|
+
parser = Yaparc::ItemParser.new
|
49
49
|
parser.parse("abc")
|
50
|
-
=>
|
50
|
+
=> #<Yaparc::Result::OK:0xb7a9fdb4 @input="bc", @value="a">
|
51
51
|
|
52
52
|
=== SatisfyParser class
|
53
53
|
|
@@ -61,9 +61,9 @@ The parser SatisfyParser recognizes a single input via predicate which determine
|
|
61
61
|
false
|
62
62
|
end
|
63
63
|
end
|
64
|
-
parser = SatisfyParser.new(is_integer)
|
64
|
+
parser = Yaparc::SatisfyParser.new(is_integer)
|
65
65
|
parser.parse("123")
|
66
|
-
=>
|
66
|
+
=> #<Yaparc::Result::OK:0xb7a8f284 @input="23", @value="1">
|
67
67
|
|
68
68
|
|
69
69
|
== Combining Parsers
|
@@ -81,15 +81,15 @@ The SeqParser corresponds to sequencing in BNF. The following parser recognizes
|
|
81
81
|
|
82
82
|
parser = SeqParser.new(Symbol.new('+'), Natural.new)
|
83
83
|
parser.parse("+321")
|
84
|
-
=>
|
84
|
+
=> #<Yaparc::Result::OK:0xb7a81ae4 @input="", @value=321>
|
85
85
|
|
86
86
|
if a block given to SeqParser, it analyses input string to construct its logical structure.
|
87
87
|
|
88
|
-
parser = SeqParser.new(Symbol.new('+'), Natural.new) do | plus, nat|
|
88
|
+
parser = Yaparc::SeqParser.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | plus, nat|
|
89
89
|
nat
|
90
90
|
end
|
91
91
|
parser.parse("+1234")
|
92
|
-
=>
|
92
|
+
=> #<Yaparc::Result::OK:0xb7a70a00 @input="", @value=1234>
|
93
93
|
|
94
94
|
It produces a parse tree which expounds the semantic structure of the program.
|
95
95
|
|
@@ -98,26 +98,25 @@ It produces a parse tree which expounds the semantic structure of the program.
|
|
98
98
|
The parser AltParser class is an alternation parser, which returns the result of the first parser to succeed, and failure if neither does.
|
99
99
|
|
100
100
|
|
101
|
-
parser = AltParser.new(
|
102
|
-
SeqParser.new(Symbol.new('+'), Natural.new) do | _, nat|
|
101
|
+
parser = Yaparc::AltParser.new(
|
102
|
+
Yaparc::SeqParser.new(Yaparc::Symbol.new('+'), Yaparc::Natural.new) do | _, nat|
|
103
103
|
nat
|
104
104
|
end,
|
105
|
-
Natural.new
|
105
|
+
Yaparc::Natural.new
|
106
106
|
)
|
107
107
|
parser.parse("1234")
|
108
|
-
=>
|
108
|
+
=> #<Yaparc::Result::OK:0xb7a5a610 @input="", @value=1234>
|
109
109
|
parser.parse("-1234")
|
110
|
-
=>
|
110
|
+
=> #<Yaparc::Result::Fail:0xb7a57ba4 @value=nil>
|
111
111
|
|
112
112
|
|
113
113
|
=== ManyParser
|
114
114
|
|
115
115
|
In ManyParser, zero or more applications of parser are admissible.
|
116
116
|
|
117
|
-
parser = ManyParser.new(SatisfyParser.new(lambda {|i| i > '0' and i < '9'}))
|
117
|
+
parser = Yaparc::ManyParser.new(Yaparc::SatisfyParser.new(lambda {|i| i > '0' and i < '9'}))
|
118
118
|
parser.parse("123abc")
|
119
|
-
=>
|
120
|
-
|
119
|
+
=> #<Yaparc::Result::OK:0xb7a49dc4 @input="abc", @value="123">
|
121
120
|
|
122
121
|
=== ManyOneParser
|
123
122
|
|
@@ -145,7 +144,7 @@ There are two ways to construct parser. One is to inherit from Yaparc::ParserBas
|
|
145
144
|
class StringMatch < Yaparc::ParserBase
|
146
145
|
|
147
146
|
def initialize(literal)
|
148
|
-
@parser = Token.new(StringParser.new(literal))
|
147
|
+
@parser = Yaparc::Token.new(Yaparc::StringParser.new(literal))
|
149
148
|
end
|
150
149
|
end
|
151
150
|
|
@@ -154,7 +153,7 @@ The other is to inherit from Yaparc::AbstractParser class.
|
|
154
153
|
class Identifier < Yaparc::AbstractParser
|
155
154
|
def initialize
|
156
155
|
@parser = lambda do
|
157
|
-
Token.new(Ident.new)
|
156
|
+
Yaparc::Token.new(Yaparc::Ident.new)
|
158
157
|
end
|
159
158
|
end
|
160
159
|
end
|
data/lib/yaparc.rb
CHANGED
@@ -1,10 +1,3 @@
|
|
1
|
-
def assert_at(file,line, message = "")
|
2
|
-
unless yield
|
3
|
-
raise "Assertion failed !: #{file}, #{line}: #{message}"
|
4
|
-
end
|
5
|
-
end
|
6
|
-
|
7
|
-
|
8
1
|
module Yaparc
|
9
2
|
module Result
|
10
3
|
class Base
|
@@ -12,7 +5,7 @@ module Yaparc
|
|
12
5
|
def initialize(options = {})
|
13
6
|
@message = options[:message] if options[:message]
|
14
7
|
@input = options[:input] if options[:input]
|
15
|
-
@value = options[:value]
|
8
|
+
@value = options[:value]
|
16
9
|
end
|
17
10
|
end
|
18
11
|
|
@@ -38,16 +31,35 @@ module Yaparc
|
|
38
31
|
mod.extend ClassMethods
|
39
32
|
end
|
40
33
|
|
41
|
-
|
42
34
|
def parse(input, &block)
|
43
35
|
result = @parser.call(input)
|
44
|
-
|
45
|
-
|
36
|
+
|
37
|
+
if result.respond_to? :parse
|
38
|
+
result = result.parse(input)
|
46
39
|
else
|
47
|
-
|
40
|
+
if block_given?
|
41
|
+
# @tree = yield result.value
|
42
|
+
result.value = yield result.value
|
43
|
+
@tree = result
|
44
|
+
else
|
45
|
+
@tree = result.value
|
46
|
+
# @tree = result.parse(input)
|
47
|
+
end
|
48
|
+
result
|
48
49
|
end
|
49
|
-
result
|
50
50
|
end
|
51
|
+
# def parse(input, &block)
|
52
|
+
# result = @parser.call(input)
|
53
|
+
# if block_given?
|
54
|
+
# # @tree = yield result.value
|
55
|
+
# result.value = yield result.value
|
56
|
+
# @tree = result
|
57
|
+
# else
|
58
|
+
# # @tree = result.value
|
59
|
+
# @tree = result.parse(input)
|
60
|
+
# end
|
61
|
+
# result
|
62
|
+
# end
|
51
63
|
|
52
64
|
def eval
|
53
65
|
tree = parse(input)
|
@@ -63,24 +75,6 @@ module Yaparc
|
|
63
75
|
yield
|
64
76
|
end
|
65
77
|
end
|
66
|
-
|
67
|
-
# def define_parser(&block)
|
68
|
-
# @@parser = lambda do |input|
|
69
|
-
# parser = yield
|
70
|
-
# parser.parse(input)
|
71
|
-
# end
|
72
|
-
# end
|
73
|
-
|
74
|
-
# def cparse(input, &block)
|
75
|
-
# tree = @@cparser.call.parse(input)
|
76
|
-
# if block_given?
|
77
|
-
# yield tree
|
78
|
-
# else
|
79
|
-
# tree
|
80
|
-
# end
|
81
|
-
# end
|
82
|
-
# module_function :cparse
|
83
|
-
|
84
78
|
end
|
85
79
|
end # of Module Parsable
|
86
80
|
|
@@ -91,7 +85,6 @@ module Yaparc
|
|
91
85
|
attr_reader :remaining
|
92
86
|
def initialize(value, remaining = nil)
|
93
87
|
@parser = lambda do |input|
|
94
|
-
# [[value, input]]
|
95
88
|
Result::OK.new(:value => value, :input => input)
|
96
89
|
end
|
97
90
|
@remaining = remaining
|
@@ -115,7 +108,6 @@ module Yaparc
|
|
115
108
|
if input.nil? or input.empty?
|
116
109
|
Result::Fail.new
|
117
110
|
else
|
118
|
-
# [[input[0..0],input[1..input.length]]]
|
119
111
|
Result::OK.new(:value => input[0..0],:input => input[1..input.length])
|
120
112
|
end
|
121
113
|
end
|
@@ -125,7 +117,7 @@ module Yaparc
|
|
125
117
|
class SatisfyParser
|
126
118
|
include Parsable
|
127
119
|
def initialize(predicate)
|
128
|
-
|
120
|
+
raise unless predicate.instance_of?(Proc)
|
129
121
|
|
130
122
|
@parser = lambda do |input|
|
131
123
|
case result = ItemParser.new.parse(input)
|
@@ -153,8 +145,6 @@ module Yaparc
|
|
153
145
|
end
|
154
146
|
end
|
155
147
|
|
156
|
-
|
157
|
-
|
158
148
|
class SeqParser
|
159
149
|
include Parsable
|
160
150
|
def initialize(*parsers, &block)
|
@@ -167,6 +157,7 @@ module Yaparc
|
|
167
157
|
break Result::Fail.new
|
168
158
|
else
|
169
159
|
args << result.value
|
160
|
+
# args << result.parse(input)
|
170
161
|
result
|
171
162
|
end
|
172
163
|
end
|
@@ -195,7 +186,6 @@ module Yaparc
|
|
195
186
|
@parser = lambda do |input|
|
196
187
|
initial_result = Result::OK.new(:input => input)
|
197
188
|
final_result = Result::Fail.new
|
198
|
-
# final_result = Error.new
|
199
189
|
parsers.each do |parser|
|
200
190
|
case result = parser.parse(initial_result.input)
|
201
191
|
when Result::Fail
|
@@ -275,12 +265,13 @@ module Yaparc
|
|
275
265
|
include Parsable
|
276
266
|
def initialize(parser, identity = "")
|
277
267
|
@parser = lambda do |input|
|
278
|
-
AltParser.new(ManyOneParser.new(parser, identity), SucceedParser.new(identity)).parse(input)
|
268
|
+
# AltParser.new(ManyOneParser.new(parser, identity), SucceedParser.new(identity)).parse(input)
|
269
|
+
AltParser.new(ManyOneParser.new(parser, identity), SucceedParser.new(identity))
|
279
270
|
end
|
280
271
|
end
|
281
272
|
|
282
273
|
def parse(input)
|
283
|
-
@parser.call(input)
|
274
|
+
@parser.call(input).parse(input)
|
284
275
|
end
|
285
276
|
end
|
286
277
|
|
@@ -319,7 +310,6 @@ module Yaparc
|
|
319
310
|
end
|
320
311
|
end
|
321
312
|
|
322
|
-
|
323
313
|
class ZeroOneParser < ParserBase
|
324
314
|
def initialize(parser)
|
325
315
|
@parser = AltParser.new(parser, SucceedParser.new([])) # Is it OK?
|
@@ -361,7 +351,6 @@ module Yaparc
|
|
361
351
|
class Token < ParserBase
|
362
352
|
|
363
353
|
def initialize(parser, prefix = Space.new, postfix = Space.new)
|
364
|
-
# @parser = SeqParser.new(Space.new, parser, Space.new) do |_, vs, _|
|
365
354
|
@parser = SeqParser.new(prefix, parser, postfix) do |_, vs, _|
|
366
355
|
vs
|
367
356
|
end
|
data/tests/test_calc.rb
CHANGED
@@ -1,126 +1,90 @@
|
|
1
1
|
require 'lib/yaparc.rb'
|
2
2
|
require 'test/unit'
|
3
|
-
require 'pp'
|
4
3
|
|
4
|
+
module Calc
|
5
5
|
|
6
|
-
class Expr < Yaparc::AbstractParser
|
6
|
+
class Expr < Yaparc::AbstractParser
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
def initialize
|
9
|
+
@parser = lambda do
|
10
|
+
Yaparc::AltParser.new(
|
11
|
+
Yaparc::SeqParser.new(Term.new,
|
12
|
+
Yaparc::Symbol.new('+'),
|
13
|
+
Expr.new) do |term, _, expr|
|
14
|
+
['+', term,expr]
|
15
|
+
end,
|
16
|
+
Term.new
|
17
|
+
)
|
18
|
+
end
|
18
19
|
end
|
19
|
-
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
# ['+', term,expr]
|
27
|
-
# end,
|
28
|
-
# Term.new
|
29
|
-
# )
|
30
|
-
# end
|
31
|
-
|
32
|
-
|
33
|
-
def evaluate(input)
|
34
|
-
result = parse(input)
|
35
|
-
tree = result.value
|
36
|
-
eval_tree(tree)
|
37
|
-
end
|
21
|
+
def evaluate(input)
|
22
|
+
result = parse(input)
|
23
|
+
tree = result.value
|
24
|
+
eval_tree(tree)
|
25
|
+
end
|
38
26
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
27
|
+
def eval_tree(tree)
|
28
|
+
case tree
|
29
|
+
when Array
|
30
|
+
case tree[0]
|
31
|
+
when '+'
|
32
|
+
eval_tree(tree[1]) + eval_tree(tree[2])
|
33
|
+
when '-'
|
34
|
+
eval_tree(tree[1]) - eval_tree(tree[2])
|
35
|
+
when '*'
|
36
|
+
eval_tree(tree[1]) * eval_tree(tree[2])
|
37
|
+
when '/'
|
38
|
+
eval_tree(tree[1]) / eval_tree(tree[2])
|
39
|
+
end
|
40
|
+
else
|
41
|
+
tree
|
51
42
|
end
|
52
|
-
else
|
53
|
-
tree
|
54
43
|
end
|
55
44
|
end
|
56
|
-
end
|
57
45
|
|
58
|
-
class Term < Yaparc::AbstractParser
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
46
|
+
class Term < Yaparc::AbstractParser
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@parser = lambda do
|
50
|
+
Yaparc::AltParser.new(
|
51
|
+
Yaparc::SeqParser.new(Factor.new,
|
52
|
+
Yaparc::Symbol.new('*'),
|
53
|
+
Term.new) do |factor, _, term|
|
54
|
+
['*', factor,term]
|
55
|
+
end,
|
56
|
+
Factor.new
|
57
|
+
)
|
58
|
+
end
|
70
59
|
end
|
71
60
|
end
|
72
61
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@parser = lambda do
|
90
|
-
Yaparc::AltParser.new(
|
91
|
-
Yaparc::SeqParser.new(
|
92
|
-
Yaparc::Symbol.new('('),
|
93
|
-
Expr.new,
|
94
|
-
Yaparc::Symbol.new(')')
|
95
|
-
) do |_,expr, _|
|
96
|
-
expr
|
97
|
-
end,
|
98
|
-
Yaparc::Natural.new
|
99
|
-
)
|
62
|
+
class Factor < Yaparc::AbstractParser
|
63
|
+
|
64
|
+
|
65
|
+
def initialize
|
66
|
+
@parser = lambda do
|
67
|
+
Yaparc::AltParser.new(
|
68
|
+
Yaparc::SeqParser.new(
|
69
|
+
Yaparc::Symbol.new('('),
|
70
|
+
Expr.new,
|
71
|
+
Yaparc::Symbol.new(')')
|
72
|
+
) do |_,expr, _|
|
73
|
+
expr
|
74
|
+
end,
|
75
|
+
Yaparc::Natural.new
|
76
|
+
)
|
77
|
+
end
|
100
78
|
end
|
101
79
|
end
|
102
|
-
|
103
|
-
# define_parser do
|
104
|
-
# AltParser.new(
|
105
|
-
# Yaparc::SeqParser.new(
|
106
|
-
# Yaparc::Symbol.new('('),
|
107
|
-
# Expr.new,
|
108
|
-
# Yaparc::Symbol.new(')')
|
109
|
-
# ) do |_,expr, _|
|
110
|
-
# expr
|
111
|
-
# end,
|
112
|
-
# Natural.new
|
113
|
-
# )
|
114
|
-
# end
|
115
|
-
end
|
116
|
-
|
80
|
+
end # of Calc
|
117
81
|
|
118
82
|
class YaparcCalcTest < Test::Unit::TestCase
|
119
83
|
include ::Yaparc
|
120
84
|
|
121
85
|
def setup
|
122
|
-
@expr = Expr.new
|
123
|
-
@factor = Factor.new
|
86
|
+
@expr = Calc::Expr.new
|
87
|
+
@factor = Calc::Factor.new
|
124
88
|
end
|
125
89
|
|
126
90
|
def test_expr
|
@@ -145,17 +109,4 @@ class YaparcCalcTest < Test::Unit::TestCase
|
|
145
109
|
assert_equal 312, result.value
|
146
110
|
assert_equal "", result.input
|
147
111
|
end
|
148
|
-
|
149
|
-
# def test_cexpr
|
150
|
-
# result = @expr.cparse("1 + 2 ")
|
151
|
-
# assert_equal [[["+", 1, 2], ""]], result
|
152
|
-
# end
|
153
|
-
|
154
|
-
# def test_expr_define_parser
|
155
|
-
# parser = Expr.new
|
156
|
-
# result = Expr.parse("1 + 2 ")
|
157
|
-
# assert_equal [[["+", 1, 2], ""]], result
|
158
|
-
# # assert_equal 3, parser.evaluate("1 + 2 ")
|
159
|
-
# # assert_equal 9, parser.evaluate("(1 + 2) * 3 ")
|
160
|
-
# end
|
161
112
|
end
|
data/tests/test_parser.rb
CHANGED
@@ -25,28 +25,12 @@ class YaparcTest < Test::Unit::TestCase
|
|
25
25
|
assert_equal 1, result.value
|
26
26
|
end
|
27
27
|
|
28
|
-
# def test_succeed_parse
|
29
|
-
# parser = ::Yaparc::SucceedParser.new(1)
|
30
|
-
# assert_equal [[1, "abs"]], parser.parse("abs")
|
31
|
-
# assert_equal [[1, "abs"]], parser.tree
|
32
|
-
# result = parser.parse("abs") do |result|
|
33
|
-
# result[0][0]
|
34
|
-
# end
|
35
|
-
# assert_equal 1, result
|
36
|
-
# end
|
37
|
-
|
38
28
|
def test_fail_parse
|
39
29
|
parser = ::Yaparc::FailParser.new
|
40
30
|
result = parser.parse("abc")
|
41
31
|
assert_instance_of Result::Fail, result
|
42
32
|
end
|
43
33
|
|
44
|
-
# def test_fail_parse
|
45
|
-
# parser = ::Yaparc::FailParser.new
|
46
|
-
# result = parser.parse("abc")
|
47
|
-
# assert_equal [], result
|
48
|
-
# end
|
49
|
-
|
50
34
|
def test_item_parse
|
51
35
|
parser = ::Yaparc::ItemParser.new
|
52
36
|
result = parser.parse("")
|
@@ -56,14 +40,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
56
40
|
assert_equal "bc", result.input
|
57
41
|
end
|
58
42
|
|
59
|
-
# def test_item_parse
|
60
|
-
# parser = ::Yaparc::ItemParser.new
|
61
|
-
# result = parser.parse("")
|
62
|
-
# assert_equal [], result
|
63
|
-
# result = parser.parse("abc")
|
64
|
-
# assert_equal [["a", "bc"]], result
|
65
|
-
# end
|
66
|
-
|
67
43
|
def test_satisfy_parse
|
68
44
|
is_integer = lambda do |i|
|
69
45
|
begin
|
@@ -96,37 +72,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
96
72
|
assert_equal "bc", result.input
|
97
73
|
end
|
98
74
|
|
99
|
-
# def test_satisfy_parse
|
100
|
-
# is_integer = lambda do |i|
|
101
|
-
# begin
|
102
|
-
# Integer(i)
|
103
|
-
# true
|
104
|
-
# rescue
|
105
|
-
# false
|
106
|
-
# end
|
107
|
-
# end
|
108
|
-
# parser = SatisfyParser.new(is_integer)
|
109
|
-
# result = parser.parse("123")
|
110
|
-
# assert_equal [["1", "23"]], result
|
111
|
-
|
112
|
-
# parser = SatisfyParser.new(is_integer)
|
113
|
-
# result = parser.parse("abc")
|
114
|
-
# assert_equal [], result
|
115
|
-
|
116
|
-
# is_char = lambda do |i|
|
117
|
-
# begin
|
118
|
-
# String(i)
|
119
|
-
# true
|
120
|
-
# rescue
|
121
|
-
# false
|
122
|
-
# end
|
123
|
-
# end
|
124
|
-
# parser = SatisfyParser.new(is_char)
|
125
|
-
# result = parser.parse("abc")
|
126
|
-
# assert_equal [["a", "bc"]], result
|
127
|
-
# end
|
128
|
-
|
129
|
-
|
130
75
|
def test_seq_parse
|
131
76
|
parser = SeqParser.new(ItemParser.new, ItemParser.new) do |item1, item2|
|
132
77
|
[item1, item2]
|
@@ -150,26 +95,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
150
95
|
assert_equal "DEF", result.input
|
151
96
|
end
|
152
97
|
|
153
|
-
# def test_seq_parse
|
154
|
-
# parser = SeqParser.new(ItemParser.new, ItemParser.new) do |item1, item2|
|
155
|
-
# [item1, item2]
|
156
|
-
# end
|
157
|
-
# result = parser.parse("abcdef")
|
158
|
-
# assert_equal [[["a", "b"], "cdef"]], result
|
159
|
-
|
160
|
-
# parser = SeqParser.new(ItemParser.new, ItemParser.new, ItemParser.new) do |item1, item2, item3|
|
161
|
-
# [item1, item3]
|
162
|
-
# end
|
163
|
-
# result = parser.parse("ABCDEF")
|
164
|
-
# assert_equal [[["A", "C"], "DEF"]], result
|
165
|
-
|
166
|
-
# parser = SeqParser.new(ItemParser.new, ItemParser.new, ItemParser.new) do |item1, item2, item3|
|
167
|
-
# [item2]
|
168
|
-
# end
|
169
|
-
# result = parser.parse("ABCDEF")
|
170
|
-
# assert_equal [[["B"], "DEF"]], result
|
171
|
-
# end
|
172
|
-
|
173
98
|
def test_seq_parse_without_block
|
174
99
|
parser = SeqParser.new(ItemParser.new, ItemParser.new)
|
175
100
|
result = parser.parse("abcdef")
|
@@ -177,12 +102,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
177
102
|
assert_equal "cdef", result.input
|
178
103
|
end
|
179
104
|
|
180
|
-
# def test_seq_parse_without_block
|
181
|
-
# parser = SeqParser.new(ItemParser.new, ItemParser.new)
|
182
|
-
# result = parser.parse("abcdef")
|
183
|
-
# assert_equal [["b", "cdef"]], result
|
184
|
-
# end
|
185
|
-
|
186
105
|
def test_alt_parse
|
187
106
|
parser = AltParser.new(ItemParser.new, SucceedParser.new('d'))
|
188
107
|
result = parser.parse("abc")
|
@@ -199,30 +118,20 @@ class YaparcTest < Test::Unit::TestCase
|
|
199
118
|
assert_instance_of Result::Fail, result
|
200
119
|
end
|
201
120
|
|
202
|
-
|
203
|
-
# def test_alt_parse
|
204
|
-
# parser = AltParser.new(ItemParser.new, SucceedParser.new('d'))
|
205
|
-
# result = parser.parse("abc")
|
206
|
-
# assert_equal [["a", "bc"]], result
|
207
|
-
|
208
|
-
# parser = AltParser.new(FailParser.new, SucceedParser.new('d'))
|
209
|
-
# result = parser.parse("abc")
|
210
|
-
# assert_equal [["d", "abc"]], result
|
211
|
-
|
212
|
-
# parser = AltParser.new(FailParser.new, FailParser.new)
|
213
|
-
# result = parser.parse("abc")
|
214
|
-
# assert_equal [], result
|
215
|
-
# end
|
216
|
-
|
217
121
|
def test_apply_parse
|
218
122
|
is_digit = lambda {|i| i >= '0' and i <= '9'}
|
219
123
|
parser = ApplyParser.new(SatisfyParser.new(is_digit)) do |digit|
|
220
124
|
digit.to_i - '0'.to_i
|
221
125
|
end
|
222
|
-
|
223
126
|
result = parser.parse('7')
|
224
127
|
assert_equal 7, result.value
|
225
128
|
assert_equal "", result.input
|
129
|
+
|
130
|
+
parser = Yaparc::ApplyParser.new(Yaparc::RegexParser.new(/\d+/)) do |match|
|
131
|
+
Integer(match)
|
132
|
+
end
|
133
|
+
result = parser.parse('7')
|
134
|
+
assert_equal 7, result.value
|
226
135
|
end
|
227
136
|
|
228
137
|
def test_char_parse
|
@@ -236,16 +145,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
236
145
|
assert_instance_of Result::Fail, result
|
237
146
|
end
|
238
147
|
|
239
|
-
# def test_char_parse
|
240
|
-
# parser = CharParser.new("a")
|
241
|
-
# result = parser.parse("abc")
|
242
|
-
# assert_equal [["a", "bc"]], result
|
243
|
-
|
244
|
-
# parser = CharParser.new("a")
|
245
|
-
# result = parser.parse("123")
|
246
|
-
# assert_equal [], result
|
247
|
-
# end
|
248
|
-
|
249
148
|
def test_string_parse
|
250
149
|
parser = StringParser.new("abc")
|
251
150
|
result = parser.parse("abcdef")
|
@@ -257,16 +156,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
257
156
|
assert_instance_of Result::Fail, result
|
258
157
|
end
|
259
158
|
|
260
|
-
# def test_string_parse
|
261
|
-
# parser = StringParser.new("abc")
|
262
|
-
# result = parser.parse("abcdef")
|
263
|
-
# assert_equal [["abc", "def"]], result
|
264
|
-
|
265
|
-
# parser = StringParser.new("abc")
|
266
|
-
# result = parser.parse("ab1234")
|
267
|
-
# assert_equal [], result
|
268
|
-
# end
|
269
|
-
|
270
159
|
def test_regex_parse
|
271
160
|
parser = RegexParser.new(/[a-z]/)
|
272
161
|
result = parser.parse("abcdef")
|
@@ -277,17 +166,13 @@ class YaparcTest < Test::Unit::TestCase
|
|
277
166
|
result = parser.parse("1234ab")
|
278
167
|
assert_equal "1234", result.value
|
279
168
|
assert_equal "ab", result.input
|
280
|
-
end
|
281
|
-
|
282
|
-
# def test_regex_parse
|
283
|
-
# parser = RegexParser.new(/[a-z]/)
|
284
|
-
# result = parser.parse("abcdef")
|
285
|
-
# assert_equal [["a", "bcdef"]], result
|
286
169
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
170
|
+
parser = RegexParser.new(/[0-9]+/)
|
171
|
+
result = parser.parse("1234ab") do |match|
|
172
|
+
Integer(match)
|
173
|
+
end
|
174
|
+
assert_equal 1234, result.value
|
175
|
+
end
|
291
176
|
|
292
177
|
def test_zero_one_parse
|
293
178
|
parser = ZeroOneParser.new(StringParser.new("abc"))
|
@@ -300,15 +185,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
300
185
|
assert_equal "123", result.input
|
301
186
|
end
|
302
187
|
|
303
|
-
# def test_zero_one_parse
|
304
|
-
# parser = ZeroOneParser.new(StringParser.new("abc"))
|
305
|
-
# result = parser.parse("abc ")
|
306
|
-
# assert_equal [["abc", " "]], result
|
307
|
-
# parser = ZeroOneParser.new(StringParser.new("abc"))
|
308
|
-
# result = parser.parse("123")
|
309
|
-
# assert_equal [[[], "123"]], result
|
310
|
-
# end
|
311
|
-
|
312
188
|
def test_many_parse
|
313
189
|
is_digit = SatisfyParser.new(lambda {|i| i >= '0' and i <= '9'})
|
314
190
|
parser = ManyParser.new(is_digit)
|
@@ -321,17 +197,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
321
197
|
assert_equal "abcdef", result.input
|
322
198
|
end
|
323
199
|
|
324
|
-
# def test_many_parse
|
325
|
-
# is_digit = SatisfyParser.new(lambda {|i| i >= '0' and i <= '9'})
|
326
|
-
# parser = ManyParser.new(is_digit)
|
327
|
-
# result = parser.parse("123abc")
|
328
|
-
# assert_equal [["123", "abc"]], result
|
329
|
-
|
330
|
-
# result = parser.parse("abcdef")
|
331
|
-
# assert_equal [[[], "abcdef"]], result
|
332
|
-
# end
|
333
|
-
|
334
|
-
|
335
200
|
def test_ident
|
336
201
|
parser = Ident.new
|
337
202
|
result = parser.parse("abc def")
|
@@ -339,12 +204,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
339
204
|
assert_equal " def", result.input
|
340
205
|
end
|
341
206
|
|
342
|
-
# def test_ident
|
343
|
-
# parser = Ident.new
|
344
|
-
# result = parser.parse("abc def")
|
345
|
-
# assert_equal [["abc", " def"]], result
|
346
|
-
# end
|
347
|
-
|
348
207
|
def test_nat
|
349
208
|
parser = Nat.new
|
350
209
|
result = parser.parse("123 abc")
|
@@ -352,13 +211,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
352
211
|
assert_equal " abc", result.input
|
353
212
|
end
|
354
213
|
|
355
|
-
|
356
|
-
# def test_nat
|
357
|
-
# parser = Nat.new
|
358
|
-
# result = parser.parse("123 abc")
|
359
|
-
# assert_equal [[123, " abc"]], result
|
360
|
-
# end
|
361
|
-
|
362
214
|
def test_nat_ident
|
363
215
|
parser = SeqParser.new(Nat.new, Ident.new) do |nat, ident|
|
364
216
|
[nat,ident]
|
@@ -368,14 +220,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
368
220
|
assert_equal "", result.input
|
369
221
|
end
|
370
222
|
|
371
|
-
# def test_nat_ident
|
372
|
-
# parser = SeqParser.new(Nat.new, Ident.new) do |nat, ident|
|
373
|
-
# [nat,ident]
|
374
|
-
# end
|
375
|
-
# result = parser.parse("123abc")
|
376
|
-
# assert_equal [[[123, "abc"], ""]], result
|
377
|
-
# end
|
378
|
-
|
379
223
|
def test_space
|
380
224
|
parser = Space.new
|
381
225
|
result = parser.parse(" abc")
|
@@ -383,12 +227,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
383
227
|
assert_equal "abc", result.input
|
384
228
|
end
|
385
229
|
|
386
|
-
# def test_space
|
387
|
-
# parser = Space.new
|
388
|
-
# result = parser.parse(" abc")
|
389
|
-
# assert_equal [[[], "abc"]], result
|
390
|
-
# end
|
391
|
-
|
392
230
|
def test_identifier
|
393
231
|
parser = Identifier.new
|
394
232
|
result = parser.parse(" abc ")
|
@@ -403,18 +241,6 @@ class YaparcTest < Test::Unit::TestCase
|
|
403
241
|
assert_equal "", result.input
|
404
242
|
end
|
405
243
|
|
406
|
-
# def test_identifier
|
407
|
-
# parser = Identifier.new
|
408
|
-
# result = parser.parse(" abc ")
|
409
|
-
# assert_equal [["abc", ""]], result
|
410
|
-
|
411
|
-
# parser_with_keyword = Identifier.new("abc","efg")
|
412
|
-
# result = parser_with_keyword.parse("abc")
|
413
|
-
# assert_equal [], result
|
414
|
-
# result = parser_with_keyword.parse(" xyz")
|
415
|
-
# assert_equal [["xyz", ""]], result
|
416
|
-
# end
|
417
|
-
|
418
244
|
def test_natural
|
419
245
|
parser = Natural.new
|
420
246
|
result = parser.parse(" 1234 ")
|
@@ -422,55 +248,11 @@ class YaparcTest < Test::Unit::TestCase
|
|
422
248
|
assert_equal "", result.input
|
423
249
|
end
|
424
250
|
|
425
|
-
# def test_natural
|
426
|
-
# parser = Natural.new
|
427
|
-
# result = parser.parse(" 1234 ")
|
428
|
-
# assert_equal [[1234, ""]], result
|
429
|
-
# end
|
430
|
-
|
431
251
|
def test_symbol
|
432
252
|
parser = Symbol.new('%')
|
433
253
|
result = parser.parse(" % ")
|
434
254
|
assert_equal "%", result.value
|
435
255
|
assert_equal "", result.input
|
436
256
|
end
|
437
|
-
|
438
|
-
# def test_symbol
|
439
|
-
# parser = Symbol.new('%')
|
440
|
-
# result = parser.parse(" % ")
|
441
|
-
# assert_equal [["%", ""]], result
|
442
|
-
# end
|
443
|
-
|
444
|
-
# def test_define_parser
|
445
|
-
# parser = Symbol.new('%')
|
446
|
-
# result = parser.parse(" % ")
|
447
|
-
# assert_equal [["%", ""]], result
|
448
|
-
# end
|
449
|
-
|
450
|
-
# def test_combination
|
451
|
-
# parser = AltParser.new(
|
452
|
-
# SeqParser.new(Symbol.new('+'),
|
453
|
-
# Natural.new) do | _, nat|
|
454
|
-
# nat
|
455
|
-
# end,
|
456
|
-
# Natural.new
|
457
|
-
# )
|
458
|
-
# result = parser.parse("+123")
|
459
|
-
# assert_equal [[123, ""]], result
|
460
|
-
# result = parser.parse(" 123 ")
|
461
|
-
# assert_equal [[123, ""]], result
|
462
|
-
# parser = AltParser.new(
|
463
|
-
# SeqParser.new(
|
464
|
-
# Symbol.new('('),
|
465
|
-
# Natural.new,
|
466
|
-
# Symbol.new(')')
|
467
|
-
# ) do |_,expr, _|
|
468
|
-
# expr
|
469
|
-
# end,
|
470
|
-
# Natural.new
|
471
|
-
# )
|
472
|
-
# result = parser.parse("( 123 )")
|
473
|
-
# assert_equal [[123, ""]], result
|
474
|
-
# end
|
475
257
|
end
|
476
258
|
|
data/tests/test_sql.rb
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
require 'lib/yaparc.rb'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
### c.f. http://www11.plala.or.jp/sotsuken/db/sql.html
|
5
|
+
###
|
6
|
+
### query_body := select_expression from_expression where_expression
|
7
|
+
### select_expression := 'select' term_sequence
|
8
|
+
### term_sequence := term[,term_sequence]*
|
9
|
+
### from_expression := 'from' path_expression[, path_expression]*
|
10
|
+
### path_expression := '/' term [path_expression]*
|
11
|
+
### where_expression :=
|
12
|
+
### | search_cond
|
13
|
+
### search_cond := term op term
|
14
|
+
### | ( NOT search_cond )
|
15
|
+
### | ( search_cond AND search_cond )
|
16
|
+
### | ( search_cond OR search_cond )
|
17
|
+
### | EXISTS ( query_body )
|
18
|
+
### | term op ANY ( query_body )
|
19
|
+
### | term op ALL ( query_body )
|
20
|
+
### | term IN ( query_body )
|
21
|
+
### term := any_characters
|
22
|
+
### op := <> | = | < | > | <= | >=
|
23
|
+
|
24
|
+
module SQL
|
25
|
+
### query_body := select_expression from_expression where_expression
|
26
|
+
class QueryBody
|
27
|
+
include Yaparc::Parsable
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@parser = lambda do
|
31
|
+
Yaparc::SeqParser.new(SelectExpression.new,
|
32
|
+
FromExpression.new,
|
33
|
+
WhereExpression.new) do |select, from, where|
|
34
|
+
{:select => select, :from => from, :where => where }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
### select_expression := 'select' term_sequence
|
41
|
+
class SelectExpression
|
42
|
+
include Yaparc::Parsable
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
@parser = lambda do
|
46
|
+
Yaparc::SeqParser.new(
|
47
|
+
Yaparc::Symbol.new('select'),
|
48
|
+
TermSequence.new) do |_,terms|
|
49
|
+
terms
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
### term_sequence := term[,term_sequence]*
|
56
|
+
class TermSequence
|
57
|
+
include Yaparc::Parsable
|
58
|
+
|
59
|
+
def initialize
|
60
|
+
@parser = lambda do
|
61
|
+
Yaparc::SeqParser.new(
|
62
|
+
Term.new,
|
63
|
+
Yaparc::ManyParser.new(
|
64
|
+
Yaparc::SeqParser.new(
|
65
|
+
Yaparc::Symbol.new(','),
|
66
|
+
TermSequence.new) do |_, terms|
|
67
|
+
terms
|
68
|
+
end,
|
69
|
+
[]
|
70
|
+
)
|
71
|
+
) do |term,terms|
|
72
|
+
[term] + terms
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
### from_expression := 'from' path_expression[, path_expression]*
|
79
|
+
class FromExpression
|
80
|
+
include Yaparc::Parsable
|
81
|
+
|
82
|
+
def initialize
|
83
|
+
@parser = lambda do
|
84
|
+
Yaparc::SeqParser.new(
|
85
|
+
Yaparc::Symbol.new('from'),
|
86
|
+
PathExpression.new,
|
87
|
+
Yaparc::ManyParser.new(
|
88
|
+
Yaparc::SeqParser.new(
|
89
|
+
Yaparc::Symbol.new(','),
|
90
|
+
PathExpression.new) do |_, path|
|
91
|
+
[path]
|
92
|
+
end,
|
93
|
+
[]
|
94
|
+
)
|
95
|
+
) do |_,path,paths|
|
96
|
+
path + paths
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
### path_expression := '/' term [path_expression]*
|
104
|
+
class PathExpression
|
105
|
+
include Yaparc::Parsable
|
106
|
+
|
107
|
+
def initialize
|
108
|
+
@parser = lambda do
|
109
|
+
Yaparc::SeqParser.new(
|
110
|
+
Yaparc::Symbol.new('/'),
|
111
|
+
Term.new,
|
112
|
+
Yaparc::ManyParser.new(
|
113
|
+
PathExpression.new do |path|
|
114
|
+
path
|
115
|
+
end,
|
116
|
+
[]
|
117
|
+
)
|
118
|
+
) do |_,term, paths|
|
119
|
+
[term] + paths
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
### where_expression :=
|
126
|
+
### | search_cond
|
127
|
+
class WhereExpression
|
128
|
+
include Yaparc::Parsable
|
129
|
+
|
130
|
+
def initialize
|
131
|
+
@parser = lambda do
|
132
|
+
Yaparc::ManyParser.new(SearchCond.new)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
### term := any_characters
|
138
|
+
class Term
|
139
|
+
include Yaparc::Parsable
|
140
|
+
|
141
|
+
def initialize
|
142
|
+
@parser = lambda do
|
143
|
+
Yaparc::Identifier.new
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
### search_cond := term op term
|
149
|
+
### | ( NOT search_cond )
|
150
|
+
### | ( search_cond AND search_cond )
|
151
|
+
### | ( search_cond OR search_cond )
|
152
|
+
### | EXISTS ( query_body )
|
153
|
+
### | term op ANY ( query_body )
|
154
|
+
### | term op ALL ( query_body )
|
155
|
+
### | term IN ( query_body )
|
156
|
+
|
157
|
+
class SearchCond
|
158
|
+
include Yaparc::Parsable
|
159
|
+
|
160
|
+
def initialize
|
161
|
+
@parser = lambda do
|
162
|
+
Yaparc::AltParser.new(
|
163
|
+
Yaparc::SeqParser.new(Term.new,
|
164
|
+
Op.new,
|
165
|
+
Term.new) do |term1, op, term2|
|
166
|
+
{:operator => op, :args => [term1, term2]}
|
167
|
+
end,
|
168
|
+
Yaparc::SeqParser.new(Yaparc::Symbol.new('('),
|
169
|
+
Yaparc::Symbol.new('NOT'),
|
170
|
+
SearchCond.new,
|
171
|
+
Yaparc::Symbol.new(')')) do |_, _, cond, _|
|
172
|
+
{:logic => :not, :conditions => [cond]}
|
173
|
+
end,
|
174
|
+
Yaparc::SeqParser.new(Yaparc::Symbol.new('('),
|
175
|
+
SearchCond.new,
|
176
|
+
Yaparc::Symbol.new('AND'),
|
177
|
+
SearchCond.new,
|
178
|
+
Yaparc::Symbol.new(')')) do |_, cond1, _,cond2,_|
|
179
|
+
{:logic => :and, :conditions => [cond1, cond2]}
|
180
|
+
end,
|
181
|
+
Yaparc::SeqParser.new(Yaparc::Symbol.new('('),
|
182
|
+
SearchCond.new,
|
183
|
+
Yaparc::Symbol.new('OR'),
|
184
|
+
SearchCond.new,
|
185
|
+
Yaparc::Symbol.new(')')) do |_, cond1, _,cond2,_|
|
186
|
+
{:logic => :or, :conditions => [cond1,cond2]}
|
187
|
+
end,
|
188
|
+
Yaparc::SeqParser.new(Yaparc::Symbol.new('EXISTS'),
|
189
|
+
Yaparc::Symbol.new('('),
|
190
|
+
QueryBody.new,
|
191
|
+
Yaparc::Symbol.new(')')) do |_, _, body,_|
|
192
|
+
{:logic => :exits, :condition => body}
|
193
|
+
end,
|
194
|
+
# term op ANY ( query_body )
|
195
|
+
Yaparc::SeqParser.new(Term.new,
|
196
|
+
Op.new,
|
197
|
+
Yaparc::Symbol.new('ANY'),
|
198
|
+
Yaparc::Symbol.new('('),
|
199
|
+
QueryBody.new,
|
200
|
+
Yaparc::Symbol.new(')')) do |term, op, _, _, body,_|
|
201
|
+
{:operator => op,
|
202
|
+
:term1 => term,
|
203
|
+
:term2 => {:logic => :any, :condition => body}
|
204
|
+
}
|
205
|
+
end,
|
206
|
+
# term op ALL ( query_body )
|
207
|
+
Yaparc::SeqParser.new(Term.new,
|
208
|
+
Op.new,
|
209
|
+
Yaparc::Symbol.new('ALL'),
|
210
|
+
Yaparc::Symbol.new('('),
|
211
|
+
QueryBody.new,
|
212
|
+
Yaparc::Symbol.new(')')) do |term, op, _, _, body,_|
|
213
|
+
{:operator => op,
|
214
|
+
:term1 => term,
|
215
|
+
:term2 => {:logic => :ALL, :condition => body}
|
216
|
+
}
|
217
|
+
end,
|
218
|
+
# term IN ( query_body )
|
219
|
+
Yaparc::SeqParser.new(Term.new,
|
220
|
+
Op.new,
|
221
|
+
Yaparc::Symbol.new('IN'),
|
222
|
+
Yaparc::Symbol.new('('),
|
223
|
+
QueryBody.new,
|
224
|
+
Yaparc::Symbol.new(')')) do |term, op, _, _, body,_|
|
225
|
+
{:operator => op,
|
226
|
+
:term1 => term,
|
227
|
+
:term2 => {:logic => :IN, :condition => body}
|
228
|
+
}
|
229
|
+
end)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
### op := <> | = | < | > | <= | >=
|
235
|
+
class Op
|
236
|
+
include Yaparc::Parsable
|
237
|
+
|
238
|
+
def initialize
|
239
|
+
@parser = lambda do
|
240
|
+
Yaparc::AltParser.new(
|
241
|
+
Yaparc::ApplyParser.new(Yaparc::Symbol.new('<>')) {|_| :not},
|
242
|
+
Yaparc::ApplyParser.new(Yaparc::Symbol.new('<=')) {|_| :lesser_eq },
|
243
|
+
Yaparc::ApplyParser.new(Yaparc::Symbol.new('>=')) {|_| :greater_eq },
|
244
|
+
Yaparc::ApplyParser.new(Yaparc::Symbol.new('<')) {|_| :lesser},
|
245
|
+
Yaparc::ApplyParser.new(Yaparc::Symbol.new('>')) {|_| :greater })
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end # of SQL
|
250
|
+
|
251
|
+
|
252
|
+
class YaparcQueryTest < Test::Unit::TestCase
|
253
|
+
include ::Yaparc
|
254
|
+
|
255
|
+
# def setup
|
256
|
+
# @expr = Expr.new
|
257
|
+
# @factor = Factor.new
|
258
|
+
# end
|
259
|
+
|
260
|
+
def test_op
|
261
|
+
op = SQL::Op.new
|
262
|
+
result = op.parse("<")
|
263
|
+
assert_instance_of Result::OK, result
|
264
|
+
assert_equal :lesser, result.value
|
265
|
+
result = op.parse("<=")
|
266
|
+
assert_instance_of Result::OK, result
|
267
|
+
assert_equal :lesser_eq, result.value
|
268
|
+
end
|
269
|
+
|
270
|
+
def test_term
|
271
|
+
term = SQL::Term.new
|
272
|
+
result = term.parse("abc")
|
273
|
+
assert_instance_of Result::OK, result
|
274
|
+
assert_equal "abc", result.value
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_path_expression
|
278
|
+
path = SQL::PathExpression.new
|
279
|
+
result = path.parse("/xyz")
|
280
|
+
assert_instance_of Result::OK, result
|
281
|
+
assert_equal ["xyz"], result.value
|
282
|
+
result = path.parse("/abc/def")
|
283
|
+
assert_instance_of Result::OK, result
|
284
|
+
assert_equal ["abc", "def"], result.value
|
285
|
+
end
|
286
|
+
|
287
|
+
def test_from_expression
|
288
|
+
path = SQL::FromExpression.new
|
289
|
+
result = path.parse("from /xyz")
|
290
|
+
assert_instance_of Result::OK, result
|
291
|
+
assert_equal ["xyz"], result.value
|
292
|
+
result = path.parse("from /abc/def")
|
293
|
+
assert_instance_of Result::OK, result
|
294
|
+
assert_equal ["abc", "def"], result.value
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_search_cond
|
298
|
+
search = SQL::SearchCond.new
|
299
|
+
result = search.parse("abc <> xyz")
|
300
|
+
assert_instance_of Result::OK, result
|
301
|
+
assert_equal Hash[:operator=> :not, :args=>["abc", "xyz"]], result.value
|
302
|
+
|
303
|
+
result = search.parse("(NOT abc <> xyz)")
|
304
|
+
assert_instance_of Result::OK, result
|
305
|
+
assert_equal Hash[:logic=>:not, :conditions=>[{:operator=>:not, :args=>["abc", "xyz"]}]], result.value
|
306
|
+
result = search.parse("(abc <> xyz AND abc > xyz)")
|
307
|
+
assert_instance_of Result::OK, result
|
308
|
+
assert_equal Hash[
|
309
|
+
:logic=>:and, :conditions=> [{:operator=>:not, :args=>["abc", "xyz"]},
|
310
|
+
{:operator=>:greater, :args=>["abc", "xyz"]}]
|
311
|
+
], result.value
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_query_body
|
315
|
+
query = SQL::QueryBody.new
|
316
|
+
result = query.parse("select abc from /xyz")
|
317
|
+
assert_instance_of Result::OK, result
|
318
|
+
assert_equal Hash[:from=>["xyz"], :where=>"", :select=>["abc"]], result.value
|
319
|
+
result = query.parse("select abc from /xyz/fgh")
|
320
|
+
assert_instance_of Result::OK, result
|
321
|
+
assert_equal Hash[:from=>["xyz","fgh"], :where=>"", :select=>["abc"]], result.value
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.3
|
|
3
3
|
specification_version: 1
|
4
4
|
name: yaparc
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2008-01-
|
6
|
+
version: 0.1.3
|
7
|
+
date: 2008-01-20 00:00:00 +09:00
|
8
8
|
summary: Yet Another Combinator Parser Library
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,11 +31,13 @@ authors:
|
|
31
31
|
files:
|
32
32
|
- tests/test_parser.rb
|
33
33
|
- tests/test_calc.rb
|
34
|
+
- tests/test_sql.rb
|
34
35
|
- lib/yaparc.rb
|
35
36
|
- README
|
36
37
|
test_files:
|
37
38
|
- tests/test_parser.rb
|
38
39
|
- tests/test_calc.rb
|
40
|
+
- tests/test_sql.rb
|
39
41
|
rdoc_options: []
|
40
42
|
|
41
43
|
extra_rdoc_files:
|