babel_bridge 0.3.1 → 0.4.0

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.
data/lib/rule.rb CHANGED
@@ -4,10 +4,10 @@ class Rule
4
4
  attr_accessor :name, :variants, :parser, :node_class
5
5
 
6
6
  private
7
- # creates a subclass of the NonTerminalNode for this Rule's node_class
7
+ # creates a subclass of the RuleNode for this Rule's node_class
8
8
  def create_node_class
9
9
  class_name = "#{parser.module_name}_#{name}_node".camelize
10
- parser.const_set class_name, Class.new(NonTerminalNode)
10
+ parser.const_set class_name, Class.new(RuleNode)
11
11
  end
12
12
 
13
13
  # creates a new sub_class of the node_class for a variant
@@ -59,4 +59,4 @@ class Rule
59
59
  "#{variants.collect {|v|v.to_s}.join("\n\t")}"
60
60
  end
61
61
  end
62
- end
62
+ end
data/lib/shell.rb CHANGED
@@ -7,19 +7,42 @@ class Shell
7
7
  @parser = parser
8
8
  end
9
9
 
10
- def evaluate(parse_tree_node)
11
- if parse_tree_node.respond_to? :evaluate
12
- " => "+parse_tree_node.evaluate.inspect
10
+ def pretty_print_parse_tree(parse_tree_node)
11
+ puts "\nParse tree:\n #{parse_tree_node.inspect.gsub("\n","\n ")}\n\n"
12
+ end
13
+
14
+ # Providing a block overrides all evaluate behavor and simply: yield parse_tree_node, self
15
+ # elsif parse_tree_node responds to "evaluate": puts_result parse_tree_node.evaluate
16
+ # else pretty-print the parse-tree
17
+ # rescue and pretty-print errors
18
+ def evaluate(parse_tree_node, &block)
19
+ if block
20
+ yield parse_tree_node, self
21
+ elsif parse_tree_node.respond_to? :evaluate
22
+ puts_result parse_tree_node.evaluate
13
23
  else
14
- "\nParse tree:\n "+
15
- parse_tree_node.inspect.gsub("\n","\n ")+"\n\n"
24
+ pretty_print_parse_tree parse_tree_node
16
25
  end
17
26
  rescue Exception => e
18
- @stderr.puts "Error evaluating parse tree: #{e}\n "+e.backtrace.join("\n ")+"\nParse Tree:\n"+parse_tree_node.inspect
27
+ errputs "Error evaluating parse tree: #{e}\n" + ["Backtrace:",e.backtrace].flatten.join("\n ")
28
+ pretty_print_parse_tree parse_tree_node
29
+ end
30
+
31
+ def puts(str)
32
+ @stdout.puts str
33
+ end
34
+
35
+ def puts_result(str)
36
+ @stdout.puts " => "+str.inspect
37
+ end
38
+
39
+ def errputs(str)
40
+ @stderr.puts str
19
41
  end
20
42
 
21
- # if block is provided, successful parsers are yield to block
22
- # Otherwise, succuessful parsers are sent the "eval" method
43
+ # Each line of input is parsed.
44
+ # If parser fails, output explaination of why.
45
+ # If parser succeeds, evaluate parse_tree_node, &block
23
46
  def start(options={},&block)
24
47
  @stdout = options[:stdout] || $stdout
25
48
  @stderr = options[:stdout] || @stdout
@@ -27,15 +50,11 @@ class Shell
27
50
  while line = @stdin == $stdin ? Readline.readline("> ", true) : @stdin.gets
28
51
  line.strip!
29
52
  next if line.length==0
30
- ret = parser.parse line
31
- if ret
32
- if block
33
- yield ret
34
- else
35
- @stdout.puts evaluate(ret)
36
- end
53
+ parse_tree_node = parser.parse line
54
+ if parse_tree_node
55
+ evaluate parse_tree_node, &block
37
56
  else
38
- @stderr.puts parser.parser_failure_info :verbose => true
57
+ errputs parser.parser_failure_info :verbose => true
39
58
  end
40
59
  end
