whittle 0.0.5 → 0.0.6

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.
@@ -0,0 +1,12 @@
1
+ # Whittle: A little LALR(1) parser in pure ruby, without a generator.
2
+ #
3
+ # Copyright (c) Chris Corbyn, 2011
4
+
5
+ module Whittle
6
+ # Represents an nonterminal Rule, which refers to other Rules.
7
+ class NonTerminal < Rule
8
+ def terminal?
9
+ false
10
+ end
11
+ end
12
+ end
@@ -76,7 +76,7 @@ module Whittle
76
76
  raise ArgumentError,
77
77
  "Parser#rule does not accept both a Hash and a block" if name.kind_of?(Hash)
78
78
 
79
- rules[name] = RuleSet.new(name)
79
+ rules[name] = RuleSet.new(name, false)
80
80
  rules[name].tap { |r| yield r }
81
81
  else
82
82
  key, value = if name.kind_of?(Hash)
@@ -88,7 +88,7 @@ module Whittle
88
88
  [name, name]
89
89
  end
90
90
 
91
- rules[key] = RuleSet.new(key)
91
+ rules[key] = RuleSet.new(key, true)
92
92
  rules[key][value].as(:value)
93
93
  end
94
94
  end
data/lib/whittle/rule.rb CHANGED
@@ -28,7 +28,6 @@ module Whittle
28
28
  @components = components
29
29
  @action = DUMP_ACTION
30
30
  @name = name
31
- @terminal = components.length == 1 && !components.first.kind_of?(Symbol)
32
31
  @assoc = :right
33
32
  @prec = 0
34
33
 
@@ -40,7 +39,7 @@ module Whittle
40
39
 
41
40
  pattern = @components.first
42
41
 
43
- if @terminal
42
+ if terminal?
44
43
  @pattern = if pattern.kind_of?(Regexp)
45
44
  Regexp.new("\\G#{pattern}")
46
45
  else
@@ -57,7 +56,7 @@ module Whittle
57
56
  # @return [Boolean]
58
57
  # true if this rule represents a terminal symbol
59
58
  def terminal?
60
- @terminal
59
+ raise "Must be implemented by subclass"
61
60
  end
62
61
 
63
62
  # Walks all possible branches from the given rule, building a parse table.
@@ -83,7 +82,7 @@ module Whittle
83
82
  end || [self, new_offset].hash
84
83
 
85
84
  if sym.nil?
86
- assert_reducable!(state, sym)
85
+ assert_reducible!(state, sym)
87
86
 
