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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca11d04a7ae882b9277380b20a737f9da15d71ff
4
- data.tar.gz: 73b065cfad311d5310d37ace99ddd4a78683c81c
3
+ metadata.gz: 1e4efc171572cb5d16bf779face5ad265fcb0972
4
+ data.tar.gz: 1d735d195b81a1c7244232a3f104764d5f29262c
5
5
  SHA512:
6
- metadata.gz: 8a2044d7296b0c958153481589955db1d2e8e40b5b31d937e72ec12175a51d6cbdaff5936e3e0739bfdcae78effe4652c037a474c237d6b9cfe121fb99631c3e
7
- data.tar.gz: f576cb77ce8d32f23427dbab99faeaefab17ca438496684ef6732617516207b019bbdc2ca35312c86fa5872a19c89ae0773fba95f11adcae202a86bc409dbb8f
6
+ metadata.gz: acd4bbdfc592f343074a53a29eee714a90f780c5655a4dc5ea7ade6ec68690850553b9759feaea59a96b3bac5071f1f70eda1fd930b2946e51b4c8ef057966e4
7
+ data.tar.gz: bbf0d65f906a6579c33f15850e28ab34afece42722adc30cd27368377d71bee894ea0881c4d0f5c93157f423084e1f473be40777ff8ef3cf65f930e8695d942e
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - "1.9.3"
5
+ - "2.1.5"
6
+ - "2.2.0"
7
+ - jruby-19mode
8
+ bundler_args: --without development
9
+ script: rake
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.0.3 ##
2
+
3
+ * examples/tree.rb supports prefix + and -.
4
+ * gem.required_ruby_version is >= 1.9.
5
+
1
6
  ## 0.0.2 ##
2
7
 
3
8
  * Add examples/tree.rb.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ group :development do
4
+ gem "byebug"
5
+ end
6
+
7
+ group :test do
8
+ gem "minitest", "~>5.4"
9
+ end
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
+ [![Gem Version](https://badge.fury.io/rb/pratt_parser.svg)](http://badge.fury.io/rb/pratt_parser)
5
+ [![Build Status](https://travis-ci.org/tommay/pratt_parser.svg)](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
@@ -1,3 +1,11 @@
1
+ require 'rake/testtask'
2
+
3
+ task :default => :test
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = "spec/**/*_spec.rb"
7
+ end
8
+
1
9
  task :gem do
2
10
  sh "gem build pratt_parser.gemspec"
3
11
  end
@@ -83,8 +83,8 @@ class PrattEvaluator
83
83
  token(char, InfixToken.new(lbp, associates, &block))
84
84
  end
85
85
 
86
- token("(", LeftParenToken.new(0))
87
- token(")", RightParenToken.new(0))
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. The parse returns a tree of BinaryNode and NumberNode
6
- # objects which is printed prefix-style ala Lisp.
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 get_number
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
- token("(", LeftParenToken.new(0))
131
- token(")", RightParenToken.new(0))
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
- infix("+", 20)
135
- infix("-", 20)
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.2"
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.2
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: '0'
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