41
60
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module BabelBridge
2
- VERSION = "0.3.1"
3
- end
2
+ VERSION = "0.4.0"
3
+ end
data/spec/bb_spec.rb ADDED
@@ -0,0 +1,164 @@
1
+ require File.join(File.dirname(__FILE__),"..","lib","babel_bridge")
2
+
3
+ describe BabelBridge do
4
+ attr_accessor :parser
5
+
6
+ def new_parser(&block)
7
+ $parser_counter||=0
8
+ $parser_counter+=1
9
+ Object.const_set(klass_name="TestParser#{$parser_counter}",Class.new(BabelBridge::Parser,&block))
10
+ @parser=Object.const_get(klass_name).new
11
+ end
12
+
13
+ #options
14
+ # :parser
15
+ # :failure_ok
16
+ def test_parse(string,options={})
17
+ parser = options[:parser] || @parser
18
+ res = parser.parse(string)
19
+ if options[:should_fail_at]
20
+ res.should == nil
21
+ parser.failure_index.should == options[:should_fail_at]
22
+ elsif !options[:failure_ok]
23
+ puts parser.parser_failure_info :verbose => true unless res
24
+ res.should_not == nil
25
+ end
26
+ res
27
+ end
28
+
29
+ it "ignore_whitespace should work" do
30
+ new_parser do
31
+ ignore_whitespace
32
+ rule :foobar, "foo", "bar"
33
+ end
34
+
35
+ test_parse "foobar"
36
+ test_parse "foo bar"
37
+ test_parse "foo \t \r \f \n bar"
38
+ test_parse " foobar"
39
+ test_parse "foobar "
40
+ end
41
+
42
+ it "the failure_index should be the furthest point reached, even if we managed to successfully match less" do
43
+ new_parser do
44
+ ignore_whitespace
45
+
46
+ rule :statement, "while", :statement, "end"
47
+ rule :statement, "0"
48
+ rule :statement, /[_a-zA-Z][_a-zA-Z0-9]*/
49
+ end
50
+
51
+ res = test_parse "while 0 foo", :should_fail_at => 8
52
+ end
53
+
54
+ it "parsing twice when the first didn't match all input should, but the second just failed, shouldn't report 'did not match entire input'" do
55
+ new_parser do
56
+ rule :foo, "foo"
57
+ end
58
+
59
+ partial_match_string = "did not match entire input"
60
+
61
+ test_parse "foobar", :failure_ok => true
62
+ parser.parser_failure_info[partial_match_string].should == partial_match_string
63
+ test_parse "bar", :failure_ok => true
64
+ parser.parser_failure_info[partial_match_string].should == nil
65
+ end
66
+
67
+ it "include_whitespace should work" do
68
+ new_parser do
69
+ ignore_whitespace
70
+
71
+ rule :pair, :statement, :end_statement, :statement
72
+ rule :end_statement, include_whitespace(/([\t ]*[\n;])+/)
73
+ rule :statement, "0"
74
+ end
75
+
76
+ test_parse "0;0"
77
+ test_parse "0\n0"
78
+ test_parse "0 ; 0"
79
+ test_parse "0 ; ; 0"
80
+ test_parse "0 \n 0"
81
+ test_parse "0 \n \n 0"
82
+ test_parse "0 \n ; \n 0"
83
+ test_parse "0 ; \n ;0"
84
+ test_parse "0 0", :should_fail_at => 1
85
+ end
86
+
87
+ it "include_whitespace should work even with EmptyNodes" do
88
+ new_parser do
89
+ ignore_whitespace
90
+
91
+ rule :pair, :statement, :end_statement, :statement
92
+ rule :end_statement, include_whitespace(/([\t ]*[\n;])+/)
93
+ rule :statement, "0", :one?, :one?, :one?
94
+ rule :one, "1"
95
+ end
96
+
97
+ test_parse "0;0"
98
+ test_parse "01;0"
99
+ test_parse "0\n0"
100
+ test_parse "01\n0"
101
+ test_parse "011\n0"
102
+ test_parse "0111\n0"
103
+ end
104
+
105
+ it "include_whitespace should work with many" do
106
+ new_parser do
107
+ ignore_whitespace
108
+ rule :statements, many(:statement,:end_statement)
109
+ rule :end_statement, include_whitespace(/([\t ]*[;\n])+/)
110
+ rule :statement, "0"
111
+ end
112
+
113
+ test_parse "0"
114
+ test_parse "0\n0"
115
+ end
116
+
117
+ it "custom ignore_whitespace should work" do
118
+ new_parser do
119
+ ignore_whitespace /[_\s]*/
120
+
121
+ rule :foobar, "foo", "bar"
122
+ end
123
+
124
+ test_parse "foobar"
125
+ test_parse "foo_bar"
126
+ test_parse "foo_ bar"
127
+ test_parse "foo _ bar"
128
+ test_parse "foo bar"
129
+ test_parse "foo-bar", :should_fail_at => 3
130
+ end
131
+
132
+ it "should work to have many many parsing" do
133
+ new_parser do
134
+ rule :top, many(:bottom,";")
135
+ rule :bottom, many("0",",")
136
+ end
137
+
138
+ test_parse "0"
139
+ test_parse "0;0"
140
+ test_parse "0,0"
141
+ test_parse "0,0;0"
142
+ test_parse "0;0,0"
143
+ test_parse "0,0,0;0;0,0,0"
144
+ end
145
+
146
+ it "should work to have many many parsing with whitespace tricks" do
147
+ new_parser do
148
+ ignore_whitespace
149
+ rule :statements, many(:statement,:end_statement)
150
+ rule :end_statement, include_whitespace(/([\t ]*[;\n])+/)
151
+ rule :statement, :bin_op
152
+ binary_operators_rule :bin_op, :int, ["**", [:/, :*], [:+, "-"]], :right_operators => ["**"]
153
+ rule :int, /\d+/
154
+ end
155
+
156
+ test_parse "0"
157
+ test_parse <<ENDCODE
158
+ 3+4
159
+ 9-2
160
+ 4
161
+ ENDCODE
162
+ end
163
+
164
+ end
data/test/test_bb.rb CHANGED
@@ -292,7 +292,8 @@ class BBTests < TestHelper
292
292
  if src[offset..-1].index(/\A[A-Z]+/)==0
