koi-reference-parser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +44 -0
- data/Rakefile +43 -0
- data/lib/koi-reference-parser.rb +8 -0
- data/lib/parser/exceptions.rb +2 -0
- data/lib/parser/koi-reference-parser.treetop +197 -0
- data/lib/parser/parser.rb +43 -0
- data/lib/parser/syntax_nodes.rb +114 -0
- data/test/parser/functional/function_call_as_argument.rb +17 -0
- data/test/parser/functional/simple_program_test.rb +35 -0
- data/test/parser/unit/assignment_test.rb +115 -0
- data/test/parser/unit/compound_expression_test.rb +35 -0
- data/test/parser/unit/function_call_test.rb +52 -0
- data/test/parser/unit/function_definition_test.rb +19 -0
- data/test/parser/unit/hash_accessor_test.rb +41 -0
- data/test/parser/unit/identifier_test.rb +55 -0
- data/test/parser/unit/if_test.rb +25 -0
- data/test/parser/unit/simple_expression_test.rb +212 -0
- data/test/parser/unit/statement_test.rb +22 -0
- data/test/parser/unit/unless_test.rb +25 -0
- data/test/setup/test_unit_extensions.rb +21 -0
- data/test/test_helper.rb +10 -0
- metadata +111 -0
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Aaron Gough (http://thingsaaronmade.com/)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
= koi-reference-parser
|
2
|
+
|
3
|
+
This is the reference parser implementation for the programming language {Koi}[http://github.com/aarongough/koi]. The parser is implemented using a {Parsing Expression Grammar (PEG)}[http://en.wikipedia.org/wiki/Parsing_expression_grammar] that is run by a PEG engine called {Treetop}[http://treetop.rubyforge.org/].
|
4
|
+
|
5
|
+
=== Example
|
6
|
+
|
7
|
+
The parser takes a text string containing a program like:
|
8
|
+
|
9
|
+
test = 1 + 2
|
10
|
+
|
11
|
+
And turns it into an {Abstract Syntax Tree (AST)}[http://en.wikipedia.org/wiki/Abstract_syntax_tree] that unambiguously represents the program's structure and meaning. The AST is represented as a series of Ruby objects that subclass a generic SyntaxNode class. The code above transformed into AST would look like:
|
12
|
+
|
13
|
+
<Block "test = 1 + 2">
|
14
|
+
<Statement "test = 1 + 2">
|
15
|
+
<Assignment "test = 1 + 2">
|
16
|
+
<Identifier "test">
|
17
|
+
<AssignmentOperator "=">
|
18
|
+
<Expression "1 + 2">
|
19
|
+
<AdditiveExpression "1 + 2">
|
20
|
+
<IntegerLiteral "1">
|
21
|
+
<AdditionOperator "+">
|
22
|
+
<IntegerLiteral "2">
|
23
|
+
|
24
|
+
|
25
|
+
=== Installation
|
26
|
+
|
27
|
+
This parser is normally installed as part of Koi's default toolchain. However if you would like to install it on it's own you can do so by installing the gem like so:
|
28
|
+
|
29
|
+
gem install koi-reference-parser
|
30
|
+
|
31
|
+
=== Usage
|
32
|
+
|
33
|
+
require 'rubygems'
|
34
|
+
require 'koi-reference-parser'
|
35
|
+
|
36
|
+
include KoiReferenceParser
|
37
|
+
|
38
|
+
ast = Parser.parse( program_text )
|
39
|
+
|
40
|
+
=== Author & Credits
|
41
|
+
|
42
|
+
Author:: {Aaron Gough}[mailto:aaron@aarongough.com]
|
43
|
+
|
44
|
+
Copyright (c) 2010 {Aaron Gough}[http://thingsaaronmade.com/] ({thingsaaronmade.com}[http://thingsaaronmade.com/]), released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'jeweler'
|
10
|
+
Jeweler::Tasks.new do |gemspec|
|
11
|
+
gemspec.name = "koi-reference-parser"
|
12
|
+
gemspec.summary = "A reference parser for the Koi language."
|
13
|
+
gemspec.description = "A reference parser for the Koi language."
|
14
|
+
gemspec.email = "aaron@aarongough.com"
|
15
|
+
gemspec.homepage = "http://github.com/aarongough/koi-reference-parser"
|
16
|
+
gemspec.authors = ["Aaron Gough"]
|
17
|
+
gemspec.rdoc_options << '--line-numbers' << '--inline-source'
|
18
|
+
gemspec.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE']
|
19
|
+
gemspec.add_dependency('treetop')
|
20
|
+
end
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
desc 'Test koi-reference-parser.'
|
27
|
+
Rake::TestTask.new(:test) do |t|
|
28
|
+
t.libs << 'lib/*.rb'
|
29
|
+
t.libs << 'test'
|
30
|
+
t.pattern = 'test/**/*_test.rb'
|
31
|
+
t.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
desc 'Generate documentation for koi-reference-parser.'
|
36
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
37
|
+
rdoc.rdoc_dir = 'rdoc'
|
38
|
+
rdoc.title = 'koi-reference-parser'
|
39
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
40
|
+
rdoc.rdoc_files.include('README.rdoc')
|
41
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
42
|
+
rdoc.rdoc_files.include('app/**/*.rb')
|
43
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
grammar KoiReferenceParser
|
2
|
+
|
3
|
+
rule block
|
4
|
+
statement+ <Block>
|
5
|
+
end
|
6
|
+
|
7
|
+
rule statement
|
8
|
+
space? ( hash_assignment / assignment / if / unless / function_call ) ';'? space? <Statement>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule nil
|
12
|
+
"nil" <NilLiteral>
|
13
|
+
end
|
14
|
+
|
15
|
+
rule true
|
16
|
+
"true" <TrueLiteral>
|
17
|
+
end
|
18
|
+
|
19
|
+
rule false
|
20
|
+
"false" <FalseLiteral>
|
21
|
+
end
|
22
|
+
|
23
|
+
rule integer
|
24
|
+
('+' / '-')? [0-9]+ <IntegerLiteral>
|
25
|
+
end
|
26
|
+
|
27
|
+
rule float
|
28
|
+
('+' / '-')? [0-9]+ '.' [0-9]+ <FloatLiteral>
|
29
|
+
end
|
30
|
+
|
31
|
+
rule string
|
32
|
+
'"' ([^"\\] / "\\" . )* '"' <StringLiteral>
|
33
|
+
end
|
34
|
+
|
35
|
+
rule identifier
|
36
|
+
'$'? [a-zA-Z] [a-zA-Z0-9_]* <Identifier>
|
37
|
+
end
|
38
|
+
|
39
|
+
rule hash_assignment
|
40
|
+
identifier hash_accessor_list space? assignment_operator space? ( hash / function_definition / expression ) <HashAssignment>
|
41
|
+
end
|
42
|
+
|
43
|
+
rule assignment
|
44
|
+
identifier space? assignment_operator space? ( hash / function_definition / expression ) <Assignment>
|
45
|
+
end
|
46
|
+
|
47
|
+
##################
|
48
|
+
# Flow control
|
49
|
+
|
50
|
+
rule if
|
51
|
+
'if(' space? expression space? ')' space
|
52
|
+
block
|
53
|
+
space? 'end' space? <If>
|
54
|
+
end
|
55
|
+
|
56
|
+
rule unless
|
57
|
+
'unless(' space? expression space? ')' space
|
58
|
+
block
|
59
|
+
space? 'end' space? <Unless>
|
60
|
+
end
|
61
|
+
|
62
|
+
##################
|
63
|
+
# Functions
|
64
|
+
|
65
|
+
rule function_call
|
66
|
+
identifier space? '(' space? expression? space? ','? expression? space? ')' <FunctionCall>
|
67
|
+
end
|
68
|
+
|
69
|
+
rule function_definition
|
70
|
+
'function(' space? identifier space? ')'
|
71
|
+
block
|
72
|
+
space? 'end' <FunctionDefinition>
|
73
|
+
end
|
74
|
+
|
75
|
+
##################
|
76
|
+
# Whitespace
|
77
|
+
|
78
|
+
rule space
|
79
|
+
[\s]+ <Whitespace>
|
80
|
+
end
|
81
|
+
|
82
|
+
##################
|
83
|
+
# Hashes
|
84
|
+
|
85
|
+
rule hash_accessor_list
|
86
|
+
hash_accessor+ <HashAccessorList>
|
87
|
+
end
|
88
|
+
|
89
|
+
rule hash_accessor
|
90
|
+
'[' expression ']' <HashAccessor>
|
91
|
+
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
|
+
|
113
|
+
##################
|
114
|
+
# Expressions
|
115
|
+
|
116
|
+
rule expression
|
117
|
+
space? (hash_access / comparative / additive) <Expression>
|
118
|
+
end
|
119
|
+
|
120
|
+
rule hash_access
|
121
|
+
identifier hash_accessor_list <HashAccess>
|
122
|
+
end
|
123
|
+
|
124
|
+
rule comparative
|
125
|
+
additive space? (equality_operator / inequality_operator / greater_than_operator / less_than_operator) space? additive <ComparativeExpression>
|
126
|
+
end
|
127
|
+
|
128
|
+
rule additive
|
129
|
+
multitive space? additive_operator space? additive <AdditiveExpression>
|
130
|
+
/
|
131
|
+
multitive
|
132
|
+
end
|
133
|
+
|
134
|
+
rule additive_operator
|
135
|
+
addition_operator
|
136
|
+
/
|
137
|
+
subtraction_operator
|
138
|
+
end
|
139
|
+
|
140
|
+
rule multitive
|
141
|
+
primary space? multitive_operator space? multitive <MultitiveExpression>
|
142
|
+
/
|
143
|
+
primary
|
144
|
+
end
|
145
|
+
|
146
|
+
rule multitive_operator
|
147
|
+
multiplication_operator
|
148
|
+
/
|
149
|
+
division_operator
|
150
|
+
end
|
151
|
+
|
152
|
+
rule primary
|
153
|
+
function_call / nil / false / true / identifier / float / integer / string
|
154
|
+
/
|
155
|
+
'(' space? expression space? ')' <Expression>
|
156
|
+
end
|
157
|
+
|
158
|
+
##################
|
159
|
+
# Operators
|
160
|
+
|
161
|
+
rule assignment_operator
|
162
|
+
'=' <AssignmentOperator>
|
163
|
+
end
|
164
|
+
|
165
|
+
rule addition_operator
|
166
|
+
'+' <AdditionOperator>
|
167
|
+
end
|
168
|
+
|
169
|
+
rule subtraction_operator
|
170
|
+
'-' <SubtractionOperator>
|
171
|
+
end
|
172
|
+
|
173
|
+
rule multiplication_operator
|
174
|
+
'*' <MultiplicationOperator>
|
175
|
+
end
|
176
|
+
|
177
|
+
rule division_operator
|
178
|
+
'/' <DivisionOperator>
|
179
|
+
end
|
180
|
+
|
181
|
+
rule equality_operator
|
182
|
+
'==' <EqualityOperator>
|
183
|
+
end
|
184
|
+
|
185
|
+
rule inequality_operator
|
186
|
+
'!=' <InequalityOperator>
|
187
|
+
end
|
188
|
+
|
189
|
+
rule greater_than_operator
|
190
|
+
'>' <GreaterThanOperator>
|
191
|
+
end
|
192
|
+
|
193
|
+
rule less_than_operator
|
194
|
+
'<' <LessThanOperator>
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Parser
|
2
|
+
|
3
|
+
require 'treetop'
|
4
|
+
Treetop.load(File.expand_path(File.join(File.dirname(__FILE__), 'koi-reference-parser.treetop')))
|
5
|
+
@@parser = KoiReferenceParserParser.new
|
6
|
+
|
7
|
+
def self.parse(data)
|
8
|
+
tree = @@parser.parse(data)
|
9
|
+
|
10
|
+
if(tree.nil?)
|
11
|
+
if( data.length > 80 )
|
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}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# clean up the tree by removing all nodes of default type 'SyntaxNode'
|
23
|
+
self.clean_tree(tree)
|
24
|
+
# clean up the tree further by removing all whitespace nodes
|
25
|
+
self.clean_whitespace(tree)
|
26
|
+
return tree
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.clean_tree(root_node)
|
32
|
+
return if(root_node.elements.nil?)
|
33
|
+
root_node.elements.delete_if{|node| node.class.name == "Treetop::Runtime::SyntaxNode" }
|
34
|
+
root_node.elements.each {|node| self.clean_tree(node) }
|
35
|
+
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
|
+
|
43
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module KoiReferenceParser
|
2
|
+
|
3
|
+
class Block < Treetop::Runtime::SyntaxNode
|
4
|
+
end
|
5
|
+
|
6
|
+
class Statement < Treetop::Runtime::SyntaxNode
|
7
|
+
end
|
8
|
+
|
9
|
+
class HashAssignment < Treetop::Runtime::SyntaxNode
|
10
|
+
end
|
11
|
+
|
12
|
+
class Assignment < Treetop::Runtime::SyntaxNode
|
13
|
+
end
|
14
|
+
|
15
|
+
class FunctionDefinition < Treetop::Runtime::SyntaxNode
|
16
|
+
end
|
17
|
+
|
18
|
+
class If < Treetop::Runtime::SyntaxNode
|
19
|
+
end
|
20
|
+
|
21
|
+
class Unless < Treetop::Runtime::SyntaxNode
|
22
|
+
end
|
23
|
+
|
24
|
+
class FunctionCall < Treetop::Runtime::SyntaxNode
|
25
|
+
end
|
26
|
+
|
27
|
+
class NilLiteral < Treetop::Runtime::SyntaxNode
|
28
|
+
end
|
29
|
+
|
30
|
+
class TrueLiteral < Treetop::Runtime::SyntaxNode
|
31
|
+
end
|
32
|
+
|
33
|
+
class FalseLiteral < Treetop::Runtime::SyntaxNode
|
34
|
+
end
|
35
|
+
|
36
|
+
class IntegerLiteral < Treetop::Runtime::SyntaxNode
|
37
|
+
end
|
38
|
+
|
39
|
+
class FloatLiteral < Treetop::Runtime::SyntaxNode
|
40
|
+
end
|
41
|
+
|
42
|
+
class StringLiteral < Treetop::Runtime::SyntaxNode
|
43
|
+
end
|
44
|
+
|
45
|
+
class HashAccessorList < Treetop::Runtime::SyntaxNode
|
46
|
+
end
|
47
|
+
|
48
|
+
class HashAccessor < Treetop::Runtime::SyntaxNode
|
49
|
+
end
|
50
|
+
|
51
|
+
class HashLiteral < Treetop::Runtime::SyntaxNode
|
52
|
+
end
|
53
|
+
|
54
|
+
class KeyValueList < Treetop::Runtime::SyntaxNode
|
55
|
+
end
|
56
|
+
|
57
|
+
class KeyValue < Treetop::Runtime::SyntaxNode
|
58
|
+
end
|
59
|
+
|
60
|
+
class Key < Treetop::Runtime::SyntaxNode
|
61
|
+
end
|
62
|
+
|
63
|
+
class Value < Treetop::Runtime::SyntaxNode
|
64
|
+
end
|
65
|
+
|
66
|
+
class Identifier < Treetop::Runtime::SyntaxNode
|
67
|
+
end
|
68
|
+
|
69
|
+
class Whitespace < Treetop::Runtime::SyntaxNode
|
70
|
+
end
|
71
|
+
|
72
|
+
class AssignmentOperator < Treetop::Runtime::SyntaxNode
|
73
|
+
end
|
74
|
+
|
75
|
+
class EqualityOperator < Treetop::Runtime::SyntaxNode
|
76
|
+
end
|
77
|
+
|
78
|
+
class InequalityOperator < Treetop::Runtime::SyntaxNode
|
79
|
+
end
|
80
|
+
|
81
|
+
class GreaterThanOperator < Treetop::Runtime::SyntaxNode
|
82
|
+
end
|
83
|
+
|
84
|
+
class LessThanOperator < Treetop::Runtime::SyntaxNode
|
85
|
+
end
|
86
|
+
|
87
|
+
class AdditionOperator < Treetop::Runtime::SyntaxNode
|
88
|
+
end
|
89
|
+
|
90
|
+
class SubtractionOperator < Treetop::Runtime::SyntaxNode
|
91
|
+
end
|
92
|
+
|
93
|
+
class MultiplicationOperator < Treetop::Runtime::SyntaxNode
|
94
|
+
end
|
95
|
+
|
96
|
+
class DivisionOperator < Treetop::Runtime::SyntaxNode
|
97
|
+
end
|
98
|
+
|
99
|
+
class Expression < Treetop::Runtime::SyntaxNode
|
100
|
+
end
|
101
|
+
|
102
|
+
class HashAccess < Treetop::Runtime::SyntaxNode
|
103
|
+
end
|
104
|
+
|
105
|
+
class ComparativeExpression < Treetop::Runtime::SyntaxNode
|
106
|
+
end
|
107
|
+
|
108
|
+
class AdditiveExpression < Treetop::Runtime::SyntaxNode
|
109
|
+
end
|
110
|
+
|
111
|
+
class MultitiveExpression < Treetop::Runtime::SyntaxNode
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionCallAsArgumentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse statement with function call as argument" do
|
8
|
+
assert_nothing_raised do
|
9
|
+
Parser.parse(<<-EOD)
|
10
|
+
|
11
|
+
print( to_string( 1 ))
|
12
|
+
|
13
|
+
EOD
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class SimpleProgramTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse simple program with 'if' flow control" do
|
8
|
+
assert_nothing_raised do
|
9
|
+
Parser.parse(<<-EOD)
|
10
|
+
|
11
|
+
test = 1
|
12
|
+
|
13
|
+
if(test == 1)
|
14
|
+
test = "yay"
|
15
|
+
end
|
16
|
+
|
17
|
+
EOD
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should parse simple program with 'unless' flow control" do
|
22
|
+
assert_nothing_raised do
|
23
|
+
Parser.parse(<<-EOD)
|
24
|
+
|
25
|
+
test = 1
|
26
|
+
|
27
|
+
unless(test == 1)
|
28
|
+
test = "yay"
|
29
|
+
end
|
30
|
+
|
31
|
+
EOD
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class AssignmentTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment of integer" do
|
8
|
+
tree = Parser.parse('test = 1')
|
9
|
+
assert_assigns_expression(IntegerLiteral, '1', tree)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "assignment of explicitly positive integer" do
|
13
|
+
tree = Parser.parse('test = +1')
|
14
|
+
assert_assigns_expression(IntegerLiteral, '+1', tree)
|
15
|
+
end
|
16
|
+
|
17
|
+
test "assignment of explicitly negative integer" do
|
18
|
+
tree = Parser.parse('test = -1')
|
19
|
+
assert_assigns_expression(IntegerLiteral, '-1', tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
test "assignment of float" do
|
23
|
+
tree = Parser.parse('test = 99.0009')
|
24
|
+
assert_assigns_expression(FloatLiteral, '99.0009', tree)
|
25
|
+
end
|
26
|
+
|
27
|
+
test "assignment of explicitly positive float" do
|
28
|
+
tree = Parser.parse('test = +99.0009')
|
29
|
+
assert_assigns_expression(FloatLiteral, '+99.0009', tree)
|
30
|
+
end
|
31
|
+
|
32
|
+
test "assignment of explicitly negative float" do
|
33
|
+
tree = Parser.parse('test = -99.0009')
|
34
|
+
assert_assigns_expression(FloatLiteral, '-99.0009', tree)
|
35
|
+
end
|
36
|
+
|
37
|
+
test "assignment of string" do
|
38
|
+
tree = Parser.parse('test = "test_string"')
|
39
|
+
assert_assigns_expression(StringLiteral, '"test_string"', tree)
|
40
|
+
end
|
41
|
+
|
42
|
+
test "assignment of string containing escaped quote" do
|
43
|
+
tree = Parser.parse('test = "test_\"string"')
|
44
|
+
assert_assigns_expression(StringLiteral, '"test_\"string"', tree)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "assignment of function definition" do
|
48
|
+
tree = Parser.parse('test = function(args) blah = 1 end')
|
49
|
+
assert_assigns(FunctionDefinition, nil, tree)
|
50
|
+
end
|
51
|
+
|
52
|
+
test "assignment of result of function call" do
|
53
|
+
tree = Parser.parse('test = function(args)')
|
54
|
+
assert_assigns_expression(FunctionCall, nil, tree)
|
55
|
+
end
|
56
|
+
|
57
|
+
test "assignment of nil" do
|
58
|
+
tree = Parser.parse('test = nil')
|
59
|
+
assert_assigns_expression(NilLiteral, nil, tree)
|
60
|
+
end
|
61
|
+
|
62
|
+
test "assignment of boolean true" do
|
63
|
+
tree = Parser.parse('test = true')
|
64
|
+
assert_assigns_expression(TrueLiteral, nil, tree)
|
65
|
+
end
|
66
|
+
|
67
|
+
test "assignment of boolean false" do
|
68
|
+
tree = Parser.parse('test = false')
|
69
|
+
assert_assigns_expression(FalseLiteral, nil, tree)
|
70
|
+
end
|
71
|
+
|
72
|
+
test "assignment of empty hash literal" do
|
73
|
+
tree = Parser.parse('test = {}')
|
74
|
+
assert_assigns(HashLiteral, nil, tree)
|
75
|
+
end
|
76
|
+
|
77
|
+
test "assignment of hash literal with single key-value pair" do
|
78
|
+
tree = Parser.parse('test = { 1 => 2 }')
|
79
|
+
assert_assigns(HashLiteral, nil, tree)
|
80
|
+
end
|
81
|
+
|
82
|
+
test "assignment of hash literal with 2 key-value pairs" do
|
83
|
+
tree = Parser.parse('test = { 1 => 2, 2 => 2 }')
|
84
|
+
assert_assigns(HashLiteral, nil, tree)
|
85
|
+
end
|
86
|
+
|
87
|
+
test "assignment of hash literal with 3 key-value pairs" do
|
88
|
+
tree = Parser.parse('test = { 1 => 2, 2 => 2, 3 => 2 }')
|
89
|
+
assert_assigns(HashLiteral, nil, tree)
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def assert_assigns(node_type, value, tree)
|
95
|
+
assert_kind_of Block, tree
|
96
|
+
assert_kind_of Statement, tree.elements.last
|
97
|
+
assert_kind_of Assignment, tree.elements.last.elements.last
|
98
|
+
assert_kind_of Identifier, tree.elements.last.elements.last.elements[0]
|
99
|
+
assert_kind_of AssignmentOperator, tree.elements.last.elements.last.elements[1]
|
100
|
+
assert_kind_of node_type, tree.elements.last.elements.last.elements[2]
|
101
|
+
assert_equal value, tree.elements.last.elements.last.elements[2].text_value unless(value.nil?)
|
102
|
+
end
|
103
|
+
|
104
|
+
def assert_assigns_expression(node_type, value, tree)
|
105
|
+
assert_kind_of Block, tree
|
106
|
+
assert_kind_of Statement, tree.elements.last
|
107
|
+
assert_kind_of Assignment, tree.elements.last.elements.last
|
108
|
+
assert_kind_of Identifier, tree.elements.last.elements.last.elements[0]
|
109
|
+
assert_kind_of AssignmentOperator, tree.elements.last.elements.last.elements[1]
|
110
|
+
assert_kind_of Expression, tree.elements.last.elements.last.elements[2]
|
111
|
+
assert_kind_of node_type, tree.elements.last.elements.last.elements[2].elements.first
|
112
|
+
assert_equal value, tree.elements.last.elements.last.elements[2].elements.first.text_value unless(value.nil?)
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class SimpleExpressionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse expression that contains function call as value" do
|
8
|
+
tree = Parser.parse('test = blah(1) + 1')
|
9
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
10
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
11
|
+
assert_kind_of AdditiveExpression, tree.elements.first.elements.last.elements[2].elements.first
|
12
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last.elements[2].elements.first.elements.first
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should parse expression that contains sub-expression as value" do
|
16
|
+
tree = Parser.parse('test = 2 * 3 * 2')
|
17
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
18
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
19
|
+
assert_kind_of MultitiveExpression, tree.elements.first.elements.last.elements[2].elements.first
|
20
|
+
assert_kind_of IntegerLiteral, tree.elements.first.elements.last.elements[2].elements.first.elements[0]
|
21
|
+
assert_kind_of MultiplicationOperator, tree.elements.first.elements.last.elements[2].elements.first.elements[1]
|
22
|
+
assert_kind_of MultitiveExpression, tree.elements.first.elements.last.elements[2].elements.first.elements[2]
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should parse expression that contains parenthesized sub-expression as value" do
|
26
|
+
tree = Parser.parse('test = (2 * 3) * 2')
|
27
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
28
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
29
|
+
assert_kind_of MultitiveExpression, tree.elements.first.elements.last.elements[2].elements.first
|
30
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2].elements.first.elements[0]
|
31
|
+
assert_kind_of MultiplicationOperator, tree.elements.first.elements.last.elements[2].elements.first.elements[1]
|
32
|
+
assert_kind_of IntegerLiteral, tree.elements.first.elements.last.elements[2].elements.first.elements[2]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionCallTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse function call with no arguments" do
|
8
|
+
tree = Parser.parse('test()')
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last
|
12
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should parse function call with identifier as argument" do
|
16
|
+
tree = Parser.parse('test(blah)')
|
17
|
+
assert_kind_of Block, tree
|
18
|
+
assert_kind_of Statement, tree.elements.first
|
19
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last
|
20
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
21
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[1]
|
22
|
+
end
|
23
|
+
|
24
|
+
test "should parse function call with multiple arguments" do
|
25
|
+
tree = Parser.parse('test(blah, blah2)')
|
26
|
+
assert_kind_of Block, tree
|
27
|
+
assert_kind_of Statement, tree.elements.first
|
28
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last
|
29
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
30
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[1]
|
31
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
32
|
+
end
|
33
|
+
|
34
|
+
test "should parse function call with expression as argument" do
|
35
|
+
tree = Parser.parse('test(1 * 2)')
|
36
|
+
assert_kind_of Block, tree
|
37
|
+
assert_kind_of Statement, tree.elements.first
|
38
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last
|
39
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
40
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[1]
|
41
|
+
end
|
42
|
+
|
43
|
+
test "should parse function call with function call as argument" do
|
44
|
+
tree = Parser.parse('test( call())')
|
45
|
+
assert_kind_of Block, tree
|
46
|
+
assert_kind_of Statement, tree.elements.first
|
47
|
+
assert_kind_of FunctionCall, tree.elements.first.elements.last
|
48
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
49
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[1]
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionDefinitionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse function definition including it's statements" do
|
8
|
+
tree = Parser.parse("test = function(args)\n teest1 = 1\n test2 = 2\nend")
|
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 FunctionDefinition, tree.elements.first.elements.first.elements.last
|
13
|
+
assert_kind_of Identifier, tree.elements.first.elements.first.elements.last.elements.first
|
14
|
+
assert_kind_of Block, tree.elements.first.elements.first.elements.last.elements.last
|
15
|
+
assert_kind_of Statement, tree.elements.first.elements.first.elements.last.elements.last.elements[0]
|
16
|
+
assert_kind_of Statement, tree.elements.first.elements.first.elements.last.elements.last.elements[1]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class HashAccessorTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "assignment to hash key" do
|
8
|
+
tree = Parser.parse('test[1] = 1')
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of HashAssignment, tree.elements.first.elements.first
|
12
|
+
assert_kind_of Identifier, tree.elements.first.elements.first.elements.first
|
13
|
+
assert_kind_of HashAccessorList, tree.elements.first.elements.first.elements[1]
|
14
|
+
assert_kind_of HashAccessor, tree.elements.first.elements.first.elements[1].elements.first
|
15
|
+
assert_equal 1, tree.elements.first.elements.first.elements[1].elements.length
|
16
|
+
end
|
17
|
+
|
18
|
+
test "assignment to a chain of hash key" do
|
19
|
+
tree = Parser.parse('test[1][2][3] = 1')
|
20
|
+
assert_kind_of Block, tree
|
21
|
+
assert_kind_of Statement, tree.elements.first
|
22
|
+
assert_kind_of HashAssignment, tree.elements.first.elements.first
|
23
|
+
assert_kind_of Identifier, tree.elements.first.elements.first.elements.first
|
24
|
+
assert_kind_of HashAccessorList, tree.elements.first.elements.first.elements[1]
|
25
|
+
assert_kind_of HashAccessor, tree.elements.first.elements.first.elements[1].elements.first
|
26
|
+
assert_equal 3, tree.elements.first.elements.first.elements[1].elements.length
|
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
|
+
|
41
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class FunctionCallTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse all lowercase identifier" do
|
8
|
+
tree = Parser.parse('test = "test"')
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
12
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should parse identifier with trailing numeral" do
|
16
|
+
tree = Parser.parse('test1 = "test"')
|
17
|
+
assert_kind_of Block, tree
|
18
|
+
assert_kind_of Statement, tree.elements.first
|
19
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
20
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should parse identifier with leading capital letter" do
|
24
|
+
tree = Parser.parse('Test = "test"')
|
25
|
+
assert_kind_of Block, tree
|
26
|
+
assert_kind_of Statement, tree.elements.first
|
27
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
28
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
29
|
+
end
|
30
|
+
|
31
|
+
test "should parse identifier that contains an underscore" do
|
32
|
+
tree = Parser.parse('test_test = "test"')
|
33
|
+
assert_kind_of Block, tree
|
34
|
+
assert_kind_of Statement, tree.elements.first
|
35
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
36
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
37
|
+
end
|
38
|
+
|
39
|
+
test "should parse single character identifier" do
|
40
|
+
tree = Parser.parse('x = "test"')
|
41
|
+
assert_kind_of Block, tree
|
42
|
+
assert_kind_of Statement, tree.elements.first
|
43
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
44
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
45
|
+
end
|
46
|
+
|
47
|
+
test "should parse identifier with leading $" do
|
48
|
+
tree = Parser.parse('$test = "test"')
|
49
|
+
assert_kind_of Block, tree
|
50
|
+
assert_kind_of Statement, tree.elements.first
|
51
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
52
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements.first
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class IfTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse if statement" do
|
8
|
+
tree = Parser.parse("if(1 == 1)\n test = 1\nend")
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of If, tree.elements.first.elements.first
|
12
|
+
assert_kind_of Expression, tree.elements.first.elements.first.elements.first
|
13
|
+
assert_kind_of Block, tree.elements.first.elements.first.elements.last
|
14
|
+
end
|
15
|
+
|
16
|
+
test "should parse single line if statement" do
|
17
|
+
tree = Parser.parse("if(1 == 1) test = 1; end")
|
18
|
+
assert_kind_of Block, tree
|
19
|
+
assert_kind_of Statement, tree.elements.first
|
20
|
+
assert_kind_of If, tree.elements.first.elements.first
|
21
|
+
assert_kind_of Expression, tree.elements.first.elements.first.elements.first
|
22
|
+
assert_kind_of Block, tree.elements.first.elements.first.elements.last
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class SimpleExpressionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
###############
|
8
|
+
# ADDITION
|
9
|
+
|
10
|
+
test "should parse simple addition expression with integers" do
|
11
|
+
tree = Parser.parse('test = 1 + 1')
|
12
|
+
assert_expression(tree, AdditionOperator)
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should parse simple addition expression with floats" do
|
16
|
+
tree = Parser.parse('test = 1.0 + 1.0')
|
17
|
+
assert_expression(tree, AdditionOperator)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "should parse simple addition expression with strings" do
|
21
|
+
tree = Parser.parse('test = "1" + "1"')
|
22
|
+
assert_expression(tree, AdditionOperator)
|
23
|
+
end
|
24
|
+
|
25
|
+
test "should parse simple addition expression with identifiers" do
|
26
|
+
tree = Parser.parse('test = test1 + test2')
|
27
|
+
assert_expression(tree, AdditionOperator)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
###############
|
32
|
+
# SUBTRACTION
|
33
|
+
|
34
|
+
test "should parse simple subtraction expression with integers" do
|
35
|
+
tree = Parser.parse('test = 1 - 1')
|
36
|
+
assert_expression(tree, SubtractionOperator)
|
37
|
+
end
|
38
|
+
|
39
|
+
test "should parse simple subtraction expression with floats" do
|
40
|
+
tree = Parser.parse('test = 1.0 - 1.0')
|
41
|
+
assert_expression(tree, SubtractionOperator)
|
42
|
+
end
|
43
|
+
|
44
|
+
test "should parse simple subtraction expression with strings" do
|
45
|
+
tree = Parser.parse('test = "1" - "1"')
|
46
|
+
assert_expression(tree, SubtractionOperator)
|
47
|
+
end
|
48
|
+
|
49
|
+
test "should parse simple subtraction expression with identifiers" do
|
50
|
+
tree = Parser.parse('test = test1 - test2')
|
51
|
+
assert_expression(tree, SubtractionOperator)
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
###############
|
56
|
+
# MULTIPLICATION
|
57
|
+
|
58
|
+
test "should parse simple multiplication expression with integers" do
|
59
|
+
tree = Parser.parse('test = 1 * 1')
|
60
|
+
assert_expression(tree, MultiplicationOperator)
|
61
|
+
end
|
62
|
+
|
63
|
+
test "should parse simple multiplication expression with floats" do
|
64
|
+
tree = Parser.parse('test = 1.0 * 1.0')
|
65
|
+
assert_expression(tree, MultiplicationOperator)
|
66
|
+
end
|
67
|
+
|
68
|
+
test "should parse simple multiplication expression with strings" do
|
69
|
+
tree = Parser.parse('test = "1" * "1"')
|
70
|
+
assert_expression(tree, MultiplicationOperator)
|
71
|
+
end
|
72
|
+
|
73
|
+
test "should parse simple multiplication expression with identifiers" do
|
74
|
+
tree = Parser.parse('test = test1 * test2')
|
75
|
+
assert_expression(tree, MultiplicationOperator)
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
###############
|
80
|
+
# DIVISION
|
81
|
+
|
82
|
+
test "should parse simple division expression with integers" do
|
83
|
+
tree = Parser.parse('test = 1 / 1')
|
84
|
+
assert_expression(tree, DivisionOperator)
|
85
|
+
end
|
86
|
+
|
87
|
+
test "should parse simple division expression with floats" do
|
88
|
+
tree = Parser.parse('test = 1.0 / 1.0')
|
89
|
+
assert_expression(tree, DivisionOperator)
|
90
|
+
end
|
91
|
+
|
92
|
+
test "should parse simple division expression with strings" do
|
93
|
+
tree = Parser.parse('test = "1" / "1"')
|
94
|
+
assert_expression(tree, DivisionOperator)
|
95
|
+
end
|
96
|
+
|
97
|
+
test "should parse simple division expression with identifiers" do
|
98
|
+
tree = Parser.parse('test = test1 / test2')
|
99
|
+
assert_expression(tree, DivisionOperator)
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
###############
|
104
|
+
# EQUALITY
|
105
|
+
|
106
|
+
test "should parse simple equality expression with integers" do
|
107
|
+
tree = Parser.parse('test = 1 == 1')
|
108
|
+
assert_expression(tree, EqualityOperator)
|
109
|
+
end
|
110
|
+
|
111
|
+
test "should parse simple equality expression with floats" do
|
112
|
+
tree = Parser.parse('test = 1.0 == 1.0')
|
113
|
+
assert_expression(tree, EqualityOperator)
|
114
|
+
end
|
115
|
+
|
116
|
+
test "should parse simple equality expression with strings" do
|
117
|
+
tree = Parser.parse('test = "1" == "1"')
|
118
|
+
assert_expression(tree, EqualityOperator)
|
119
|
+
end
|
120
|
+
|
121
|
+
test "should parse simple equality expression with identifiers" do
|
122
|
+
tree = Parser.parse('test = test1 == test2')
|
123
|
+
assert_expression(tree, EqualityOperator)
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
###############
|
128
|
+
# INEQUALITY
|
129
|
+
|
130
|
+
test "should parse simple inequality expression with integers" do
|
131
|
+
tree = Parser.parse('test = 1 != 1')
|
132
|
+
assert_expression(tree, InequalityOperator)
|
133
|
+
end
|
134
|
+
|
135
|
+
test "should parse simple inequality expression with floats" do
|
136
|
+
tree = Parser.parse('test = 1.0 != 1.0')
|
137
|
+
assert_expression(tree, InequalityOperator)
|
138
|
+
end
|
139
|
+
|
140
|
+
test "should parse simple inequality expression with strings" do
|
141
|
+
tree = Parser.parse('test = "1" != "1"')
|
142
|
+
assert_expression(tree, InequalityOperator)
|
143
|
+
end
|
144
|
+
|
145
|
+
test "should parse simple inequality expression with identifiers" do
|
146
|
+
tree = Parser.parse('test = test1 != test2')
|
147
|
+
assert_expression(tree, InequalityOperator)
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
###############
|
152
|
+
# GREATER THAN
|
153
|
+
|
154
|
+
test "should parse simple 'greater than' expression with integers" do
|
155
|
+
tree = Parser.parse('test = 1 > 1')
|
156
|
+
assert_expression(tree, GreaterThanOperator)
|
157
|
+
end
|
158
|
+
|
159
|
+
test "should parse simple 'greater than' expression with floats" do
|
160
|
+
tree = Parser.parse('test = 1.0 > 1.0')
|
161
|
+
assert_expression(tree, GreaterThanOperator)
|
162
|
+
end
|
163
|
+
|
164
|
+
test "should parse simple 'greater than' expression with strings" do
|
165
|
+
tree = Parser.parse('test = "1" > "1"')
|
166
|
+
assert_expression(tree, GreaterThanOperator)
|
167
|
+
end
|
168
|
+
|
169
|
+
test "should parse simple 'greater than' expression with identifiers" do
|
170
|
+
tree = Parser.parse('test = test1 > test2')
|
171
|
+
assert_expression(tree, GreaterThanOperator)
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
###############
|
176
|
+
# LESS THAN
|
177
|
+
|
178
|
+
test "should parse simple 'less than' expression with integers" do
|
179
|
+
tree = Parser.parse('test = 1 < 1')
|
180
|
+
assert_expression(tree, LessThanOperator)
|
181
|
+
end
|
182
|
+
|
183
|
+
test "should parse simple 'less than' expression with floats" do
|
184
|
+
tree = Parser.parse('test = 1.0 < 1.0')
|
185
|
+
assert_expression(tree, LessThanOperator)
|
186
|
+
end
|
187
|
+
|
188
|
+
test "should parse simple 'less than' expression with strings" do
|
189
|
+
tree = Parser.parse('test = "1" < "1"')
|
190
|
+
assert_expression(tree, LessThanOperator)
|
191
|
+
end
|
192
|
+
|
193
|
+
test "should parse simple 'less than' expression with identifiers" do
|
194
|
+
tree = Parser.parse('test = test1 < test2')
|
195
|
+
assert_expression(tree, LessThanOperator)
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def assert_expression(tree, operator = nil)
|
202
|
+
assert_kind_of Block, tree
|
203
|
+
assert_kind_of Statement, tree.elements.first
|
204
|
+
assert_kind_of Assignment, tree.elements.first.elements.last
|
205
|
+
assert_kind_of Identifier, tree.elements.first.elements.last.elements[0]
|
206
|
+
assert_kind_of AssignmentOperator, tree.elements.first.elements.last.elements[1]
|
207
|
+
assert_kind_of Expression, tree.elements.first.elements.last.elements[2]
|
208
|
+
assert_equal 3, tree.elements.first.elements.last.elements[2].elements.first.elements.size
|
209
|
+
assert_kind_of operator, tree.elements.first.elements.last.elements[2].elements.first.elements[1] unless(operator.nil?)
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class StatementTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse statments on separate lines as separate" do
|
8
|
+
tree = Parser.parse("test = 1\ntest = 1")
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements[0]
|
11
|
+
assert_kind_of Statement, tree.elements[1]
|
12
|
+
end
|
13
|
+
|
14
|
+
test "should parse statements on same line separated by ';' as separate" do
|
15
|
+
tree = Parser.parse("test = 1;test = 1")
|
16
|
+
assert_kind_of Block, tree
|
17
|
+
assert_kind_of Statement, tree.elements[0]
|
18
|
+
assert_kind_of Statement, tree.elements[1]
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper.rb'))
|
2
|
+
|
3
|
+
class UnlessTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include KoiReferenceParser
|
6
|
+
|
7
|
+
test "should parse unless statement" do
|
8
|
+
tree = Parser.parse("unless(1 == 1)\n test = 1\nend")
|
9
|
+
assert_kind_of Block, tree
|
10
|
+
assert_kind_of Statement, tree.elements.first
|
11
|
+
assert_kind_of Unless, tree.elements.first.elements.first
|
12
|
+
assert_kind_of Expression, tree.elements.first.elements.first.elements.first
|
13
|
+
assert_kind_of Block, tree.elements.first.elements.first.elements.last
|
14
|
+
end
|
15
|
+
|
16
|
+
test "should parse single line unless statement" do
|
17
|
+
tree = Parser.parse("unless(1 == 1) test = 1; end")
|
18
|
+
assert_kind_of Block, tree
|
19
|
+
assert_kind_of Statement, tree.elements.first
|
20
|
+
assert_kind_of Unless, tree.elements.first.elements.first
|
21
|
+
assert_kind_of Expression, tree.elements.first.elements.first.elements.first
|
22
|
+
assert_kind_of Block, tree.elements.first.elements.first.elements.last
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Test::Unit
|
2
|
+
# Used to fix a minor minitest/unit incompatibility in flexmock
|
3
|
+
AssertionFailedError = Class.new(StandardError)
|
4
|
+
|
5
|
+
class TestCase
|
6
|
+
|
7
|
+
def self.test(name, &block)
|
8
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
9
|
+
defined = instance_method(test_name) rescue false
|
10
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
11
|
+
if block_given?
|
12
|
+
define_method(test_name, &block)
|
13
|
+
else
|
14
|
+
define_method(test_name) do
|
15
|
+
flunk "No implementation provided for #{name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require_files = []
|
5
|
+
require_files << File.join(File.dirname(__FILE__), '..', 'lib', 'koi-reference-parser.rb')
|
6
|
+
require_files.concat Dir[File.join(File.dirname(__FILE__), 'setup', '*.rb')]
|
7
|
+
|
8
|
+
require_files.each do |file|
|
9
|
+
require File.expand_path(file)
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: koi-reference-parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Aaron Gough
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-30 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: treetop
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: A reference parser for the Koi language.
|
33
|
+
email: aaron@aarongough.com
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- MIT-LICENSE
|
40
|
+
- README.rdoc
|
41
|
+
files:
|
42
|
+
- .gitignore
|
43
|
+
- MIT-LICENSE
|
44
|
+
- README.rdoc
|
45
|
+
- Rakefile
|
46
|
+
- lib/koi-reference-parser.rb
|
47
|
+
- lib/parser/exceptions.rb
|
48
|
+
- lib/parser/koi-reference-parser.treetop
|
49
|
+
- lib/parser/parser.rb
|
50
|
+
- lib/parser/syntax_nodes.rb
|
51
|
+
- test/parser/functional/function_call_as_argument.rb
|
52
|
+
- test/parser/functional/simple_program_test.rb
|
53
|
+
- test/parser/unit/assignment_test.rb
|
54
|
+
- test/parser/unit/compound_expression_test.rb
|
55
|
+
- test/parser/unit/function_call_test.rb
|
56
|
+
- test/parser/unit/function_definition_test.rb
|
57
|
+
- test/parser/unit/hash_accessor_test.rb
|
58
|
+
- test/parser/unit/identifier_test.rb
|
59
|
+
- test/parser/unit/if_test.rb
|
60
|
+
- test/parser/unit/simple_expression_test.rb
|
61
|
+
- test/parser/unit/statement_test.rb
|
62
|
+
- test/parser/unit/unless_test.rb
|
63
|
+
- test/setup/test_unit_extensions.rb
|
64
|
+
- test/test_helper.rb
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/aarongough/koi-reference-parser
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --charset=UTF-8
|
72
|
+
- --line-numbers
|
73
|
+
- --inline-source
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
82
|
+
version: "0"
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.6
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: A reference parser for the Koi language.
|
97
|
+
test_files:
|
98
|
+
- test/parser/functional/function_call_as_argument.rb
|
99
|
+
- test/parser/functional/simple_program_test.rb
|
100
|
+
- test/parser/unit/assignment_test.rb
|
101
|
+
- test/parser/unit/compound_expression_test.rb
|
102
|
+
- test/parser/unit/function_call_test.rb
|
103
|
+
- test/parser/unit/function_definition_test.rb
|
104
|
+
- test/parser/unit/hash_accessor_test.rb
|
105
|
+
- test/parser/unit/identifier_test.rb
|
106
|
+
- test/parser/unit/if_test.rb
|
107
|
+
- test/parser/unit/simple_expression_test.rb
|
108
|
+
- test/parser/unit/statement_test.rb
|
109
|
+
- test/parser/unit/unless_test.rb
|
110
|
+
- test/setup/test_unit_extensions.rb
|
111
|
+
- test/test_helper.rb
|