rockit 0.7.1 → 0.7.2

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.
Files changed (73) hide show
  1. data/README +24 -160
  2. data/TODO +17 -17
  3. data/VERSION +1 -1
  4. data/doc/rockit_paper.pdf +0 -0
  5. data/lib/packrat/grammar.rb +139 -84
  6. data/rakefile +27 -9
  7. data/tests/acceptance/packrat/java/atest_java.rb +37 -0
  8. data/tests/acceptance/packrat/java/java.rb +136 -0
  9. data/tests/acceptance/packrat/java/t.rb +10 -0
  10. data/tests/acceptance/packrat/java/todo +10 -0
  11. data/tests/acceptance/packrat/java/xtc.lang.java/Java.rats +446 -0
  12. data/tests/acceptance/packrat/java/xtc.lang.java/JavaConstant.rats +111 -0
  13. data/tests/acceptance/packrat/java/xtc.lang.java/JavaCore.rats +508 -0
  14. data/tests/acceptance/packrat/java/xtc.lang.java/JavaIdentifier.rats +62 -0
  15. data/tests/acceptance/packrat/java/xtc.lang.java/JavaSymbol.rats +38 -0
  16. data/tests/acceptance/packrat/java/xtc.lang.java/JavaTree.rats +40 -0
  17. data/tests/acceptance/packrat/java/xtc.lang.java/JavaType.rats +61 -0
  18. data/tests/acceptance/packrat/java/xtc.lang.java/Spacing.rats +36 -0
  19. data/tests/acceptance/packrat/java/xtc.lang.java/Symbol.rats +77 -0
  20. data/tests/acceptance/packrat/minibasic/README +13 -0
  21. data/tests/acceptance/packrat/minibasic/atest_minibasic.rb +151 -13
  22. data/tests/acceptance/packrat/minibasic/minibasic.rb +94 -76
  23. data/tests/acceptance/packrat/minibasic/mult3.basic +6 -0
  24. data/tests/acceptance/packrat/minibasic/sumeven.basic +19 -0
  25. data/tests/unit/packrat/test_ast.rb +116 -0
  26. data/tests/unit/packrat/test_interpreting_parser.rb +15 -55
  27. metadata +22 -59
  28. data/lib/rockit/prettyprint/box.rb +0 -60
  29. data/lib/rockit/prettyprint/renderer.rb +0 -41
  30. data/lib/rockit/prettyprint/text_renderer.rb +0 -47
  31. data/lib/rockit/tree/base.rb +0 -223
  32. data/lib/rockit/tree/enter_leave_visitor.rb +0 -12
  33. data/lib/rockit/tree/graphviz.rb +0 -69
  34. data/lib/rockit/tree/visitor.rb +0 -12
  35. data/lib/util/array_alternatives.rb +0 -20
  36. data/lib/util/enter_leave_visitor.rb +0 -69
  37. data/lib/util/graphviz_dot.rb +0 -182
  38. data/lib/util/string_location.rb +0 -42
  39. data/lib/util/visitor.rb +0 -49
  40. data/lib/util/visitor_combinators.rb +0 -14
  41. data/tests/acceptance/rockit/dparser/atest_any_operator.rb +0 -33
  42. data/tests/acceptance/rockit/dparser/atest_arithmetic_grammar.rb +0 -30
  43. data/tests/acceptance/rockit/dparser/atest_list_operator.rb +0 -57
  44. data/tests/acceptance/rockit/dparser/atest_mult_operator.rb +0 -60
  45. data/tests/acceptance/rockit/dparser/atest_operator_grammar.rb +0 -61
  46. data/tests/acceptance/rockit/dparser/atest_plus_operator.rb +0 -55
  47. data/tests/acceptance/rockit/dparser/atest_samples_calculator.rb +0 -14
  48. data/tests/acceptance/rockit/dparser/atest_samples_minibasic.rb +0 -20
  49. data/tests/acceptance/rockit/dparser/atest_samples_multifunccalculator.rb +0 -36
  50. data/tests/acceptance/rockit/dparser/atest_simple_grammar.rb +0 -34
  51. data/tests/acceptance/rockit/dparser/atest_speculative_code_action.rb +0 -128
  52. data/tests/acceptance/rockit/dparser/calc_tests_common.rb +0 -103
  53. data/tests/unit/parse/utest_ebnf_grammar.rb +0 -50
  54. data/tests/unit/parse/utest_expand_grammar.rb +0 -23
  55. data/tests/unit/parse/utest_grammar.rb +0 -160
  56. data/tests/unit/rockit/assembler/llvm/utest_instructions.rb +0 -41
  57. data/tests/unit/rockit/assembler/llvm/utest_module.rb +0 -19
  58. data/tests/unit/rockit/prettyprint/utest_box.rb +0 -44
  59. data/tests/unit/rockit/tree/utest_tree_base.rb +0 -301
  60. data/tests/unit/rockit/tree/utest_tree_enter_leave_visitor.rb +0 -69
  61. data/tests/unit/rockit/tree/utest_tree_visitor.rb +0 -63
  62. data/tests/unit/rockit/utest_grammar.rb +0 -145
  63. data/tests/unit/rockit/utest_grammar_symbol.rb +0 -11
  64. data/tests/unit/rockit/utest_maybe_operator.rb +0 -12
  65. data/tests/unit/rockit/utest_regexp_terminal.rb +0 -45
  66. data/tests/unit/rockit/utest_repetition_operators.rb +0 -35
  67. data/tests/unit/rockit/utest_rule.rb +0 -23
  68. data/tests/unit/rockit/utest_string_terminal.rb +0 -40
  69. data/tests/unit/util/utest_array_alternatives.rb +0 -23
  70. data/tests/unit/util/utest_enter_leave_visitor.rb +0 -89
  71. data/tests/unit/util/utest_string_location.rb +0 -42
  72. data/tests/unit/util/utest_visitor.rb +0 -92
  73. data/tests/unit/util/utest_visitor_combinators.rb +0 -64