293
293
  endpattern=$~.to_s
294
294
  if i=src.index(endpattern,offset+endpattern.length)
295
- BabelBridge::TerminalNode.new(parent_node,i+endpattern.length-offset,"endpattern")
295
+ range = offset..(i+endpattern.length)
296
+ BabelBridge::TerminalNode.new(parent_node,range,"endpattern")
296
297
  end
297
298
  end
298
299
  end}
@@ -322,20 +323,6 @@ class BBTests < TestHelper
322
323
  assert_equal ["foo","foo"], parser.parse("foo foo").foo.collect {|f| f.text}
323
324
  end
324
325
 
325
- def test_poly_post_delimiter
326
- parser=new_parser do
327
- rule :foo, many?("foo",/ +/,true).as(:foo), match("end").as(:end)
328
- end
329
-
330
- assert_equal nil,parser.parse("end").foo
331
- assert_equal "end",parser.parse("end").end.to_s
332
- assert_equal nil,parser.parse(" end")
333
- assert_equal nil,parser.parse("foofoo end")
334
- assert_equal ["foo"], parser.parse("foo end").foo.collect {|f| f.text}
335
- assert_equal ["foo","foo"], parser.parse("foo foo end").foo.collect {|f| f.text}
336
- assert_equal 5, parser.parse("foo foo foo foo foo end").foo.length
337
- end
338
-
339
326
  def test_poly_optional_delimiter
340
327
  parser=new_parser do
341
328
  rule :foo, many(";",match?(/ +/))
@@ -395,11 +382,11 @@ class BBTests < TestHelper
395
382
  def test_binary_operator_rule
396
383
  parser=new_parser do
397
384
  binary_operators_rule :bin_op, :int, ["**", [:/, :*], [:+, "-"]], :right_operators => ["**"] do
398
- def evaluate
385
+ def evaluate
399
386
  "(#{left.evaluate}#{operator}#{right.evaluate})"
400
387
  end
401
388
  end
402
-
389
+
403
390
  rule :int, /[-]?[0-9]+/ do
404
391
  def evaluate; to_s; end
405
392
  end
@@ -413,6 +400,14 @@ class BBTests < TestHelper
413
400
  assert_equal "(5**(6**7))", parser.parse("5**6**7").evaluate
414
401
  end
415
402
 
403
+ def test_dont_parser
404
+ parser = new_parser do
405
+ rule :option, dont.match(/msg.*/), /.*/
406
+ end
407
+ assert_nil parser.parse "msg test"
408
+ assert parser.parse "non test"
409
+ end
410
+
416
411
  def test_line_col
417
412
  assert_equal [1,1], "".line_col(0)
418
413
  assert_equal [1,1], " ".line_col(0)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: babel_bridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,10 +10,45 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
  date: 2010-11-28 00:00:00.000000000 Z
13
- dependencies: []
14
- description: ! "Babel Bridge is an object oriented parser generator for parsing expression
15
- grammars (PEG). \nGenerate memoizing packrat parsers 100% in Ruby code with a simple
16
- embedded DSL.\n"
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! 'Babel Bridge is an object oriented parser generator for parsing expression
47
+ grammars (PEG).
48
+
49
+ Generate memoizing packrat parsers 100% in Ruby code with a simple embedded DSL.
50
+
51
+ '
17
52
  email: shanebdavis@gmail.com
18
53
  executables: []
19
54
  extensions: []
@@ -23,11 +58,13 @@ files:
23
58
  - babel_bridge.gemspec
24
59
  - test/test_bb.rb
25
60
  - test/test_helper.rb
61
+ - spec/bb_spec.rb
26
62
  - lib/babel_bridge.rb
27
63
  - lib/nodes/empty_node.rb
28
64
  - lib/nodes/many_node.rb
29
65
  - lib/nodes/node.rb
30
66
  - lib/nodes/non_terminal_node.rb
67
+ - lib/nodes/rule_node.rb
31
68
  - lib/nodes/terminal_node.rb
32
69
  - lib/nodes.rb
33
70
  - lib/parser.rb
@@ -43,6 +80,7 @@ files:
43
80
  - examples/test.rb
44
81
  - examples/turing/examples.turing
45
82
  - examples/turing/notes.rb
83
+ - examples/turing/turing++.rb
46
84
  - examples/turing/turing.rb
47
85
  - examples/turing/turing00.rb
48
86
  - examples/turing/turing01.rb
@@ -83,3 +121,4 @@ signing_key:
83
121
  specification_version: 3
84
122
  summary: A Ruby-based parser-generator based on Parsing Expression Grammars.
85
123
  test_files: []
124
+ has_rdoc: false