koi-reference-parser 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -0
- data/VERSION +1 -1
- data/lib/parser/koi-reference-parser.treetop +58 -45
- data/lib/parser/parser.rb +2 -17
- data/lib/parser/syntax_nodes.rb +0 -9
- data/test/{parser/functional → functional}/function_call_as_argument.rb +1 -1
- data/test/{parser/functional → functional}/simple_program_test.rb +1 -1
- data/test/helpers/assert_assigns.rb +9 -0
- data/test/helpers/assert_assigns_expression.rb +10 -0
- data/test/helpers/assert_expression.rb +11 -0
- data/test/helpers/assert_identifier.rb +6 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/assignment/assignment_of_hash_value_test.rb +19 -0
- data/test/{parser/unit/hash_accessor_test.rb → unit/assignment/assignment_to_hash_test.rb} +2 -14
- data/test/unit/assignment/boolean_assignment_test.rb +17 -0
- data/test/unit/assignment/float_assignment_test.rb +22 -0
- data/test/unit/assignment/function_call_assignment_test.rb +12 -0
- data/test/unit/assignment/function_definition_test.rb +12 -0
- data/test/unit/assignment/hash_literal_assignment_test.rb +27 -0
- data/test/unit/assignment/integer_assignment_test.rb +22 -0
- data/test/unit/assignment/nil_assignment_test.rb +12 -0
- data/test/unit/assignment/string_assignment_test.rb +17 -0
- data/test/unit/expressions/addition_expression_test.rb +27 -0
- data/test/{parser/unit → unit/expressions}/compound_expression_test.rb +0 -0
- data/test/unit/expressions/division_expression_test.rb +27 -0
- data/test/unit/expressions/equality_expression_test.rb +27 -0
- data/test/unit/expressions/greater_than_expression_test.rb +27 -0
- data/test/unit/expressions/inequality_expression_test.rb +27 -0
- data/test/unit/expressions/less_than_expression_test.rb +27 -0
- data/test/unit/expressions/multiplication_expression_test.rb +27 -0
- data/test/unit/expressions/subtraction_expression_test.rb +27 -0
- data/test/{parser/unit → unit/flow_control}/if_test.rb +0 -0
- data/test/{parser/unit → unit/flow_control}/unless_test.rb +0 -0
- data/test/{parser/unit → unit/functions}/function_call_test.rb +0 -0
- data/test/{parser/unit → unit/functions}/function_definition_test.rb +0 -0
- data/test/unit/identifier_test.rb +37 -0
- data/test/{parser/unit → unit}/statement_test.rb +1 -1
- data/test/{parser/unit → unit}/syntax_node_to_hash_test.rb +1 -1
- metadata +67 -29
- data/test/parser/unit/assignment_test.rb +0 -115
- data/test/parser/unit/identifier_test.rb +0 -55
- data/test/parser/unit/simple_expression_test.rb +0 -212
data/README.rdoc
CHANGED
@@ -21,6 +21,7 @@ And turns it into an {Abstract Syntax Tree (AST)}[http://en.wikipedia.org/wiki/A
|
|
21
21
|
<AdditionOperator "+">
|
22
22
|
<IntegerLiteral "2">
|
23
23
|
|
24
|
+
The AST is also available in a far more portable format based on nested hashes by calling the to_hash method on the root AST node.
|
24
25
|
|
25
26
|
=== Installation
|
26
27
|
|
@@ -36,6 +37,9 @@ This parser is normally installed as part of Koi's default toolchain. However if
|
|
36
37
|
include KoiReferenceParser
|
37
38
|
|
38
39
|
ast = Parser.parse( program_text )
|
40
|
+
|
41
|
+
# Get the AST as a portable nested hash
|
42
|
+
ast_hash = ast.to_hash
|
39
43
|
|
40
44
|
=== Author & Credits
|
41
45
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
@@ -1,5 +1,14 @@
|
|
1
|
+
# This file is a Parsing Expression Grammar (PEG) for the Koi
|
2
|
+
# programming language. It is interpreted by the PEG engine Treetop.
|
3
|
+
|
4
|
+
# More info on PEGs: http://en.wikipedia.org/wiki/Parsing_expression_grammar
|
5
|
+
# More info on Treetop: http://treetop.rubyforge.org/
|
6
|
+
|
1
7
|
grammar KoiReferenceParser
|
2
8
|
|
9
|
+
##################
|
10
|
+
# Program structure
|
11
|
+
|
3
12
|
rule block
|
4
13
|
statement+ <Block>
|
5
14
|
end
|
@@ -8,6 +17,9 @@ grammar KoiReferenceParser
|
|
8
17
|
space? ( hash_assignment / assignment / if / unless / function_call ) ';'? space? <Statement>
|
9
18
|
end
|
10
19
|
|
20
|
+
##################
|
21
|
+
# Literals
|
22
|
+
|
11
23
|
rule nil
|
12
24
|
"nil" <NilLiteral>
|
13
25
|
end
|
@@ -36,6 +48,24 @@ grammar KoiReferenceParser
|
|
36
48
|
'$'? [a-zA-Z] [a-zA-Z0-9_]* <Identifier>
|
37
49
|
end
|
38
50
|
|
51
|
+
##################
|
52
|
+
# Hash literals
|
53
|
+
|
54
|
+
rule hash
|
55
|
+
'{' key_value_list? '}' <HashLiteral>
|
56
|
+
end
|
57
|
+
|
58
|
+
rule key_value_list
|
59
|
+
key_value+ <KeyValueList>
|
60
|
+
end
|
61
|
+
|
62
|
+
rule key_value
|
63
|
+
space? expression space? '=>' space? expression space? ','? <KeyValue>
|
64
|
+
end
|
65
|
+
|
66
|
+
##################
|
67
|
+
# Assignment
|
68
|
+
|
39
69
|
rule hash_assignment
|
40
70
|
identifier hash_accessor_list space? assignment_operator space? ( hash / function_definition / expression ) <HashAssignment>
|
41
71
|
end
|
@@ -70,18 +100,15 @@ grammar KoiReferenceParser
|
|
70
100
|
'function(' space? identifier space? ')'
|
71
101
|
block
|
72
102
|
space? 'end' <FunctionDefinition>
|
73
|
-
end
|
74
|
-
|
103
|
+
end
|
104
|
+
|
75
105
|
##################
|
76
|
-
#
|
106
|
+
# Hash component access
|
77
107
|
|
78
|
-
rule
|
79
|
-
|
108
|
+
rule hash_access
|
109
|
+
identifier hash_accessor_list <HashAccess>
|
80
110
|
end
|
81
111
|
|
82
|
-
##################
|
83
|
-
# Hashes
|
84
|
-
|
85
112
|
rule hash_accessor_list
|
86
113
|
hash_accessor+ <HashAccessorList>
|
87
114
|
end
|
@@ -89,26 +116,6 @@ grammar KoiReferenceParser
|
|
89
116
|
rule hash_accessor
|
90
117
|
'[' expression ']' <HashAccessor>
|
91
118
|
end
|
92
|
-
|
93
|
-
rule hash
|
94
|
-
'{' key_value_list? '}' <HashLiteral>
|
95
|
-
end
|
96
|
-
|
97
|
-
rule key_value_list
|
98
|
-
key_value+ <KeyValueList>
|
99
|
-
end
|
100
|
-
|
101
|
-
rule key_value
|
102
|
-
space? expression space? '=>' space? expression space? ','? <KeyValue>
|
103
|
-
end
|
104
|
-
|
105
|
-
rule key
|
106
|
-
space? expression space? <Key>
|
107
|
-
end
|
108
|
-
|
109
|
-
rule value
|
110
|
-
space? expression space? <Value>
|
111
|
-
end
|
112
119
|
|
113
120
|
##################
|
114
121
|
# Expressions
|
@@ -117,12 +124,8 @@ grammar KoiReferenceParser
|
|
117
124
|
space? (hash_access / comparative / additive) <Expression>
|
118
125
|
end
|
119
126
|
|
120
|
-
rule hash_access
|
121
|
-
identifier hash_accessor_list <HashAccess>
|
122
|
-
end
|
123
|
-
|
124
127
|
rule comparative
|
125
|
-
additive space?
|
128
|
+
additive space? comparative_operator space? additive <ComparativeExpression>
|
126
129
|
end
|
127
130
|
|
128
131
|
rule additive
|
@@ -130,12 +133,6 @@ grammar KoiReferenceParser
|
|
130
133
|
/
|
131
134
|
multitive
|
132
135
|
end
|
133
|
-
|
134
|
-
rule additive_operator
|
135
|
-
addition_operator
|
136
|
-
/
|
137
|
-
subtraction_operator
|
138
|
-
end
|
139
136
|
|
140
137
|
rule multitive
|
141
138
|
primary space? multitive_operator space? multitive <MultitiveExpression>
|
@@ -143,17 +140,26 @@ grammar KoiReferenceParser
|
|
143
140
|
primary
|
144
141
|
end
|
145
142
|
|
146
|
-
rule multitive_operator
|
147
|
-
multiplication_operator
|
148
|
-
/
|
149
|
-
division_operator
|
150
|
-
end
|
151
|
-
|
152
143
|
rule primary
|
153
144
|
function_call / nil / false / true / identifier / float / integer / string
|
154
145
|
/
|
155
146
|
'(' space? expression space? ')' <Expression>
|
156
147
|
end
|
148
|
+
|
149
|
+
##################
|
150
|
+
# Operator sets
|
151
|
+
|
152
|
+
rule comparative_operator
|
153
|
+
equality_operator / inequality_operator / greater_than_operator / less_than_operator
|
154
|
+
end
|
155
|
+
|
156
|
+
rule additive_operator
|
157
|
+
addition_operator / subtraction_operator
|
158
|
+
end
|
159
|
+
|
160
|
+
rule multitive_operator
|
161
|
+
multiplication_operator / division_operator
|
162
|
+
end
|
157
163
|
|
158
164
|
##################
|
159
165
|
# Operators
|
@@ -193,5 +199,12 @@ grammar KoiReferenceParser
|
|
193
199
|
rule less_than_operator
|
194
200
|
'<' <LessThanOperator>
|
195
201
|
end
|
202
|
+
|
203
|
+
##################
|
204
|
+
# Whitespace
|
205
|
+
|
206
|
+
rule space
|
207
|
+
[\s]+
|
208
|
+
end
|
196
209
|
|
197
210
|
end
|
data/lib/parser/parser.rb
CHANGED
@@ -8,21 +8,12 @@ class Parser
|
|
8
8
|
tree = @@parser.parse(data)
|
9
9
|
|
10
10
|
if(tree.nil?)
|
11
|
-
|
12
|
-
error_detail = "\n\n" + data.slice(@@parser.index - 120, 80).gsub("\n", ";")
|
13
|
-
error_detail += "\n" + data.slice(@@parser.index - 40, 80).gsub("\n", ";")
|
14
|
-
error_detail += "\n" + " "*40 + "^\n"
|
15
|
-
else
|
16
|
-
error_detail = "\n\n" + data.gsub("\n", ";")
|
17
|
-
error_detail += "\n" + " " * @@parser.index + "^\n"
|
18
|
-
end
|
19
|
-
raise ParseError, "Parse error at index: #{@@parser.index}#{error_detail}"
|
11
|
+
raise ParseError, "Parse error at offset: #{@@parser.index}"
|
20
12
|
end
|
21
13
|
|
22
14
|
# clean up the tree by removing all nodes of default type 'SyntaxNode'
|
23
15
|
self.clean_tree(tree)
|
24
|
-
|
25
|
-
self.clean_whitespace(tree)
|
16
|
+
|
26
17
|
return tree
|
27
18
|
end
|
28
19
|
|
@@ -33,11 +24,5 @@ class Parser
|
|
33
24
|
root_node.elements.delete_if{|node| node.class.name == "Treetop::Runtime::SyntaxNode" }
|
34
25
|
root_node.elements.each {|node| self.clean_tree(node) }
|
35
26
|
end
|
36
|
-
|
37
|
-
def self.clean_whitespace(root_node)
|
38
|
-
return if(root_node.elements.nil?)
|
39
|
-
root_node.elements.delete_if{|node| node.class.name == "KoiReferenceParser::Whitespace" }
|
40
|
-
root_node.elements.each {|node| self.clean_whitespace(node) }
|
41
|
-
end
|
42
27
|
|
43
28
|
end
|
data/lib/parser/syntax_nodes.rb
CHANGED
@@ -57,18 +57,9 @@ module KoiReferenceParser
|
|
57
57
|
class KeyValue < Treetop::Runtime::SyntaxNode
|
58
58
|
end
|
59
59
|
|
60
|
-
class Key < Treetop::Runtime::SyntaxNode
|
61
|
-
end
|
62
|
-
|
63
|
-
class Value < Treetop::Runtime::SyntaxNode
|
64
|
-
end
|
65
|
-
|
66
60
|
class Identifier < Treetop::Runtime::SyntaxNode
|
67
61
|
end
|
68
62
|
|
69
|
-
class Whitespace < Treetop::Runtime::SyntaxNode
|
70
|
-
end
|
71
|
-
|
72
63
|
class AssignmentOperator < Treetop::Runtime::SyntaxNode
|
73
64
|
end
|
74
65
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
def assert_assigns(node_type, value, tree)
|
2
|
+
assert_kind_of Block, tree
|
3
|
+
assert_kind_of Statement, tree.elements.last
|
4
|
+
assert_kind_of Assignment, tree.elements.last.elements.last
|
5
|
+
assert_kind_of Identifier, tree.elements.last.elements.last.elements[0]
|
6
|
+
assert_kind_of AssignmentOperator, tree.elements.last.elements.last.elements[1]
|
7
|
+
assert_kind_of node_type, tree.elements.last.elements.last.elements[2]
|
8
|
+
assert_equal value, tree.elements.last.elements.last.elements[2].text_value unless(value.nil?)
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
def assert_assigns_expression(node_type, value, tree)
|
2
|
+
assert_kind_of Block, tree
|
3
|
+
assert_kind_of Statement, tree.elements.last
|
4
|
+
assert_kind_of Assignment, tree.elements.last.elements.last
|
5
|
+
assert_kind_of Identifier, tree.elements.last.elements.last.elements[0]
|
6
|
+
assert_kind_of AssignmentOperator, tree.elements.last.elements.last.elements[1]
|
7
|
+
assert_kind_of Expression, tree.elements.last.elements.last.elements[2]
|
8
|
+
assert_kind_of node_type, tree.elements.last.elements.last.elements[2].elements.first
|
9
|
+
assert_equal value, tree.elements.last.elements.last.elements[2].elements.first.text_value unless(value.nil?)
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
def assert_expression(tree, expression_type, operator)
|
2
|
+
assert_kind_of Block, tree
|
3
|
+
assert_kind_of Statement, tree.elements.first
|
4
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
5
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
6
|
+
assert_kind_of AssignmentOperator, tree.elements.first.elements.last.elements[1]
|
7
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
8
|
+
assert_kind_of expression_type, tree.elements.first.elements.last.elements[2].elements.first
|
9
|
+
assert_equal 3, tree.elements.first.elements.last.elements[2].elements.first.elements.size
|
10
|
+
assert_kind_of operator, tree.elements.first.elements.last.elements[2].elements.first.elements[1] unless(operator.nil?)
|
11
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -4,6 +4,7 @@ require 'test/unit'
|
|
4
4
|
require_files = []
|
5
5
|
require_files << File.join(File.dirname(__FILE__), '..', 'lib', 'koi-reference-parser.rb')
|
6
6
|
require_files.concat Dir[File.join(File.dirname(__FILE__), 'setup', '*.rb')]
|
7
|
+
require_files.concat Dir[File.join(File.dirname(__FILE__), 'helpers', '*.rb')]
|
7
8
|
|
8
9
|
require_files.each do |file|
|
9
10
|
require File.expand_path(file)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class AssignmentOfHashValueTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of hash key" do
|
8
|
+
tree = Parser.parse('test = test[1]')
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of Assignment, tree.elements.first.elements.first
|
12
|
+
assert_kind_of Identifier, tree.elements.first.elements.first.elements[0]
|
13
|
+
assert_kind_of Expression, tree.elements.first.elements.first.elements[2]
|
14
|
+
assert_kind_of HashAccess, tree.elements.first.elements.first.elements[2].elements.first
|
15
|
+
assert_kind_of Identifier, tree.elements.first.elements.first.elements[2].elements.first.elements[0]
|
16
|
+
assert_kind_of HashAccessorList, tree.elements.first.elements.first.elements[2].elements.first.elements[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
2
|
|
3
|
-
class
|
3
|
+
class AssignmentToHashTest < Test::Unit::TestCase
|
4
4
|
|
5
5
|
include KoiReferenceParser
|
6
|
-
|
6
|
+
|
7
7
|
test "assignment to hash key" do
|
8
8
|
tree = Parser.parse('test[1] = 1')
|
9
9
|
assert_kind_of Block, tree
|
@@ -25,17 +25,5 @@ class HashAccessorTest < Test::Unit::TestCase
|
|
25
25
|
assert_kind_of HashAccessor, tree.elements.first.elements.first.elements[1].elements.first
|
26
26
|
assert_equal 3, tree.elements.first.elements.first.elements[1].elements.length
|
27
27
|
end
|
28
|
-
|
29
|
-
test "assignment of hash key" do
|
30
|
-
tree = Parser.parse('test = test[1]')
|
31
|
-
assert_kind_of Block, tree
|
32
|
-
assert_kind_of Statement, tree.elements.first
|
33
|
-
assert_kind_of Assignment, tree.elements.first.elements.first
|
34
|
-
assert_kind_of Identifier, tree.elements.first.elements.first.elements[0]
|
35
|
-
assert_kind_of Expression, tree.elements.first.elements.first.elements[2]
|
36
|
-
assert_kind_of HashAccess, tree.elements.first.elements.first.elements[2].elements.first
|
37
|
-
assert_kind_of Identifier, tree.elements.first.elements.first.elements[2].elements.first.elements[0]
|
38
|
-
assert_kind_of HashAccessorList, tree.elements.first.elements.first.elements[2].elements.first.elements[1]
|
39
|
-
end
|
40
28
|
|
41
29
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class BooleanAssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of boolean true" do
|
8
|
+
tree = Parser.parse('test = true')
|
9
|
+
assert_assigns_expression(TrueLiteral, nil, tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "assignment of boolean false" do
|
13
|
+
tree = Parser.parse('test = false')
|
14
|
+
assert_assigns_expression(FalseLiteral, nil, tree)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FloatAssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of float" do
|
8
|
+
tree = Parser.parse('test = 99.0009')
|
9
|
+
assert_assigns_expression(FloatLiteral, '99.0009', tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "assignment of explicitly positive float" do
|
13
|
+
tree = Parser.parse('test = +99.0009')
|
14
|
+
assert_assigns_expression(FloatLiteral, '+99.0009', tree)
|
15
|
+
end
|
16
|
+
|
17
|
+
test "assignment of explicitly negative float" do
|
18
|
+
tree = Parser.parse('test = -99.0009')
|
19
|
+
assert_assigns_expression(FloatLiteral, '-99.0009', tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionCallAssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of result of function call" do
|
8
|
+
tree = Parser.parse('test = function(args)')
|
9
|
+
assert_assigns_expression(FunctionCall, nil, tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionDefinitionAssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of function definition" do
|
8
|
+
tree = Parser.parse('test = function(args) blah = 1 end')
|
9
|
+
assert_assigns(FunctionDefinition, nil, tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class HashLiteralAssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of empty hash literal" do
|
8
|
+
tree = Parser.parse('test = {}')
|
9
|
+
assert_assigns(HashLiteral, nil, tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "assignment of hash literal with single key-value pair" do
|
13
|
+
tree = Parser.parse('test = { 1 => 2 }')
|
14
|
+
assert_assigns(HashLiteral, nil, tree)
|
15
|
+
end
|
16
|
+
|
17
|
+
test "assignment of hash literal with 2 key-value pairs" do
|
18
|
+
tree = Parser.parse('test = { 1 => 2, 2 => 2 }')
|
19
|
+
assert_assigns(HashLiteral, nil, tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
test "assignment of hash literal with 3 key-value pairs" do
|
23
|
+
tree = Parser.parse('test = { 1 => 2, 2 => 2, 3 => 2 }')
|
24
|
+
assert_assigns(HashLiteral, nil, tree)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|