alphalang 0.2.8 → 0.3.0
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.
- checksums.yaml +4 -4
- data/bin/alphalang +8 -0
- data/lib/alpha.rb +24 -12
- data/lib/error_handler.rb +68 -0
- data/lib/error_handler.rb~ +0 -0
- data/lib/nodes/basenodes.rb +76 -23
- data/lib/nodes/stmtnodes.rb +113 -3
- data/lib/rdparse.rb +2 -54
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c79a0fb156d98b42640f99526fcf8b6274828c07f8504b9d4b3563fdedb9078d
|
4
|
+
data.tar.gz: 9b0c5a2476e297ba4b78165608e43adb96cf4312e99f8530a1a6cb4d8d466a09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df72d6c52254c86ad8cd85000bf5e44a614d2909d1e55b1620cba8fdb2ba9a8b3552b27b8b034e4f5147752a21e51686c3613b36b237b2ced95fc4fcffafedc2
|
7
|
+
data.tar.gz: d8bc966079ac40acf1af38adf08654fd8b7961f4b79067d747d94b23f6e99cff5f7a0ee75a6829de8eb34679284b623fb6891e7f893d1eb8c655ecb7dac8ae84
|
data/bin/alphalang
CHANGED
@@ -44,6 +44,10 @@ OptionParser.new do |opts|
|
|
44
44
|
opts.on('--listlocale', 'Lists all keywords from a specific locale file from your locales directory.') do
|
45
45
|
options[:listlocale] = true
|
46
46
|
end
|
47
|
+
|
48
|
+
opts.on('-p', '--printtree', 'Prints the abstract syntax tree in a simple form.') do
|
49
|
+
options[:printtree] = true
|
50
|
+
end
|
47
51
|
end.parse!
|
48
52
|
|
49
53
|
verbose_flag = options[:verbose]
|
@@ -54,6 +58,10 @@ create_locale_flag = options[:createlocale]
|
|
54
58
|
delete_locale_flag = options[:deletelocale]
|
55
59
|
list_locales_flag = options[:listlocales]
|
56
60
|
list_locale_flag = options[:listlocale]
|
61
|
+
PRINT_TREE_FLAG = options[:printtree]
|
62
|
+
TREE_ARRAY = []
|
63
|
+
|
64
|
+
raise Errno::EBADR, "Don't use --logger and --printtree together." if PRINT_TREE_FLAG and verbose_flag
|
57
65
|
|
58
66
|
if create_locale_flag
|
59
67
|
require_relative '../lib/locale_creator'
|
data/lib/alpha.rb
CHANGED
@@ -24,11 +24,6 @@ class LangParser
|
|
24
24
|
|
25
25
|
start :program do
|
26
26
|
match(:comp_stmt)
|
27
|
-
match(:terminal)
|
28
|
-
end
|
29
|
-
|
30
|
-
rule :terminal do
|
31
|
-
match(/\n|;/)
|
32
27
|
end
|
33
28
|
|
34
29
|
rule :comp_stmt do
|
@@ -64,12 +59,12 @@ class LangParser
|
|
64
59
|
|
65
60
|
rule :if_comp_stmt do
|
66
61
|
match(:if_stmt, :comp_elseif, :else_stmt, :STOP) { |a, b, c| IfCompStmtNode.new(a, b, c) }
|
62
|
+
match(:if_stmt, :comp_elseif, :STOP) { |a, b| IfCompStmtNode.new(a, b) }
|
67
63
|
match(:if_stmt, :else_stmt, :STOP) { |a, b| IfCompStmtNode.new(a, b) }
|
68
64
|
match(:if_stmt, :STOP) { |a| IfCompStmtNode.new(a) }
|
69
65
|
end
|
70
66
|
|
71
67
|
rule :if_stmt do
|
72
|
-
match(:IF, :expr_stmt, :and, :expr_stmt, :comp_stmt) { |_, a, b, c, d| IfCompactNode.new(a, b, c, d) }
|
73
68
|
match(:IF, :expr_stmt, :comp_stmt) { |_, a, b| IfNode.new(a, b) }
|
74
69
|
end
|
75
70
|
|
@@ -165,15 +160,11 @@ class LangParser
|
|
165
160
|
rule :atom do
|
166
161
|
match(:number)
|
167
162
|
match(:boolean)
|
163
|
+
match(:string)
|
168
164
|
match(:call_member)
|
169
165
|
match(:prio_stmt)
|
170
166
|
end
|
171
167
|
|
172
|
-
rule :boolean do
|
173
|
-
match(ScopeManager.true_value) { |a| BoolNode.new(a) }
|
174
|
-
match(ScopeManager.false_value) { |a| BoolNode.new(a) }
|
175
|
-
end
|
176
|
-
|
177
168
|
rule :number do
|
178
169
|
match('-', /\d+/, '.', /\d+/) { |neg, a, dot, b| NumberNode.new(neg + a + dot + b) }
|
179
170
|
match(/\d+/, '.', /\d+/) { |a, dot, b| NumberNode.new(a + dot + b) }
|
@@ -181,6 +172,25 @@ class LangParser
|
|
181
172
|
match(/\d+/) { |a| NumberNode.new(a) }
|
182
173
|
end
|
183
174
|
|
175
|
+
rule :boolean do
|
176
|
+
match(ScopeManager.true_value) { |a| BoolNode.new(a) }
|
177
|
+
match(ScopeManager.false_value) { |a| BoolNode.new(a) }
|
178
|
+
end
|
179
|
+
|
180
|
+
rule :string do
|
181
|
+
match('"', :comp_string, '"') { |_, str, _| StringNode.new(str) }
|
182
|
+
end
|
183
|
+
|
184
|
+
# TODO: Figure out if this is possible with char without messing too much with lexer
|
185
|
+
rule :comp_string do
|
186
|
+
match(:word, :comp_string) { |a, b| [a, b].flatten }
|
187
|
+
match(:word)
|
188
|
+
end
|
189
|
+
|
190
|
+
rule :word do
|
191
|
+
match(/\w/) { |m| m }
|
192
|
+
end
|
193
|
+
|
184
194
|
rule :call_member do
|
185
195
|
match(:member, '(', :arg_list, ')') { |var, _, args, _| FuncCallNode.new(var, args) }
|
186
196
|
match(:member, '(', ')') { |var, _, _| FuncCallNode.new(var, NilClass) }
|
@@ -202,7 +212,9 @@ class LangParser
|
|
202
212
|
def parse_file(filename)
|
203
213
|
file = File.read(filename)
|
204
214
|
root = @langParser.parse file
|
205
|
-
root.evaluate
|
215
|
+
root = root.evaluate
|
216
|
+
puts TREE_ARRAY
|
217
|
+
root
|
206
218
|
end
|
207
219
|
|
208
220
|
def calc_test(str)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Error Handler, imported by RDParse.
|
2
|
+
class ErrorHandler
|
3
|
+
class ParseError < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.convert_regex_sensitive_token(token, token_list)
|
7
|
+
token = token_list['end'] if token == :STOP
|
8
|
+
token = "#{token_list['(not|!)'].split('|')[0][1..]}" if token == :NOT
|
9
|
+
token = "#{token_list['(and|&&)'].split('|')[0][1..]}" if token == :AND
|
10
|
+
token = "#{token_list['(or|\|\|)'].split('|')[0][1..]}" if token == :OR
|
11
|
+
token = '[(]' if token == '('
|
12
|
+
token = '[)]' if token == ')'
|
13
|
+
token = '[+]' if token == '+'
|
14
|
+
token = '[-]' if token == '-'
|
15
|
+
token = '[*]' if token == '*'
|
16
|
+
token = '[/]' if token == '/'
|
17
|
+
token
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.translate_tokens_array(array, token_list)
|
21
|
+
result = []
|
22
|
+
array.each do |token|
|
23
|
+
token = convert_regex_sensitive_token(token, token_list)
|
24
|
+
result << token unless token.is_a?(Symbol)
|
25
|
+
result << token_list[token.to_s.downcase] if token.is_a?(Symbol)
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.find_surrounding_code(problem_pos, tokens)
|
31
|
+
tokens_before_problem = []
|
32
|
+
temp = problem_pos
|
33
|
+
while temp >= 0
|
34
|
+
tokens_before_problem << tokens[temp]
|
35
|
+
temp -= 1
|
36
|
+
end
|
37
|
+
tokens_before_problem.reverse
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.find_faulty_line(pos, file_string, tokens, token_list)
|
41
|
+
tokens_before_problem = find_surrounding_code(pos - 1, tokens)
|
42
|
+
file_as_array_without_whitespaces = translate_tokens_array(tokens_before_problem, token_list)
|
43
|
+
|
44
|
+
pattern = file_as_array_without_whitespaces.join('\s*')
|
45
|
+
regex = Regexp.new(pattern)
|
46
|
+
|
47
|
+
# Remove comments, replace entire comment lines with "\n" to perserve num_lines
|
48
|
+
cleaned_string = file_string.gsub(/^;;.*/, "\n")
|
49
|
+
cleaned_string = cleaned_string.gsub(/;;.*/, '')
|
50
|
+
|
51
|
+
match_data = regex.match(cleaned_string)
|
52
|
+
num_lines = match_data[0].count("\n") + 1 unless NilClass # TODO: Find out what causes these edge cases
|
53
|
+
|
54
|
+
problem = tokens[pos]
|
55
|
+
line_msg = "There is a problem on line #{num_lines}"
|
56
|
+
line_msg = "Couldn't precise the exact line" if num_lines.is_a?(NilClass) # TODO: Find out edge cases
|
57
|
+
|
58
|
+
if tokens_before_problem[-1] == :PRINT
|
59
|
+
raise ParseError, "#{line_msg} with the <#{token_list['print']}> statement, needs something to print."
|
60
|
+
elsif tokens_before_problem[-1] == :PAUSE
|
61
|
+
raise ParseError, "#{line_msg} with the <#{token_list['pause']}> statement, pause needs a numeric argument."
|
62
|
+
elsif problem == :STOP
|
63
|
+
raise ParseError, "#{line_msg}. Found <#{token_list['end']}>\nEmpty if-statements and functions are not allowed"
|
64
|
+
else
|
65
|
+
raise ParseError, "#{line_msg}. Found <#{problem}>"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
File without changes
|
data/lib/nodes/basenodes.rb
CHANGED
@@ -36,21 +36,70 @@ class BoolNode < Node
|
|
36
36
|
@value = false if value == ScopeManager.false_value
|
37
37
|
end
|
38
38
|
|
39
|
+
def to_s
|
40
|
+
@value.to_s
|
41
|
+
end
|
42
|
+
|
39
43
|
def evaluate
|
40
44
|
@value
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
48
|
+
# See ArrayNode for a more complete Data Structure
|
49
|
+
class StringNode < Node
|
50
|
+
def initialize(value)
|
51
|
+
if value.is_a?(String)
|
52
|
+
super
|
53
|
+
else
|
54
|
+
super(value.join(' '))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def +(other)
|
59
|
+
raise NotImplementedError, 'Addition is not implemented for Strings.'
|
60
|
+
end
|
61
|
+
|
62
|
+
def -(other)
|
63
|
+
raise NotImplementedError, 'Subtraction is not implemented for Strings.'
|
64
|
+
end
|
65
|
+
|
66
|
+
def *(other)
|
67
|
+
raise NotImplementedError, 'Multiplication is not implemented for Strings.'
|
68
|
+
end
|
69
|
+
|
70
|
+
def /(other)
|
71
|
+
raise NotImplementedError, 'Division is not implemented for Strings.'
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_i
|
75
|
+
@value.to_i
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_f
|
79
|
+
@value.to_f
|
80
|
+
end
|
81
|
+
|
82
|
+
def contains?(other)
|
83
|
+
return if @value.include?(other)
|
84
|
+
end
|
85
|
+
|
86
|
+
def evaluate
|
87
|
+
self
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
44
91
|
###################### Logic Gate Nodes
|
45
92
|
|
46
93
|
class AndNode < Node
|
47
94
|
def initialize(lhs, rhs)
|
48
95
|
@lhs, @rhs = lhs, rhs
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
96
|
+
return unless @rhs.class.method_defined?(:lhs)
|
97
|
+
|
98
|
+
@rhs.lhs = @lhs.lhs if @rhs.lhs == nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
"#{@lhs} and #{@rhs}"
|
54
103
|
end
|
55
104
|
|
56
105
|
def evaluate
|
@@ -61,11 +110,13 @@ end
|
|
61
110
|
class OrNode < Node
|
62
111
|
def initialize(lhs, rhs)
|
63
112
|
@lhs, @rhs = lhs, rhs
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
113
|
+
return unless @rhs.class.method_defined?(:lhs)
|
114
|
+
|
115
|
+
@rhs.lhs = @lhs.lhs if @rhs.lhs == nil
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_s
|
119
|
+
"#{@lhs} or #{@rhs}"
|
69
120
|
end
|
70
121
|
|
71
122
|
def evaluate
|
@@ -78,6 +129,10 @@ class NotNode < Node
|
|
78
129
|
@node = node
|
79
130
|
end
|
80
131
|
|
132
|
+
def to_s
|
133
|
+
"not #{@node}"
|
134
|
+
end
|
135
|
+
|
81
136
|
def evaluate
|
82
137
|
not @node.evaluate
|
83
138
|
end
|
@@ -92,6 +147,10 @@ class CompareNode < Node
|
|
92
147
|
@lhs, @op, @rhs = lhs, op, rhs
|
93
148
|
end
|
94
149
|
|
150
|
+
def to_s
|
151
|
+
"#{@lhs} #{@op} #{@rhs}"
|
152
|
+
end
|
153
|
+
|
95
154
|
def evaluate
|
96
155
|
@value = @lhs.evaluate.send(@op, @rhs.evaluate)
|
97
156
|
end
|
@@ -105,21 +164,13 @@ class BinaryOperationNode < Node
|
|
105
164
|
@lhs, @op, @rhs = lhs, op, rhs
|
106
165
|
end
|
107
166
|
|
167
|
+
def to_s
|
168
|
+
"#{@lhs} #{@op} #{@rhs}"
|
169
|
+
end
|
170
|
+
|
108
171
|
def evaluate
|
109
172
|
if @rhs.evaluate.is_a?(ArrayNode) && @op == '+'
|
110
173
|
return @value = @rhs.evaluate + @lhs.evaluate
|
111
|
-
elsif @lhs.evaluate.is_a?(Array) && @op == '+'
|
112
|
-
return @value = @lhs.evaluate.append(@rhs.evaluate)
|
113
|
-
end
|
114
|
-
|
115
|
-
if @rhs.evaluate.is_a?(ArrayNode) && @op == '-'
|
116
|
-
return @value = @rhs.evaluate - @lhs.evaluate
|
117
|
-
elsif @lhs.evaluate.is_a?(Array) && @op == '-'
|
118
|
-
return @lhs.evaluate.reject { |v| v.evaluate == @rhs.evaluate }
|
119
|
-
end
|
120
|
-
|
121
|
-
if @rhs.evaluate.is_a?(ArrayNode) or @rhs.evaluate.is_a?(Array) and @lhs.evaluate.is_a?(Numeric)
|
122
|
-
raise SyntaxError, "You can't subtract an array from a number! #{@lhs.evaluate} #{@op} #{@rhs.name}"
|
123
174
|
end
|
124
175
|
|
125
176
|
if @op == '/'
|
@@ -163,10 +214,12 @@ class ArrayNode < Node
|
|
163
214
|
|
164
215
|
def +(value)
|
165
216
|
@value.append(value)
|
217
|
+
self
|
166
218
|
end
|
167
219
|
|
168
220
|
def -(value)
|
169
|
-
@value.reject { |v| v.evaluate == value }
|
221
|
+
@value = @value.reject { |v| v.evaluate == value }
|
222
|
+
self
|
170
223
|
end
|
171
224
|
|
172
225
|
def [](index)
|
data/lib/nodes/stmtnodes.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
require_relative 'basenodes'
|
2
2
|
|
3
|
+
def set_up_scope_header
|
4
|
+
result = "<#{ScopeManager.scope_lvl}> "
|
5
|
+
result += '++--++--' * (ScopeManager.scope_lvl + 1) + ' '
|
6
|
+
result
|
7
|
+
end
|
8
|
+
|
3
9
|
###################### Variable Nodes
|
4
10
|
|
5
11
|
class VariableCallNode < Node
|
@@ -9,8 +15,19 @@ class VariableCallNode < Node
|
|
9
15
|
@name = name
|
10
16
|
end
|
11
17
|
|
18
|
+
def create_tree_entry
|
19
|
+
result = set_up_scope_header
|
20
|
+
result += "Variable #{@name} is now #{@value}"
|
21
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@name
|
26
|
+
end
|
27
|
+
|
12
28
|
def evaluate
|
13
29
|
@value = ScopeManager.lookup_var(@name)
|
30
|
+
create_tree_entry if PRINT_TREE_FLAG
|
14
31
|
return @value
|
15
32
|
end
|
16
33
|
end
|
@@ -23,8 +40,19 @@ class VariableDecNode < Node
|
|
23
40
|
@name = name
|
24
41
|
end
|
25
42
|
|
43
|
+
def create_tree_entry
|
44
|
+
result = set_up_scope_header
|
45
|
+
result += "Variable #{@name} is now #{@value}"
|
46
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"#{@name} = #{@value}"
|
51
|
+
end
|
52
|
+
|
26
53
|
def evaluate
|
27
54
|
ScopeManager.add_to_current_scope(name, @value)
|
55
|
+
create_tree_entry if PRINT_TREE_FLAG
|
28
56
|
self
|
29
57
|
end
|
30
58
|
end
|
@@ -41,6 +69,7 @@ class ArrayCallNode < Node
|
|
41
69
|
raise ArgumentError, "You are trying to access an out of bounds index. Here -> #{@value}[#{@index}]"
|
42
70
|
end
|
43
71
|
@value = arr[@index]
|
72
|
+
@value
|
44
73
|
end
|
45
74
|
end
|
46
75
|
|
@@ -53,8 +82,19 @@ class FunctionDecNode < Node
|
|
53
82
|
@args = node.args
|
54
83
|
end
|
55
84
|
|
85
|
+
def create_tree_entry
|
86
|
+
result = set_up_scope_header
|
87
|
+
result += "Function #{@name} declared"
|
88
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_s
|
92
|
+
"#{@name} = #{@value}"
|
93
|
+
end
|
94
|
+
|
56
95
|
def evaluate
|
57
96
|
ScopeManager.add_func_to_global_scope(@name, @value, @args)
|
97
|
+
create_tree_entry if PRINT_TREE_FLAG
|
58
98
|
return nil
|
59
99
|
end
|
60
100
|
end
|
@@ -67,6 +107,20 @@ class FuncCallNode < Node
|
|
67
107
|
@args = args
|
68
108
|
end
|
69
109
|
|
110
|
+
def to_s
|
111
|
+
if @args == NilClass
|
112
|
+
"#{name}()"
|
113
|
+
else
|
114
|
+
"#{name}(#{@args})"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_tree_entry
|
119
|
+
result = set_up_scope_header
|
120
|
+
result += "Function #{@name} is called"
|
121
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
122
|
+
end
|
123
|
+
|
70
124
|
def evaluate
|
71
125
|
func = ScopeManager.lookup_func(@name)
|
72
126
|
|
@@ -95,6 +149,7 @@ class FuncCallNode < Node
|
|
95
149
|
ScopeManager.scope_lvl = old_scope_lvl
|
96
150
|
end
|
97
151
|
|
152
|
+
create_tree_entry if PRINT_TREE_FLAG
|
98
153
|
return func_return_value
|
99
154
|
end
|
100
155
|
end
|
@@ -108,8 +163,20 @@ class IfNode < Node
|
|
108
163
|
@argument, @node = argument, node
|
109
164
|
end
|
110
165
|
|
166
|
+
def to_s
|
167
|
+
"If #{argument}"
|
168
|
+
end
|
169
|
+
|
170
|
+
def create_tree_entry
|
171
|
+
result = set_up_scope_header
|
172
|
+
result += "If statement #{@argument} is used"
|
173
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
174
|
+
end
|
175
|
+
|
111
176
|
def evaluate
|
112
177
|
@value = @node.evaluate
|
178
|
+
create_tree_entry if PRINT_TREE_FLAG
|
179
|
+
@value
|
113
180
|
end
|
114
181
|
end
|
115
182
|
|
@@ -120,8 +187,20 @@ class ElseifNode < Node
|
|
120
187
|
@argument, @node = argument, node
|
121
188
|
end
|
122
189
|
|
190
|
+
def to_s
|
191
|
+
'Else'
|
192
|
+
end
|
193
|
+
|
194
|
+
def create_tree_entry
|
195
|
+
result = set_up_scope_header
|
196
|
+
result += "Elseif statement is used. #{@argument}"
|
197
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
198
|
+
end
|
199
|
+
|
123
200
|
def evaluate
|
124
201
|
@value = @node.evaluate
|
202
|
+
create_tree_entry if PRINT_TREE_FLAG
|
203
|
+
@value
|
125
204
|
end
|
126
205
|
end
|
127
206
|
|
@@ -133,8 +212,16 @@ class ElseNode < Node
|
|
133
212
|
@argument = BoolNode.new(ScopeManager.true_value)
|
134
213
|
end
|
135
214
|
|
215
|
+
def create_tree_entry
|
216
|
+
result = set_up_scope_header
|
217
|
+
result += "Else statement is used."
|
218
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
219
|
+
end
|
220
|
+
|
136
221
|
def evaluate
|
137
222
|
@value = @node.evaluate
|
223
|
+
create_tree_entry if PRINT_TREE_FLAG
|
224
|
+
@value
|
138
225
|
end
|
139
226
|
end
|
140
227
|
|
@@ -163,10 +250,19 @@ class WhileLoopNode < Node
|
|
163
250
|
super(statement)
|
164
251
|
end
|
165
252
|
|
253
|
+
def create_tree_entry
|
254
|
+
result = set_up_scope_header
|
255
|
+
result += "While Loop ran with #{@counter} iterations."
|
256
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
257
|
+
end
|
258
|
+
|
166
259
|
def evaluate
|
260
|
+
@counter = 0
|
167
261
|
while @condition.evaluate
|
168
262
|
@value.evaluate
|
263
|
+
@counter += 1
|
169
264
|
end
|
265
|
+
create_tree_entry if PRINT_TREE_FLAG
|
170
266
|
self.class
|
171
267
|
end
|
172
268
|
end
|
@@ -180,16 +276,20 @@ class PrintNode
|
|
180
276
|
@value = value
|
181
277
|
end
|
182
278
|
|
279
|
+
def create_tree_entry
|
280
|
+
result = set_up_scope_header
|
281
|
+
result += "Printed #{@value}."
|
282
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
283
|
+
end
|
284
|
+
|
183
285
|
def evaluate
|
184
286
|
if @value.evaluate.is_a?(ArrayNode)
|
185
287
|
print "Array #{@value.name}: " unless TEST_UNIT_ACTIVE
|
186
288
|
puts @value.evaluate unless TEST_UNIT_ACTIVE
|
187
|
-
elsif @value.evaluate.is_a?(Array)
|
188
|
-
print "Array #{@value.name}: " unless TEST_UNIT_ACTIVE
|
189
|
-
puts @value.evaluate.join(', ') unless TEST_UNIT_ACTIVE
|
190
289
|
else
|
191
290
|
puts @value.evaluate unless TEST_UNIT_ACTIVE
|
192
291
|
end
|
292
|
+
create_tree_entry if PRINT_TREE_FLAG
|
193
293
|
self.class
|
194
294
|
end
|
195
295
|
end
|
@@ -199,8 +299,18 @@ class PauseNode < Node
|
|
199
299
|
super(value)
|
200
300
|
end
|
201
301
|
|
302
|
+
def create_tree_entry
|
303
|
+
result = set_up_scope_header
|
304
|
+
result += "Paused for #{@value} seconds."
|
305
|
+
TREE_ARRAY << result unless TREE_ARRAY[-1] == result
|
306
|
+
end
|
307
|
+
|
202
308
|
def evaluate
|
309
|
+
# TODO: Create an Error Handler class... Needs to use rdparses functions here for a more helpful msg.
|
310
|
+
raise SyntaxError, 'Pause needs a numeric argument.' unless @value.evaluate.is_a?(Numeric)
|
311
|
+
|
203
312
|
@value = 0 if @value.evaluate.negative?
|
313
|
+
create_tree_entry if PRINT_TREE_FLAG
|
204
314
|
sleep @value.evaluate
|
205
315
|
end
|
206
316
|
end
|
data/lib/rdparse.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
# 2014-02-16 New version that handles { false } blocks and :empty tokens.
|
9
9
|
|
10
10
|
require 'logger'
|
11
|
+
require_relative 'error_handler'
|
11
12
|
|
12
13
|
class Rule
|
13
14
|
|
@@ -187,58 +188,6 @@ class Parser
|
|
187
188
|
end # until
|
188
189
|
end
|
189
190
|
|
190
|
-
def convert_regex_sensitive_token(token)
|
191
|
-
token = @token_list['end'] if token == :STOP # fulhack pga :END påstods inte funka för länge sen
|
192
|
-
token = '[(]' if token == '('
|
193
|
-
token = '[)]' if token == ')'
|
194
|
-
token = '[+]' if token == '+'
|
195
|
-
token = '[-]' if token == '-'
|
196
|
-
token = '[*]' if token == '*'
|
197
|
-
token = '[/]' if token == '/'
|
198
|
-
token = "#{@token_list['(not|!)'].split('|')[0][1..]}" if token == :NOT
|
199
|
-
token = "#{@token_list['(and|&&)'].split('|')[0][1..]}" if token == :AND
|
200
|
-
token = "#{@token_list['(or|\|\|)'].split('|')[0][1..]}" if token == :OR
|
201
|
-
token
|
202
|
-
end
|
203
|
-
|
204
|
-
def translate_tokens_array(array)
|
205
|
-
result = []
|
206
|
-
array.each do |token|
|
207
|
-
token = convert_regex_sensitive_token(token)
|
208
|
-
result << token unless token.is_a?(Symbol)
|
209
|
-
result << @token_list[token.to_s.downcase] if token.is_a?(Symbol)
|
210
|
-
end
|
211
|
-
result
|
212
|
-
end
|
213
|
-
|
214
|
-
def find_surrounding_code(problem_pos)
|
215
|
-
tokens_before_problem = []
|
216
|
-
temp = problem_pos
|
217
|
-
while temp >= 0
|
218
|
-
tokens_before_problem << @tokens[temp]
|
219
|
-
temp -= 1
|
220
|
-
end
|
221
|
-
tokens_before_problem.reverse
|
222
|
-
end
|
223
|
-
|
224
|
-
def find_faulty_line
|
225
|
-
tokens_before_problem = find_surrounding_code(@max_pos - 1)
|
226
|
-
file_as_array_without_whitespaces = translate_tokens_array(tokens_before_problem)
|
227
|
-
|
228
|
-
pattern = file_as_array_without_whitespaces.join('\s*')
|
229
|
-
regex = Regexp.new(pattern)
|
230
|
-
|
231
|
-
cleaned_string = @file_string.gsub(/;;.*/, '')
|
232
|
-
|
233
|
-
match_data = regex.match(cleaned_string)
|
234
|
-
num_lines = match_data[0].count("\n") + 1
|
235
|
-
|
236
|
-
problem = @tokens[@max_pos]
|
237
|
-
problem = @token_list[problem.to_s.downcase] unless @token_list[problem.to_s.downcase].is_a?(NilClass)
|
238
|
-
|
239
|
-
raise ParseError, "There is a problem around line #{num_lines}. Found <#{problem}>"
|
240
|
-
end
|
241
|
-
|
242
191
|
def parse(string)
|
243
192
|
# First, split the string according to the "token" instructions given.
|
244
193
|
# Afterwards @tokens contains all tokens that are to be parsed.
|
@@ -259,8 +208,7 @@ class Parser
|
|
259
208
|
raise ParseError, 'Mismatched parenthesis! In Emacs: M-x check-parens RET'
|
260
209
|
end
|
261
210
|
|
262
|
-
|
263
|
-
return find_faulty_line
|
211
|
+
return ErrorHandler.find_faulty_line(@max_pos, @file_string, @tokens, @token_list)
|
264
212
|
end
|
265
213
|
return result
|
266
214
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alphalang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mattias, victor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logger
|
@@ -60,6 +60,8 @@ extra_rdoc_files: []
|
|
60
60
|
files:
|
61
61
|
- bin/alphalang
|
62
62
|
- lib/alpha.rb
|
63
|
+
- lib/error_handler.rb
|
64
|
+
- lib/error_handler.rb~
|
63
65
|
- lib/locale_creator.rb
|
64
66
|
- lib/locale_defaulter.rb
|
65
67
|
- lib/locale_deleter.rb
|