@@ -1,12 +0,0 @@
1
- require 'util/visitor'
2
- require 'rockit/tree/base'
3
-
4
- module Rockit::Tree
5
- class Base
6
- include Visitable
7
-
8
- def accept_visitor(visitor)
9
- visitor.visit_me_and_my_children(self, self.children)
10
- end
11
- end
12
- end
@@ -1,20 +0,0 @@
1
- # Collect alternatives to an array by pushing them onto an internal
2
- # instance variable @__alternatives. We can then assemble all the alternatives
3
- # (including self) into an Array. This is used for specifying alternative
4
- # RightHandSides in a Rule in a Grammar.
5
- class Array
6
- def __alternatives
7
- @__alternatives ||= Array.new
8
- end
9
-
10
- def /(other)
11
- self.__alternatives << other
12
- self
13
- end
14
-
15
- def assemble_alternatives
16
- alternatives = self.__alternatives
17
- alternatives.unshift self
18
- alternatives
19
- end
20
- end
@@ -1,69 +0,0 @@
1
- require 'util/visitor'
2
-
3
- # An EnterLeaveVisitor is a Visitor that visits objects both on the way down
4
- # and on the way up when traversing an object structure/hierarchy.
5
- # It will first call enter_X(x) if available, then visit_X(x) if avilable
6
- # then traverse down into children objects and then call leave_X(x) if
7
- # available.
8
- # Objects use visit_all to indicate structure. The first argument to visit_all
9
- # is a parent object and the rest are children objects.
10
- # NOTE! If they simply call visit the leave method will never be called but
11
- # the enter and visit methods will.
12
- module EnterLeaveVisitor
13
- include Visitor
14
-
15
- def visit(obj)
16
- visit_me_then_children(obj)
17
- end
18
-
19
- def enter(obj)
20
- method = _enter_method(obj)
21
- self.send(method, obj) if method
22
- end
23
-
24
- def leave(obj)
25
- method = _leave_method(obj)
26
- self.send(method, obj) if method
27
- end
28
-
29
- # Each children should be an array with children
30
- def visit_me_then_children(parent, *children)
31
- enter_method, visit_method, leave_method = _evl_methods(parent)
32
- self.send(enter_method, parent) if enter_method
33
- self.send(visit_method, parent) if visit_method
34
- children.each {|cs| cs.each {|c| c.accept_visitor(self)}}
35
- self.send(leave_method, parent) if leave_method
36
- end
37
-
38
- def _evl_methods(obj)
39
- obj.class.ancestors.map {|c| _evl_methods_for_class(c)}.compact.first
40
- end
41
-
42
- def _evl_methods_for_class(klass)
43
- # Memoized so not dynamic, maybe we should clear cache when a method is
44
- # added?
45
- (@_memoized_methods ||= Hash.new)[klass] ||= _methodnames_from_class(klass)
46
- end
47
-
48
- def _methodname_from_classname(klassName, prefix)
49
- name = prefix + klassName
50
- self.class.instance_methods.include?(name) ? name : nil
51
- end
52
-
53
- def _methodnames_from_class(klass)
54
- class_name = klass.inspect.split("::").last
55
- l = ["enter_", "visit_", "leave_"].map do |prefix|
56
- _methodname_from_classname(class_name, prefix)
57
- end
58
- # Return nil unless we found at least one method to visit
59
- (l.compact.length > 0) ? l : nil
60
- end
61
- end
62
-
63
- module EnterLeaveVisitable
64
- include Visitable
65
- end
66
-
67
- class Object
68
- include EnterLeaveVisitable
69
- end
@@ -1,182 +0,0 @@
1
- class DotGraphPrinter
2
- attr_accessor :orientation, :size, :color
3
-
4
- # The following can be set to blocks of code that gives a default
5
- # value for the node shapes, node labels and link labels, respectively.
6
- attr_accessor :node_shaper, :node_labeler, :link_labeler
7
-
8
- # A node shaper maps each node to a string describing its shape.
9
- # Valid shapes are:
10
- # "ellipse" (default)
11
- # "box"
12
- # "circle"
13
- # "plaintext" (no outline)
14
- # "doublecircle"
15
- # "diamond"
16
- # Not yet supported or untested once are:
17
- # "polygon", "record", "epsf"
18
- @@default_node_shaper = proc{|n| "box"}
19
-
20
- @@default_node_labeler = proc{|n|
21
- if Symbol===n
22
- n.id2name
23
- elsif String===n
24
- n
25
- else
26
- n.inspect
27
- end
28
- }
29
-
30
- @@default_link_labeler = proc{|info| info ? info.inspect : nil}
31
-
32
- # links is either array of
33
- # arrays [fromNode, toNode [, infoOnLink]], or
34
- # objects with attributes :from, :to, :info
35
- # nodes is array of node objects
36
- # All nodes used in the links are used as nodes even if they are not
37
- # in the "nodes" parameters.
38
- def initialize(links = [], nodes = [])
39
- @links, @nodes = links, add_nodes_in_links(links, nodes)
40
- @node_attributes, @edge_attributes = Hash.new, Hash.new
41
- set_default_values
42
- end
43
-
44
- def set_default_values
45
- @color = "black"
46
- @size = "9,11"
47
- @orientation = "portrait"
48
- @node_shaper = @@default_node_shaper
49
- @node_labeler = @@default_node_labeler
50
- @link_labeler = @@default_link_labeler
51
- end
52
-
53
- def write_to_file(filename, fileType = "ps")
54
- dotfile = temp_filename(filename)
55
- File.open(dotfile, "w") {|f| f.write to_dot_specification}
56
- system "dot -T#{fileType} -o #{filename} #{dotfile}"
57
- File.delete(dotfile)
58
- end
59
-
60
- def set_edge_attributes(anEdge, aHash)
61
- # TODO check if attributes are valid dot edge attributes
62
- edge = find_edge(anEdge)
63
- set_attributes(edge, @edge_attributes, true, aHash)
64
- end
65
-
66
- def set_node_attributes(aNode, aHash)
67
- # TODO check if attributes are valid dot node attributes
68
- set_attributes(aNode, @node_attributes, true, aHash)
69
- end
70
-
71
- def to_dot_specification
72
- set_edge_labels(@links)
73
- set_node_labels_and_shape(@nodes)
74
- "digraph G {\n" +
75
- graph_parameters_to_dot_specification +
76
- @nodes.uniq.map {|n| format_node(n)}.join(";\n") + ";\n" +
77
- @links.uniq.map {|l| format_link(l)}.join(";\n") + ";\n" +
78
- "}"
79
- end
80
-
81
- protected
82
-
83
- def find_edge(anEdge)
84
- @links.each do |link|
85
- return link if source_and_dest(link) == source_and_dest(anEdge)
86
- end
87
- end
88
-
89
- def set_attributes(key, hash, override, newAttributeHash)
90
- h = hash[key] || Hash.new
91
- newAttributeHash = all_keys_to_s(newAttributeHash)
92
- newAttributeHash.each do |k, value|
93
- h[k] = value unless h[k] and !override
94
- end
95
- hash[key] = h
96
- end
97
-
98
- def graph_parameters_to_dot_specification
99
- "graph [\n" +
100
- (self.size ? " size = #{@size.inspect},\n" : "") +
101
- (self.orientation ? " orientation = #{@orientation},\n" : "") +
102
- (self.color ? " color = #{@color}\n" : "") +
103
- "]\n"
104
- end
105
-
106
- def each_node_in_links(links)
107
- links.each do |l|
108
- src, dest = source_and_dest(l)
109
- yield src
110
- yield dest
111
- end
112
- end
113
-
114
- def add_nodes_in_links(links, nodes)
115
- new_nodes = []
116
- each_node_in_links(links) {|node| new_nodes.push node}
117
- (nodes + new_nodes).uniq
118
- end
119
-
120
- def all_keys_to_s(aHash)
121
- # MAYBE reuse existing hash?
122
- Hash[*(aHash.map{|p| p[0] = p[0].to_s; p}.flatten)]
123
- end
124
-
125
- def set_edge_labels(edges)
126
- edges.each do |edge|
127
- src, dest, info = get_link_data(edge)
128
- if info
129
- label = @link_labeler.call(info)
130
- set_attributes(edge, @edge_attributes, false, :label =>label) if label
131
- end
132
- end
133
- end
134
-
135
- def set_node_labels_and_shape(nodes)
136
- nodes.each do |node|
137
- set_attributes(node, @node_attributes, false,
138
- :label => @node_labeler.call(node).inspect,
139
- :shape => @node_shaper.call(node).inspect)
140
- end
141
- end
142
-
143
- def get_link_data(link)
144
- begin
145
- return link.from, link.to, link.info
146
- rescue Exception
147
- return link[0], link[1], link[2]
148
- end
149
- end
150
-
151
- def source_and_dest(link)
152
- get_link_data(link)[0,2]
153
- end
154
-
155
- def format_attributes(attributes)
156
- return "" unless attributes
157
- strings = attributes.map {|a, v| "#{a}=#{v}"}
158
- strings.length > 0 ? (" [" + strings.join(", ") + "]") : ("")
159
- end
160
-
161
- def mangle_node_name(node)
162
- "n" + node.hash.abs.inspect
163
- end
164
-
165
- def format_link(link)
166
- from, to, info = get_link_data(link)
167
- mangle_node_name(from) + " -> " + mangle_node_name(to) +
168
- format_attributes(@edge_attributes[link])
169
- end
170
-
171
- def format_node(node)
172
- mangle_node_name(node) + format_attributes(@node_attributes[node])
173
- end
174
-
175
- def temp_filename(base = "tmp")
176
- tmpfile = base + rand(100000).inspect
177
- while test(?f, tmpfile)
178
- tmpfile = base + rand(100000).inspect
179
- end
180
- tmpfile
181
- end
182
- end
@@ -1,42 +0,0 @@
1
- # A class for calculating locations (line, column) in a string based
2
- # on an offset.
3
- class StringLocations
4
- def initialize(string)
5
- @string, @string_length = string, string.length
6
- @line_lengths = @string.split(/\n/).map {|l| l.length}
7
- @start_pos_of_line = [0]
8
- @line_lengths.each do |l|
9
- @start_pos_of_line << @start_pos_of_line.last + l + 1
10
- end
11
- end
12
-
13
- def location(offset)
14
- l = line(offset)
15
- return l, column(offset, l)
16
- end
17
-
18
- def column(offset, l = nil)
19
- l ||= line(offset)
20
- offset - @start_pos_of_line[l-1]
21
- end
22
-
23
- def line(offset)
24
- if offset >= @string_length
25
- raise "#{offset} is larger than the string size #{@string_length}"
26
- end
27
- line_index(offset) + 1
28
- end
29
-
30
- # Find the index to the line where the given offset can be found. Assumes
31
- # the start_pos_of_line array has been extended so that offset is covered.
32
- def line_index(offset)
33
- index = nil
34
- for index in (0...(@start_pos_of_line.length))
35
- if @start_pos_of_line[index] <= offset &&
36
- @start_pos_of_line[index+1] > offset
37
- break
38
- end
39
- end
40
- index
41
- end
42
- end
@@ -1,49 +0,0 @@
1
- module Visitor
2
- def visit(obj)
3
- method = _visitor_method(obj)
4
- self.send(method, obj) if method
5
- end
6
-
7
- def visit_me_and_my_children(me, children)
8
- visit(me)
9
- children.each {|c| c.accept_visitor(self)}
10
- end
11
-
12
- def visit_me_then_children(obj, *children)
13
- visit(obj)
14
- children.each {|cs| cs.each {|c| c.accept_visitor(self)}}
15
- end
16
-
17
- # Find the visit_X method to use based on the inheritance tree. First try
18
- # the class name then traverse the ancestors list.
19
- def _visitor_method(obj)
20
- obj.class.ancestors.map {|c| _visitor_method_for_class(c)}.compact.first
21
- end
22
-
23
- def _visitor_method_for_class(klass)
24
- _visitor_methods[klass] ||= _methodname_from_class(klass)
25
- end
26
-
27
- def _visitor_methods
28
- @_visitor_methods ||= Hash.new
29
- end
30
-
31
- def _methodname_from_class(klass)
32
- name = "visit_" + klass.inspect.split("::").last
33
- self.class.instance_methods.include?(name) ? name : nil
34
- end
35
-
36
- def visit_each(ary)
37
- ary.each {|e| e.accept_visitor(self)}
38
- end
39
- end
40
-
41
- module Visitable
42
- def accept_visitor(visitor)
43
- visitor.visit(self)
44
- end
45
- end
46
-
47
- class Object
48
- include Visitable
49
- end
@@ -1,14 +0,0 @@
1
- require 'util/visitor'
2
-
3
- # Sequentially apply visitors
4
- class SequenceVisitor
5
- include Visitor
6
-
7
- def initialize(*visitors)
8
- @visitors = visitors
9
- end
10
-
11
- def visit(obj)
12
- @visitors.each {|v| obj.accept_visitor(v)}
13
- end
14
- end
@@ -1,33 +0,0 @@
1
- require 'test/unit'
2
- require 'rockit/dparser'
3
-
4
- class ATestAnyOperator < Test::Unit::TestCase
5
- AnyTestGrammar = Rockit::DParser::Grammar.new do
6
- start :S, [["a", any("b", "c"), any(:D, :E), ast(:S, 0, 1, 2)]]
7
- ("d".."e").map {|s| term(s.upcase.intern, s)}
8
- end
9
-
10
- Parser = AnyTestGrammar.new_parser
11
-
12
- def test_01
13
- ast = Parser.parse "abd"
14
- assert_equal("a", ast[0])
15
- assert_equal("b", ast[1])
16
- assert_equal("d", ast[2])
17
-
18
- ast = Parser.parse "abe"
19
- assert_equal("a", ast[0])
20
- assert_equal("b", ast[1])
21
- assert_equal("e", ast[2])
22
-
23
- ast = Parser.parse "acd"
24
- assert_equal("a", ast[0])
25
- assert_equal("c", ast[1])
26
- assert_equal("d", ast[2])
27
-
28
- ast = Parser.parse "ace"
29
- assert_equal("a", ast[0])
30
- assert_equal("c", ast[1])
31
- assert_equal("e", ast[2])
32
- end
33
- end
@@ -1,30 +0,0 @@
1
- require 'test/unit'
2
- require 'rockit/dparser'
3
-
4
- class ATestArithmeticGrammar < Test::Unit::TestCase
5
- ArithmeticTestGrammar = Rockit::DParser::Grammar.new do
6
- start :Expr, [
7
- [:Digit, "+", :Digit, ast(:Add, 0, 2)],
8
- [:Digit, "*", :Digit, ast(:Mult, 0, 2)],
9
- ]
10
- term :Digit, /[0-9]+/
11
- end
12
-
13
- def test_03_use_parser
14
- parser = ArithmeticTestGrammar.new_parser
15
-
16
- ast = parser.parse "12+34"
17
- assert_equal("Add", ast.name)
18
- assert_kind_of(parser.astclass_of_name(:Add), ast)
19
- assert_equal(2, ast.num_children)
20
- assert_equal("12", ast[0])
21
- assert_equal("34", ast[1])
22
-
23
- ast = parser.parse "567*980"
24
- assert_equal("Mult", ast.name)
25
- assert_kind_of(parser.astclass_of_name(:Mult), ast)
26
- assert_equal(2, ast.num_children)
27
- assert_equal("567", ast[0])
28
- assert_equal("980", ast[1])
29
- end
30
- end