pratt_parser 0.0.2 → 0.0.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.
- checksums.yaml +4 -4
- data/.travis.yml +9 -0
- data/CHANGELOG +5 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +18 -0
- data/README.md +3 -0
- data/Rakefile +8 -0
- data/examples/expression_evaluator.rb +2 -2
- data/examples/tree.rb +41 -7
- data/pratt_parser.gemspec +3 -1
- data/spec/pratt_parser_spec.rb +77 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e4efc171572cb5d16bf779face5ad265fcb0972
|
4
|
+
data.tar.gz: 1d735d195b81a1c7244232a3f104764d5f29262c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acd4bbdfc592f343074a53a29eee714a90f780c5655a4dc5ea7ade6ec68690850553b9759feaea59a96b3bac5071f1f70eda1fd930b2946e51b4c8ef057966e4
|
7
|
+
data.tar.gz: bbf0d65f906a6579c33f15850e28ab34afece42722adc30cd27368377d71bee894ea0881c4d0f5c93157f423084e1f473be40777ff8ef3cf65f930e8695d942e
|
data/.travis.yml
ADDED
data/CHANGELOG
CHANGED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
byebug (3.5.1)
|
5
|
+
columnize (~> 0.8)
|
6
|
+
debugger-linecache (~> 1.2)
|
7
|
+
slop (~> 3.6)
|
8
|
+
columnize (0.9.0)
|
9
|
+
debugger-linecache (1.2.0)
|
10
|
+
minitest (5.5.1)
|
11
|
+
slop (3.6.0)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
ruby
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
byebug
|
18
|
+
minitest (~> 5.4)
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
Pratt Parser
|
2
2
|
============
|
3
3
|
|
4
|
+
[](http://badge.fury.io/rb/pratt_parser)
|
5
|
+
[](https://travis-ci.org/tommay/pratt_parser)
|
6
|
+
|
4
7
|
A Pratt Parser. Just a simple parsing framework.
|
5
8
|
|
6
9
|
Define tokens that describe your language and combine terms. Write a
|
data/Rakefile
CHANGED
@@ -83,8 +83,8 @@ class PrattEvaluator
|
|
83
83
|
token(char, InfixToken.new(lbp, associates, &block))
|
84
84
|
end
|
85
85
|
|
86
|
-
token("(", LeftParenToken.new(
|
87
|
-
token(")", RightParenToken.new(
|
86
|
+
token("(", LeftParenToken.new(1))
|
87
|
+
token(")", RightParenToken.new(1))
|
88
88
|
|
89
89
|
infix("=", 10, &:==)
|
90
90
|
infix("+", 20, &:+)
|
data/examples/tree.rb
CHANGED
@@ -2,14 +2,34 @@
|
|
2
2
|
|
3
3
|
# Parses simple arithmetic expressions using a PrattParser. Supports
|
4
4
|
# +, -, *, /, ^ (with customary precedence and associativity), and
|
5
|
-
# parentheses.
|
6
|
-
# objects which is printed prefix-style ala
|
5
|
+
# parentheses. + and - may be either prefix or infix. The parse
|
6
|
+
# returns a tree of *Node objects which is printed prefix-style ala
|
7
|
+
# Lisp.
|
7
8
|
#
|
8
9
|
# Numeric integer constants are supported using single-digit tokens
|
9
10
|
# which are left-associative.
|
10
11
|
|
11
12
|
require "pratt_parser"
|
12
13
|
|
14
|
+
class UnaryNode
|
15
|
+
def initialize(operator, node)
|
16
|
+
@operator = operator
|
17
|
+
@node = node
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
"(#{@operator} #{@node})"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a pretty-print version of the expression ala Lisp.
|
25
|
+
|
26
|
+
def pp(indent = "")
|
27
|
+
newindent = indent + " "
|
28
|
+
"#{indent}(#{@operator}\n#{@node.pp(newindent)})"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
13
33
|
class BinaryNode
|
14
34
|
def initialize(operator, left, right)
|
15
35
|
@operator = operator
|
@@ -34,7 +54,7 @@ class NumberNode
|
|
34
54
|
@number = number
|
35
55
|
end
|
36
56
|
|
37
|
-
def
|
57
|
+
def number
|
38
58
|
@number
|
39
59
|
end
|
40
60
|
|
@@ -91,6 +111,16 @@ class TreeBuilder
|
|
91
111
|
end
|
92
112
|
end
|
93
113
|
|
114
|
+
# A Bifix token can be either prefix (via nud) or infix (via lcd).
|
115
|
+
|
116
|
+
class BifixToken < InfixToken
|
117
|
+
def nud(parser)
|
118
|
+
# Bind super-right to the right.
|
119
|
+
right = parser.expression(1000000)
|
120
|
+
UnaryNode.new(@operator, right)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
94
124
|
class DigitToken < Token
|
95
125
|
def initialize(lbp, value)
|
96
126
|
super(lbp)
|
@@ -127,12 +157,16 @@ class TreeBuilder
|
|
127
157
|
token(char, InfixToken.new(char, lbp, associates))
|
128
158
|
end
|
129
159
|
|
130
|
-
|
131
|
-
|
160
|
+
def self.bifix(char, lbp)
|
161
|
+
token(char, BifixToken.new(char, lbp, :left))
|
162
|
+
end
|
163
|
+
|
164
|
+
token("(", LeftParenToken.new(1))
|
165
|
+
token(")", RightParenToken.new(1))
|
132
166
|
|
133
167
|
infix("=", 10)
|
134
|
-
|
135
|
-
|
168
|
+
bifix("+", 20)
|
169
|
+
bifix("-", 20)
|
136
170
|
infix("*", 30)
|
137
171
|
infix("/", 30)
|
138
172
|
infix("^", 40, :right)
|
data/pratt_parser.gemspec
CHANGED
@@ -8,7 +8,9 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
9
9
|
gem.name = "pratt_parser"
|
10
10
|
gem.require_paths = ["lib"]
|
11
|
-
gem.version = "0.0.
|
11
|
+
gem.version = "0.0.3"
|
12
|
+
# Needs Enumerator which was added in 1.9.
|
13
|
+
gem.required_ruby_version = ">= 1.9"
|
12
14
|
gem.license = "MIT"
|
13
15
|
# gem.required_ruby_version = '>= 2.1.0'
|
14
16
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Need a lot more tests than this but it's a start.
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "bundler/setup"
|
5
|
+
require "minitest/autorun"
|
6
|
+
require "pratt_parser"
|
7
|
+
|
8
|
+
describe PrattParser do
|
9
|
+
# it "parses an empty expression" do
|
10
|
+
# lexer = Enumerator.new {}
|
11
|
+
# PrattParser.new(lexer).eval.must_be nil
|
12
|
+
# end
|
13
|
+
|
14
|
+
it "calls nud(self) for the first token in a (sub)expression" do
|
15
|
+
token = MiniTest::Mock.new
|
16
|
+
lexer = Enumerator.new do |y|
|
17
|
+
y << token
|
18
|
+
end
|
19
|
+
parser = PrattParser.new(lexer)
|
20
|
+
token.expect(:nud, "ok", [parser])
|
21
|
+
parser.eval.must_equal "ok"
|
22
|
+
token.verify
|
23
|
+
end
|
24
|
+
|
25
|
+
it "moves on to the next token on a valid expect" do
|
26
|
+
class TokenA
|
27
|
+
def nud(parser)
|
28
|
+
parser.expect(TokenB)
|
29
|
+
"A"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
class TokenB; end
|
33
|
+
class TokenC
|
34
|
+
def lbp; 0; end
|
35
|
+
end
|
36
|
+
|
37
|
+
expected_token = MiniTest::Mock.new
|
38
|
+
expected_token.expect(:class, TokenB, [])
|
39
|
+
|
40
|
+
fetched_expected_token = false
|
41
|
+
lexer = Enumerator.new do |y|
|
42
|
+
y << TokenA.new
|
43
|
+
y << expected_token
|
44
|
+
fetched_expected_token = true
|
45
|
+
y << TokenC.new
|
46
|
+
end
|
47
|
+
|
48
|
+
PrattParser.new(lexer).eval
|
49
|
+
|
50
|
+
assert fetched_expected_token
|
51
|
+
end
|
52
|
+
|
53
|
+
it "fails on invalid expect" do
|
54
|
+
class TokenA
|
55
|
+
def nud(parser)
|
56
|
+
parser.expect(TokenC)
|
57
|
+
"A"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
class TokenB; end
|
61
|
+
class TokenC; end
|
62
|
+
|
63
|
+
unexpected_token = MiniTest::Mock.new
|
64
|
+
unexpected_token.expect(:class, TokenB, [])
|
65
|
+
unexpected_token.expect(:class, TokenB, [])
|
66
|
+
|
67
|
+
lexer = Enumerator.new do |y|
|
68
|
+
y << TokenA.new
|
69
|
+
y << unexpected_token
|
70
|
+
end
|
71
|
+
|
72
|
+
assert_raises RuntimeError do
|
73
|
+
PrattParser.new(lexer).eval
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pratt_parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom May
|
@@ -19,7 +19,10 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- ".gitignore"
|
22
|
+
- ".travis.yml"
|
22
23
|
- CHANGELOG
|
24
|
+
- Gemfile
|
25
|
+
- Gemfile.lock
|
23
26
|
- LICENSE.md
|
24
27
|
- README.md
|
25
28
|
- Rakefile
|
@@ -27,6 +30,7 @@ files:
|
|
27
30
|
- examples/tree.rb
|
28
31
|
- lib/pratt_parser.rb
|
29
32
|
- pratt_parser.gemspec
|
33
|
+
- spec/pratt_parser_spec.rb
|
30
34
|
homepage: https://github.com/tommay/pratt_parser
|
31
35
|
licenses:
|
32
36
|
- MIT
|
@@ -39,7 +43,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
39
43
|
requirements:
|
40
44
|
- - ">="
|
41
45
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
46
|
+
version: '1.9'
|
43
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
48
|
requirements:
|
45
49
|
- - ">="
|
@@ -51,4 +55,5 @@ rubygems_version: 2.4.5
|
|
51
55
|
signing_key:
|
52
56
|
specification_version: 4
|
53
57
|
summary: A Pratt parser.
|
54
|
-
test_files:
|
58
|
+
test_files:
|
59
|
+
- spec/pratt_parser_spec.rb
|