88
87
  state[sym] = {
89
88
  :action => :reduce,
@@ -231,7 +230,7 @@ module Whittle
231
230
  #
232
231
  # Returns nil if nothing is matched.
233
232
  def scan(source, offset, line)
234
- return nil unless @terminal
233
+ return nil unless terminal?
235
234
 
236
235
  if match = source.match(@pattern, offset)
237
236
  {
@@ -255,7 +254,7 @@ module Whittle
255
254
  end
256
255
  end
257
256
 
258
- def assert_reducable!(instructions, sym)
257
+ def assert_reducible!(instructions, sym)
259
258
  if instructions.key?(sym) && !instructions[sym][:rule].equal?(self)
260
259
  message = <<-END.gsub(/(^|$)\s+/m, " ")
261
260
  Unresolvable conflict found between rules
@@ -15,9 +15,13 @@ module Whittle
15
15
  #
16
16
  # @param [Symbol, String] name
17
17
  # the name of the rule in the grammar
18
- def initialize(name)
19
- @name = name
20
- @rules = []
18
+ #
19
+ # @param [Boolean] terminal
20
+ # the class the use to add new rules
21
+ def initialize(name, terminal = false)
22
+ @name = name
23
+ @rules = []
24
+ @terminal = terminal
21
25
  end
22
26
 
23
27
  # Enumerate all Rules in the set.
@@ -30,7 +34,8 @@ module Whittle
30
34
  # @param [Object...] components...
31
35
  # a variable list of components (Symbols, Strings, or Regexps)
32
36
  def [](*components)
33
- Rule.new(@name, *components).tap do |rule|
37
+ klass = terminal? ? Terminal : NonTerminal
38
+ klass.new(@name, *components).tap do |rule|
34
39
  @rules << rule
35
40
  end
36
41
  end
@@ -88,7 +93,7 @@ module Whittle
88
93
  # @return [Boolean]
89
94
  # true if this rule is a terminal symbol
90
95
  def terminal?
91
- @rules.length == 1 && @rules.first.terminal?
96
+ @terminal
92
97
  end
93
98
 
94
99
  # Predicate test for whether or not this RuleSet references a nonterminal Symbol.
@@ -0,0 +1,12 @@
1
+ # Whittle: A little LALR(1) parser in pure ruby, without a generator.
2
+ #
3
+ # Copyright (c) Chris Corbyn, 2011
4
+
5
+ module Whittle
6
+ # Represents an terminal Rule, matching a pattern in the input String
7
+ class Terminal < Rule
8
+ def terminal?
9
+ true
10
+ end
11
+ end
12
+ end
@@ -3,5 +3,5 @@
3
3
  # Copyright (c) Chris Corbyn, 2011
4
4
 
5
5
  module Whittle
6
- VERSION = "0.0.5"
6
+ VERSION = "0.0.6"
7
7
  end
data/lib/whittle.rb CHANGED
@@ -8,5 +8,7 @@ require "whittle/errors/unconsumed_input_error"
8
8
  require "whittle/errors/parse_error"
9
9
  require "whittle/errors/grammar_error"
10
10
  require "whittle/rule"
11
+ require "whittle/terminal"
12
+ require "whittle/non_terminal"
11
13
  require "whittle/rule_set"
12
14
  require "whittle/parser"
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe "a parser with a nonterminal rule looking like a terminal" do
4
+ let(:parser) do
5
+ Class.new(Whittle::Parser) do
6
+ rule("+")
7
+
8
+ rule(:prog) do |r|
9
+ r["+"]
10
+ end
11
+
12
+ start(:prog)
13
+ end
14
+ end
15
+
16
+ it "recognises the correct terminal" do
17
+ parser.new.parse("+").should == "+"
18
+ end
19
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: whittle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70134349797920 !ruby/object:Gem::Requirement
16
+ requirement: &70361567853620 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '2.6'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70134349797920
24
+ version_requirements: *70361567853620
25
25
  description: ! "Write powerful parsers by defining a series of very simple rules\n
26
26
  \ and operations to perform as those rules are matched. Whittle\n
27
27
  \ parsers are written in pure ruby and as such are extremely
@@ -46,9 +46,11 @@ files:
46
46
  - lib/whittle/errors/grammar_error.rb
47
47
  - lib/whittle/errors/parse_error.rb
48
48
  - lib/whittle/errors/unconsumed_input_error.rb
49
+ - lib/whittle/non_terminal.rb
49
50
  - lib/whittle/parser.rb
50
51
  - lib/whittle/rule.rb
51
52
  - lib/whittle/rule_set.rb
53
+ - lib/whittle/terminal.rb
52
54
  - lib/whittle/version.rb
53
55
  - spec/spec_helper.rb
54
56
  - spec/unit/parser/empty_rule_spec.rb
@@ -56,6 +58,7 @@ files:
56
58
  - spec/unit/parser/error_reporting_spec.rb
57
59
  - spec/unit/parser/grouped_expr_spec.rb
58
60
  - spec/unit/parser/multiple_precedence_spec.rb
61
+ - spec/unit/parser/non_terminal_ambiguity_spec.rb
59
62
  - spec/unit/parser/noop_spec.rb
60
63
  - spec/unit/parser/pass_through_parser_spec.rb
61
64
  - spec/unit/parser/precedence_spec.rb
@@ -98,6 +101,7 @@ test_files:
98
101
  - spec/unit/parser/error_reporting_spec.rb
99
102
  - spec/unit/parser/grouped_expr_spec.rb
100
103
  - spec/unit/parser/multiple_precedence_spec.rb
104
+ - spec/unit/parser/non_terminal_ambiguity_spec.rb
101
105
  - spec/unit/parser/noop_spec.rb
102
106
  - spec/unit/parser/pass_through_parser_spec.rb
103
107
  - spec/unit/parser/precedence_spec.rb