babel_bridge 0.3.1 → 0.4.0

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