whittle 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ require "whittle"
2
+
3
+ RSpec.configure do |config|
4
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser with an empty rule" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:expr) do |r|
7
+ r[].as { "test" }
8
+ r["(", :expr, ")"].as { |_, expr, _| expr }
9
+ end
10
+
11
+ rule("(")
12
+ rule(")")
13
+
14
+ start(:expr)
15
+ end
16
+ end
17
+
18
+ it "injects the empty rule to allow matching the input" do
19
+ parser.new.parse("((()))").should == "test"
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser matching the empty string" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:empty) do |r|
7
+ r[].as { "bob" }
8
+ end
9
+
10
+ start(:empty)
11
+ end
12
+ end
13
+
14
+ it "always matches the empty string" do
15
+ parser.new.parse("").should == "bob"
16
+ end
17
+ end
@@ -0,0 +1,55 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser encountering unexpected input" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:wsp) do |r|
7
+ r[/\s+/]
8
+ end
9
+
10
+ rule(:id) do |r|
11
+ r[/[a-z]+/].as(:value)
12
+ end
13
+
14
+ rule(",")
15
+ rule("-")
16
+
17
+ rule(:list) do |r|
18
+ r[:list, ",", :id].as { |list, _, id| list << id }
19
+ r[:id].as { |id| Array(id) }
20
+ end
21
+
22
+ start(:list)
23
+ end
24
+ end
25
+
26
+ it "raises an exception of type ParseError" do
27
+ expect {
28
+ parser.new.parse("a, b - c")
29
+ }.to raise_error(Whittle::ParseError)
30
+ end
31
+
32
+ it "provides access to the line number" do
33
+ begin
34
+ parser.new.parse("a, \nb, \nc- \nd")
35
+ rescue Whittle::ParseError => e
36
+ e.line.should == 3
37
+ end
38
+ end
39
+
40
+ it "provides access to the expected tokens" do
41
+ begin
42
+ parser.new.parse("a, \nb, \nc- \nd")
43
+ rescue Whittle::ParseError => e
44
+ e.expected.should == [","]
45
+ end
46
+ end
47
+
48
+ it "provides access to the received token" do
49
+ begin
50
+ parser.new.parse("a, \nb, \nc- \nd")
51
+ rescue Whittle::ParseError => e
52
+ e.received.should == "-"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser with logical grouping" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:expr) do |r|
7
+ r["(", :expr, ")"].as { |_, expr, _| expr }
8
+ r[:expr, "-", :expr].as { |a, _, b| a - b }
9
+ r[:int].as(:value)
10
+ end
11
+
12
+ rule(:int) do |r|
13
+ r[/[0-9]+/].as { |int| Integer(int) }
14
+ end
15
+
16
+ rule("(")
17
+ rule(")")
18
+ rule("-") % :left ^ 1
19
+
20
+ start(:expr)
21
+ end
22
+ end
23
+
24
+ it "parses the grouping first" do
25
+ parser.new.parse("2-(3-1)-1").should == -1
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser with multiple precedence levels" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:expr) do |r|
7
+ r["(", :expr, ")"].as { |_, expr, _| expr }
8
+ r[:expr, "+", :expr].as { |a, _, b| a + b }
9
+ r[:expr, "-", :expr].as { |a, _, b| a - b }
10
+ r[:expr, "*", :expr].as { |a, _, b| a * b }
11
+ r[:expr, "/", :expr].as { |a, _, b| a / b }
12
+ r[:int].as(:value)
13
+ end
14
+
15
+ rule(:int) do |r|
16
+ r[/[0-9]+/].as { |int| Integer(int) }
17
+ end
18
+
19
+ rule("(")
20
+ rule(")")
21
+ rule("+") % :left ^ 1
22
+ rule("-") % :left ^ 1
23
+ rule("*") % :left ^ 2
24
+ rule("/") % :left ^ 2
25
+
26
+ start(:expr)
27
+ end
28
+ end
29
+
30
+ it "evaluates each precedence as it is encountered" do
31
+ parser.new.parse("4-2*3-(6/3)/2+1").should == -2
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe "a noop parser" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:char) do |r|
7
+ r[/./].as(:value)
8
+ end
9
+
10
+ rule(:prog) do |r|
11
+ r[:char]
12
+ end
13
+
14
+ start(:prog)
15
+ end
16
+ end
17
+
18
+ it "returns nil for all inputs" do
19
+ ["a", "b"].each do |input|
20
+ parser.new.parse(input).should be_nil
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe "a pass-through parser" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:foo) do |r|
7
+ r["FOO"].as(:value)
8
+ end
9
+
10
+ start(:foo)
11
+ end
12
+ end
13
+
14
+ it "returns the input" do
15
+ parser.new.parse("FOO").should == "FOO"
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser depending on operator precedences" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule("+") % :left ^ 1
7
+ rule("*") % :left ^ 2
8
+
9
+ rule(:int) do |r|
10
+ r[/[0-9]+/].as { |i| Integer(i) }
11
+ end
12
+
13
+ rule(:expr) do |r|
14
+ r[:expr, "+", :expr].as { |a, _, b| a + b }
15
+ r[:expr, "*", :expr].as { |a, _, b| a * b }
16
+ r[:int].as(:value)
17
+ end
18
+
19
+ start(:expr)
20
+ end
21
+ end
22
+
23
+ it "resolves shift-reduce conflicts by precedence" do
24
+ parser.new.parse("1+2*3").should == 7
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser with a self-referential rule" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule("(")
7
+ rule(")")
8
+ rule("+")
9
+
10
+ rule(:int) do |r|
11
+ r[/[0-9]+/].as { |int| Integer(int) }
12
+ end
13
+
14
+ rule(:expr) do |r|
15
+ r[:expr, "+", :expr].as { |a, _, b| a + b }
16
+ r[:int].as(:value)
17
+ end
18
+
19
+ start(:expr)
20
+ end
21
+ end
22
+
23
+ it "handles the recursion gracefully" do
24
+ parser.new.parse("2+3+1").should == 6
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser that skips tokens" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:wsp) do |r|
7
+ r[/\s+/]
8
+ end
9
+
10
+ rule("-") % :left
11
+
12
+ rule(:int) do |r|
13
+ r[/[0-9]+/].as { |int| Integer(int) }
14
+ end
15
+
16
+ rule(:expr) do |r|
17
+ r[:expr, "-", :expr].as { |a, _, b| a - b }
18
+ r[:int].as(:value)
19
+ end
20
+
21
+ start(:expr)
22
+ end
23
+ end
24
+
25
+ it "reads the input excluding the skipped tokens" do
26
+ parser.new.parse("6 - 3 - 1").should == 2
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser returning the sum of two integers" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule("+")
7
+
8
+ rule(:int) do |r|
9
+ r[/[0-9]+/].as { |int| Integer(int) }
10
+ end
11
+
12
+ rule(:sum) do |r|
13
+ r[:int, "+", :int].as { |a, _, b| a + b }
14
+ end
15
+
16
+ start(:sum)
17
+ end
18
+ end
19
+
20
+ it "returns the sum of the operands" do
21
+ parser.new.parse("10+20").should == 30
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe "a type-casting parser" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule(:int) do |r|
7
+ r[/[0-9]+/].as { |int| Integer(int) }
8
+ end
9
+
10
+ start(:int)
11
+ end
12
+ end
13
+
14
+ it "returns the input passed through the callback" do
15
+ parser.new.parse("123").should == 123
16
+ end
17
+ end
data/whittle.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "whittle/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "whittle"
7
+ s.version = Whittle::VERSION
8
+ s.authors = ["d11wtq"]
9
+ s.email = ["chris@w3style.co.uk"]
10
+ s.homepage = "https://github.com/d11wtq/whittle"
11
+ s.summary = %q{An efficient, easy to use, LALR parser for Ruby}
12
+ s.description = %q{Write powerful parsers by defining a series of very simple rules
13
+ and operations to perform as those rules are matched. Whittle
14
+ parsers are written in pure ruby and as such are extremely flexible.
15
+ Anybody familiar with parsers like yacc should find Whittle intuitive.
16
+ Those unfamiliar with parsers shouldn't find it difficult to
17
+ understand.}
18
+
19
+ s.rubyforge_project = "whittle"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+
26
+ s.add_development_dependency "rspec", "~> 2.6"
27
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: whittle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - d11wtq
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70265816010420 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70265816010420
25
+ description: ! "Write powerful parsers by defining a series of very simple rules\n
26
+ \ and operations to perform as those rules are matched. Whittle\n
27
+ \ parsers are written in pure ruby and as such are extremely
28
+ flexible.\n Anybody familiar with parsers like yacc should find
29
+ Whittle intuitive.\n Those unfamiliar with parsers shouldn't
30
+ find it difficult to\n understand."
31
+ email:
32
+ - chris@w3style.co.uk
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - .rspec
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - Rakefile
43
+ - lib/whittle.rb
44
+ - lib/whittle/error.rb
45
+ - lib/whittle/errors/grammar_error.rb
46
+ - lib/whittle/errors/parse_error.rb
47
+ - lib/whittle/errors/unconsumed_input_error.rb
48
+ - lib/whittle/parser.rb
49
+ - lib/whittle/rule.rb
50
+ - lib/whittle/rule_set.rb
51
+ - lib/whittle/version.rb
52
+ - spec/spec_helper.rb
53
+ - spec/unit/parser/empty_rule_spec.rb
54
+ - spec/unit/parser/empty_string_spec.rb
55
+ - spec/unit/parser/error_reporting_spec.rb
56
+ - spec/unit/parser/grouped_expr_spec.rb
57
+ - spec/unit/parser/multiple_precedence_spec.rb
58
+ - spec/unit/parser/noop_spec.rb
59
+ - spec/unit/parser/pass_through_parser_spec.rb
60
+ - spec/unit/parser/precedence_spec.rb
61
+ - spec/unit/parser/self_referential_expr_spec.rb
62
+ - spec/unit/parser/skipped_tokens_spec.rb
63
+ - spec/unit/parser/sum_parser_spec.rb
64
+ - spec/unit/parser/typecast_parser_spec.rb
65
+ - whittle.gemspec
66
+ homepage: https://github.com/d11wtq/whittle
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project: whittle
86
+ rubygems_version: 1.8.11
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: An efficient, easy to use, LALR parser for Ruby
90
+ test_files:
91
+ - spec/spec_helper.rb
92
+ - spec/unit/parser/empty_rule_spec.rb
93
+ - spec/unit/parser/empty_string_spec.rb
94
+ - spec/unit/parser/error_reporting_spec.rb
95
+ - spec/unit/parser/grouped_expr_spec.rb
96
+ - spec/unit/parser/multiple_precedence_spec.rb
97
+ - spec/unit/parser/noop_spec.rb
98
+ - spec/unit/parser/pass_through_parser_spec.rb
99
+ - spec/unit/parser/precedence_spec.rb
100
+ - spec/unit/parser/self_referential_expr_spec.rb
101
+ - spec/unit/parser/skipped_tokens_spec.rb
102
+ - spec/unit/parser/sum_parser_spec.rb
103
+ - spec/unit/parser/typecast_parser_spec.rb
104
+ has_rdoc: