whittle 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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