rockit 0.7.1 → 0.7.2

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