alphalang 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/alphalang +59 -0
- data/lib/alpha.rb +168 -0
- data/lib/lang_creator.rb +124 -0
- data/lib/locales/de +17 -0
- data/lib/locales/en +17 -0
- data/lib/locales/locale_template +17 -0
- data/lib/locales/sv +17 -0
- data/lib/nodes/#stmtnodes.rb# +196 -0
- data/lib/nodes/basenodes.rb +195 -0
- data/lib/nodes/stmtnodes.rb +200 -0
- data/lib/rdparse.rb +238 -0
- data/lib/rdparse_quiet.rb +237 -0
- data/lib/tester/fibonacci.alpha +19 -0
- data/lib/tester/test_unit.rb +217 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2f7356e9bd0fa5e53d01733fa3266b7294f969037c665941daaac523e50e3b9f
|
4
|
+
data.tar.gz: '060006929bc0e33a766c001622f0079f9f3c3c51163138c867cc5bb67f31755d'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1e5673759a21f75cc4d7fa14147b5a60fab5319e07ebce2349cdf35121e6a79bb1e78714c641c9061806c50ff1d9d60c2ca0c615c09f13c32f08a38eb812fb7
|
7
|
+
data.tar.gz: 53a824dd4c27bd9cf3ffb35d9db46a7b98a67b2ffd095d365cd1cc569faa835fa2d41e4e0752f3d4ba2b0c31825fd8e1000e0aca4a3e62686187ef66916e35e8
|
data/bin/alphalang
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require File.expand_path('../lib/alpha', __dir__)
|
4
|
+
|
5
|
+
basic_error_msg = "Usage: alphalang [options] file.alpha\nUsage: alphalang -h for the help menu."
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = basic_error_msg
|
10
|
+
|
11
|
+
opts.on('-l', '--logger', 'Run program in a very verbose manner') do
|
12
|
+
options[:verbose] = true
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('-v', '--verify', 'Run syntax verification. Does not require a file input.') do
|
16
|
+
options[:verify] = true
|
17
|
+
end
|
18
|
+
|
19
|
+
opts.on('--lang=LOCALE', 'Set the locale language for all program keywords. Available: en, sv, de') do |lang|
|
20
|
+
options[:lang] = lang
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('--createlocale', 'Creates a new locale-file for all program keywords available.') do
|
24
|
+
options[:createlocale] = true
|
25
|
+
end
|
26
|
+
end.parse!
|
27
|
+
|
28
|
+
verbose = options[:verbose]
|
29
|
+
verify = options[:verify]
|
30
|
+
language = options[:lang] || 'en'
|
31
|
+
createlocale = options[:createlocale]
|
32
|
+
|
33
|
+
if createlocale
|
34
|
+
require_relative'../lib/lang_creator'
|
35
|
+
create()
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
raise OptionParser::MissingArgument, "No file provided.
|
40
|
+
Usage: alphalang my_file.alpha | alphalang -h" if ARGV.empty? unless verify
|
41
|
+
raise OptionParser::InvalidArgument, 'Too many files provided.
|
42
|
+
Did you mean to use an --[option]? | alphalang -h' if ARGV.length > 1
|
43
|
+
raise OptionParser::InvalidArgument, 'File must end with .alpha' unless verify or ARGV[0].end_with?('.alpha')
|
44
|
+
|
45
|
+
if verbose
|
46
|
+
require_relative '../lib/rdparse'
|
47
|
+
else
|
48
|
+
require_relative '../lib/rdparse_quiet'
|
49
|
+
end
|
50
|
+
|
51
|
+
if verify
|
52
|
+
if !ARGV.empty?
|
53
|
+
puts 'Flag for verification found. Ignoring input file.'
|
54
|
+
sleep 1
|
55
|
+
end
|
56
|
+
require_relative '../lib/tester/test_unit'
|
57
|
+
else
|
58
|
+
LangParser.new(language).parse_file(ARGV[0])
|
59
|
+
end
|
data/lib/alpha.rb
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
require_relative './nodes/stmtnodes'
|
2
|
+
|
3
|
+
class LangParser
|
4
|
+
def initialize(locale='en')
|
5
|
+
@langParser = Parser.new('lang parser', locale) do
|
6
|
+
token(/while/) { |_| :WHILE }
|
7
|
+
token(/print/) { |_| :PRINT }
|
8
|
+
token(/pause/) { |_| :PAUSE }
|
9
|
+
token(/def/) { |_| :DEF }
|
10
|
+
token(/end/) { |_| :STOP }
|
11
|
+
token(/if/) { |_| :IF }
|
12
|
+
token(/elseif/) { |_| :ELSEIF }
|
13
|
+
token(/else/) { |_| :ELSE }
|
14
|
+
token(/(false|true)/) { |m| m }
|
15
|
+
token(/(==|<=|>=)/) { |m| m }
|
16
|
+
token(/(not|!)/) { |_| :NOT }
|
17
|
+
token(/(and|&&)/) { |_| :AND }
|
18
|
+
token(/(or|\|\|)/) { |_| :OR }
|
19
|
+
token(/\s+/)
|
20
|
+
token(/\d+/) { |m| m }
|
21
|
+
token(/\w+/) { |m| m }
|
22
|
+
token(/./) { |m| m }
|
23
|
+
|
24
|
+
start :program do
|
25
|
+
match(:comp_stmt) { |comp_stmt| comp_stmt }
|
26
|
+
match(:terminal)
|
27
|
+
end
|
28
|
+
|
29
|
+
rule :terminal do
|
30
|
+
match(/\n|;/)
|
31
|
+
end
|
32
|
+
|
33
|
+
rule :comp_stmt do
|
34
|
+
match(:stmt, :comp_stmt) { |a, b| CompStmtNode.new([a, b]) }
|
35
|
+
match(:stmt)
|
36
|
+
end
|
37
|
+
|
38
|
+
rule :stmt do
|
39
|
+
match(:if_comp_stmt)
|
40
|
+
match(:while_stmt)
|
41
|
+
match(:func_dec)
|
42
|
+
match(:ass_stmt)
|
43
|
+
match(:pause_stmt)
|
44
|
+
match(:expr_stmt)
|
45
|
+
end
|
46
|
+
|
47
|
+
rule :if_comp_stmt do
|
48
|
+
match(:if_stmt, :comp_elseif, :else_stmt, :STOP) { |a, b, c| IfCompStmtNode.new(a, b, c) }
|
49
|
+
match(:if_stmt, :else_stmt, :STOP) { |a, b| IfCompStmtNode.new(a, b) }
|
50
|
+
match(:if_stmt, :STOP) { |a| IfCompStmtNode.new(a) }
|
51
|
+
end
|
52
|
+
|
53
|
+
rule :comp_elseif do
|
54
|
+
match(:elseif_stmt, :comp_elseif) { |a, b| [a, b] }
|
55
|
+
match(:elseif_stmt)
|
56
|
+
end
|
57
|
+
|
58
|
+
rule :if_stmt do
|
59
|
+
match(:IF, :expr_stmt, :and, :expr_stmt, :comp_stmt) { |_, a, b, c, d| IfCompactNode.new(a, b, c, d) }
|
60
|
+
match(:IF, :expr_stmt, :comp_stmt) { |_, a, b| IfNode.new(a, b) }
|
61
|
+
end
|
62
|
+
|
63
|
+
rule :elseif_stmt do
|
64
|
+
match(:ELSEIF, :expr_stmt, :comp_stmt) { |_, a, b| ElseifNode.new(a, b) }
|
65
|
+
end
|
66
|
+
|
67
|
+
rule :else_stmt do
|
68
|
+
match(:ELSE, :comp_stmt) { |_, b| ElseNode.new(b) }
|
69
|
+
end
|
70
|
+
|
71
|
+
rule :while_stmt do
|
72
|
+
match(:WHILE, :expr_stmt, :comp_stmt, :STOP) { |_, a, b| WhileLoopNode.new(a, b) }
|
73
|
+
end
|
74
|
+
|
75
|
+
rule :func_dec do
|
76
|
+
match(:DEF, :member, :comp_stmt, :STOP) { |_, name, value, _| FunctionDecNode.new(name, value) }
|
77
|
+
end
|
78
|
+
|
79
|
+
rule :ass_stmt do
|
80
|
+
match(:member, '=', :expr) { |var, _, value, _| VariableDecNode.new(var, value) }
|
81
|
+
match(:member, '=', :array_stmt) { |var, _, value| VariableDecNode.new(var, value) }
|
82
|
+
end
|
83
|
+
|
84
|
+
#array inte klar kan assigna till vaiabel men inte kolla upp än
|
85
|
+
rule :array_stmt do
|
86
|
+
match('[', :arg_list, ']') { |_, array, _| array }
|
87
|
+
end
|
88
|
+
|
89
|
+
rule :pause_stmt do
|
90
|
+
match(:PAUSE, :expr) { |_, a| PauseNode.new(a) }
|
91
|
+
end
|
92
|
+
|
93
|
+
rule :expr_stmt do
|
94
|
+
match(:or_stmt)
|
95
|
+
match(:and_stmt)
|
96
|
+
match(:not_stmt)
|
97
|
+
match(:expr)
|
98
|
+
end
|
99
|
+
|
100
|
+
rule :or_stmt do
|
101
|
+
match(:expr, :OR, :expr_stmt) { |a, _, b| OrNode.new(a, b) }
|
102
|
+
end
|
103
|
+
|
104
|
+
rule :and_stmt do
|
105
|
+
match(:expr, :AND, :expr_stmt) { |a, _, b| AndNode.new(a, b) }
|
106
|
+
end
|
107
|
+
|
108
|
+
rule :not_stmt do
|
109
|
+
match(:NOT, :expr_stmt) { |_, b| NotNode.new(b) }
|
110
|
+
end
|
111
|
+
|
112
|
+
rule :expr do
|
113
|
+
match(:expr, /(<|>)/, :expr) { |a, op, b| CompareNode.new(a, op, b) }
|
114
|
+
match(/(<|>)/, :expr) { |op, b| CompareNode.new(nil, op, b) }
|
115
|
+
match(:expr, /(<=|>=)/, :expr) { |a, op, b| CompareNode.new(a, op, b) }
|
116
|
+
match(/(<=|>=)/, :expr) { |op, b| CompareNode.new(nil, op, b) }
|
117
|
+
match(:expr, '==', :expr) { |a, op, b| CompareNode.new(a, op, b) }
|
118
|
+
match(:expr, '+', :term) { |a, op, b| BinaryOperationNode.new(a, op, b) }
|
119
|
+
match(:expr, '-', :term) { |a, op, b| BinaryOperationNode.new(a, op, b) }
|
120
|
+
match(:term)
|
121
|
+
end
|
122
|
+
|
123
|
+
rule :term do
|
124
|
+
match(:term, '*', :atom) { |a, op, b| BinaryOperationNode.new(a, op, b) }
|
125
|
+
match(:term, '/', :atom) { |a, op, b| BinaryOperationNode.new(a, op, b) }
|
126
|
+
match(:atom)
|
127
|
+
end
|
128
|
+
|
129
|
+
rule :atom do
|
130
|
+
match('-', /\d+/, '.', /\d+/) { |neg, a, dot, b| NumberNode.new((neg+a+dot+b)) }
|
131
|
+
match(/\d+/, '.', /\d+/) { |a, dot, b| NumberNode.new((a+dot+b)) }
|
132
|
+
match('-', /\d+/) { |neg, a| NumberNode.new(neg + a) }
|
133
|
+
match(/\d+/) { |a| NumberNode.new(a) }
|
134
|
+
match(/(false|true)/) { |a| BoolNode.new(a) }
|
135
|
+
match(:PRINT, :member) { |_, a| PrintNode.new(a) }
|
136
|
+
match(:PRINT, :expr) { |_, a| PrintNode.new(a) }
|
137
|
+
match(:member)
|
138
|
+
match(:prio_stmt)
|
139
|
+
end
|
140
|
+
|
141
|
+
rule :member do
|
142
|
+
match(/[a-z]/, '(', :arg_list, ')') { |var, _, args, _| FuncCallNode.new(var, args) }
|
143
|
+
match(/[a-z]/, '(', ')') { |var, _, _| FuncCallNode.new(var, NilClass) }
|
144
|
+
match(/[a-z]/) { |var| VariableCallNode.new(var) }
|
145
|
+
end
|
146
|
+
|
147
|
+
rule :arg_list do
|
148
|
+
match(:expr, ',', :arg_list) { |a, _, b| ArgListNode.new(a, b) }
|
149
|
+
match(:expr) { |a| ArgListNode.new(a, NilClass) }
|
150
|
+
end
|
151
|
+
|
152
|
+
rule :prio_stmt do
|
153
|
+
match('(', :stmt, ')') { |_, a, _| a }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def parse_file(filename)
|
159
|
+
file = File.read(filename)
|
160
|
+
root = @langParser.parse file
|
161
|
+
root.evaluate
|
162
|
+
end
|
163
|
+
|
164
|
+
def calc_test(str)
|
165
|
+
root = @langParser.parse str
|
166
|
+
root.evaluate
|
167
|
+
end
|
168
|
+
end
|
data/lib/lang_creator.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Function to read user input for translation
|
4
|
+
def read_translation(line)
|
5
|
+
puts "Enter the translation for: '#{line}' <RET> to accept '#{line}'"
|
6
|
+
translation = gets.chomp
|
7
|
+
translation = line if translation.empty?
|
8
|
+
translation
|
9
|
+
end
|
10
|
+
|
11
|
+
def read_translation_true_false(line)
|
12
|
+
word1 = /false/.match(line)
|
13
|
+
word2 = /true/.match(line)
|
14
|
+
puts "Enter the translation for: '#{word1}' <RET> to accept '#{word1}'"
|
15
|
+
translation = '('
|
16
|
+
input = gets.chomp
|
17
|
+
if input.empty?
|
18
|
+
translation += word1.to_s
|
19
|
+
else
|
20
|
+
translation += input
|
21
|
+
end
|
22
|
+
translation += '|'
|
23
|
+
puts "Enter the translation for: '#{word2}' <RET> to accept '#{word2}'"
|
24
|
+
input2 = gets.chomp
|
25
|
+
if input2.empty?
|
26
|
+
translation += word2.to_s
|
27
|
+
else
|
28
|
+
translation += input2
|
29
|
+
end
|
30
|
+
translation += ')'
|
31
|
+
translation
|
32
|
+
end
|
33
|
+
|
34
|
+
def read_translation_not_and_or(line)
|
35
|
+
word = /\w+/.match(line)
|
36
|
+
puts "Enter the translation for: '#{word}' <RET> to accept '#{word}'"
|
37
|
+
translation = '('
|
38
|
+
input = gets.chomp
|
39
|
+
if input.empty?
|
40
|
+
translation += word.to_s
|
41
|
+
else
|
42
|
+
translation += input
|
43
|
+
end
|
44
|
+
translation += /\|.+/.match(line).to_s
|
45
|
+
translation
|
46
|
+
end
|
47
|
+
def create()
|
48
|
+
# Prompt the user to choose a name for the translation file
|
49
|
+
puts "Choose a name for your translation file:"
|
50
|
+
name = gets.chomp
|
51
|
+
|
52
|
+
# Create an empty file to store translations
|
53
|
+
File.open(name, 'w') {}
|
54
|
+
|
55
|
+
# Read each line from the input file
|
56
|
+
locale_path = File.join(__dir__, "locales", 'locale_template')
|
57
|
+
|
58
|
+
# Prompt the user to translate the line
|
59
|
+
counter = 0
|
60
|
+
locale_thingies = File.readlines(locale_path)
|
61
|
+
locale_thingies.each do |line|
|
62
|
+
|
63
|
+
counter += 1
|
64
|
+
break if counter == 14
|
65
|
+
if counter < 9
|
66
|
+
translation = read_translation(line.chomp)
|
67
|
+
|
68
|
+
# Save translation after the original line
|
69
|
+
File.open(name, 'a') { |f| f.puts "#{line.chomp} #{translation}" }
|
70
|
+
end
|
71
|
+
if counter == 9
|
72
|
+
translation = read_translation_true_false(line.chomp)
|
73
|
+
File.open(name, 'a') { |f| f.puts "#{line.chomp} #{translation}" }
|
74
|
+
end
|
75
|
+
if counter == 10
|
76
|
+
File.open(name, 'a') { |f| f.puts "#{line.chomp} (==|<=|>=)" }
|
77
|
+
end
|
78
|
+
if counter > 10
|
79
|
+
translation = read_translation_not_and_or(line.chomp)
|
80
|
+
File.open(name, 'a') { |f| f.puts "#{line.chomp} #{translation}" }
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# Append additional translations
|
86
|
+
File.open(name, 'a') do |f|
|
87
|
+
f.puts '\s+ \s+'
|
88
|
+
f.puts '\d+ \d+'
|
89
|
+
f.puts '\w+ \w+'
|
90
|
+
f.puts '. .'
|
91
|
+
end
|
92
|
+
|
93
|
+
# Clear the screen
|
94
|
+
system("clear")
|
95
|
+
|
96
|
+
# Display the contents of the translation file
|
97
|
+
puts File.read(name)
|
98
|
+
|
99
|
+
# Ask user if the translation is correct
|
100
|
+
puts "Is this correct? [Y/n]"
|
101
|
+
answer = gets.chomp
|
102
|
+
|
103
|
+
if answer.downcase == /y|Y/ or answer.empty?
|
104
|
+
puts "Translation saved to #{name}"
|
105
|
+
|
106
|
+
# Move the translation file to the desired directory
|
107
|
+
ruby_version = "" + RUBY_VERSION.to_s
|
108
|
+
ruby_version[-1] = '0'
|
109
|
+
|
110
|
+
# Find the users installation directory and place the locale file there
|
111
|
+
if File.exist?("/home/#{ENV['USER']}/.local/share/gem/ruby/#{ruby_version}/gems/alphalang-0.1.0/lib/locales/")
|
112
|
+
File.rename(name, "/home/#{ENV['USER']}/.local/share/gem/ruby/#{ruby_version}/gems/alphalang-0.1.0/lib/locales/#{name}")
|
113
|
+
# elsif File.exist?("~/var/lib/gems/#{ruby_version}/gems/alphalang-0.1.0/lib/locales/")
|
114
|
+
# File.rename(name, "~/var/lib/gems/#{ruby_version}/gems/alphalang-0.1.0/lib/locales/#{name}")
|
115
|
+
else
|
116
|
+
raise ArgumentError, "Didn't find your .local/share/gem/ruby/<VERSION>/gems/alphalang-0.1.0
|
117
|
+
Tried Ruby <VERSION> = #{ruby_version} "
|
118
|
+
end
|
119
|
+
|
120
|
+
else
|
121
|
+
puts 'Translation removed'
|
122
|
+
File.delete(name)
|
123
|
+
end
|
124
|
+
end
|
data/lib/locales/de
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
while während
|
2
|
+
print drucken
|
3
|
+
pause pause
|
4
|
+
def def
|
5
|
+
end ende
|
6
|
+
if wenn
|
7
|
+
elseif andernfalls
|
8
|
+
else sonst
|
9
|
+
(false|true) (falsch|wahr)
|
10
|
+
(==|<=|>=) (==|<=|>=)
|
11
|
+
(not|!) (nicht|!)
|
12
|
+
(and|&&) (und|&&)
|
13
|
+
(or|\|\|) (oder|\|\|)
|
14
|
+
\s+ \s+
|
15
|
+
\d+ \d+
|
16
|
+
\w+ \w+
|
17
|
+
. .
|
data/lib/locales/en
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
while while
|
2
|
+
print print
|
3
|
+
pause pause
|
4
|
+
def def
|
5
|
+
end end
|
6
|
+
if if
|
7
|
+
elseif elseif
|
8
|
+
else else
|
9
|
+
(false|true) (false|true)
|
10
|
+
(==|<=|>=) (==|<=|>=)
|
11
|
+
(not|!) (not|!)
|
12
|
+
(and|&&) (and|&&)
|
13
|
+
(or|\|\|) (or|\|\|)
|
14
|
+
\s+ \s+
|
15
|
+
\d+ \d+
|
16
|
+
\w+ \w+
|
17
|
+
. .
|
data/lib/locales/sv
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
while medan
|
2
|
+
print skriv
|
3
|
+
pause vänta
|
4
|
+
def def
|
5
|
+
end slut
|
6
|
+
if om
|
7
|
+
elseif annarsom
|
8
|
+
else annars
|
9
|
+
(false|true) (falskt|sant)
|
10
|
+
(==|<=|>=) (==|<=|>=)
|
11
|
+
(not|!) (inte|!)
|
12
|
+
(and|&&) (och|&&)
|
13
|
+
(or|\|\|) (eller|\|\|)
|
14
|
+
\s+ \s+
|
15
|
+
\d+ \d+
|
16
|
+
\w+ \w+
|
17
|
+
. .
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require_relative 'basenodes'
|
2
|
+
|
3
|
+
####################################################
|
4
|
+
class VariableCallNode < Node
|
5
|
+
attr_accessor :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def lookup_var(name)
|
12
|
+
temp_scope_lvl = $scope_lvl
|
13
|
+
while temp_scope_lvl >= 0
|
14
|
+
if not $scopes[temp_scope_lvl].has_key?(name)
|
15
|
+
temp_scope_lvl -= 1
|
16
|
+
else
|
17
|
+
return $scopes[temp_scope_lvl][name]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def evaluate
|
23
|
+
return @value = lookup_var(@name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class VariableDecNode < Node
|
28
|
+
attr_accessor :name
|
29
|
+
|
30
|
+
def initialize(name, value)
|
31
|
+
super(value)
|
32
|
+
@name = name
|
33
|
+
end
|
34
|
+
|
35
|
+
def evaluate
|
36
|
+
$scopes[$scope_lvl][@name.name] = @value.evaluate
|
37
|
+
self
|
38
|
+
# return nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
####################################################
|
43
|
+
|
44
|
+
class FunctionDecNode < Node
|
45
|
+
def initialize(node, value)
|
46
|
+
super(value)
|
47
|
+
@name = node
|
48
|
+
@args = node.args
|
49
|
+
end
|
50
|
+
|
51
|
+
def evaluate
|
52
|
+
$scopes[0][@name.name] = [@value, @args]
|
53
|
+
return nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class FuncCallNode < Node
|
58
|
+
attr_accessor :name, :args
|
59
|
+
|
60
|
+
def initialize(name, args)
|
61
|
+
@name = name
|
62
|
+
@args = args
|
63
|
+
end
|
64
|
+
|
65
|
+
def lookup_var(name)
|
66
|
+
return $scopes[0][name]
|
67
|
+
end
|
68
|
+
|
69
|
+
def evaluate
|
70
|
+
$scopes.push({})
|
71
|
+
func = lookup_var(@name)
|
72
|
+
function_body = func[0]
|
73
|
+
function_param = func[1]
|
74
|
+
|
75
|
+
return nil if func.is_a?(NilClass)
|
76
|
+
|
77
|
+
$scope_lvl += 1
|
78
|
+
|
79
|
+
if function_param.is_a?(ArgListNode)
|
80
|
+
function_param.each do |val, index|
|
81
|
+
function_param[index] = VariableDecNode.new(function_param[index].name, @args[index])
|
82
|
+
function_param[index].evaluate
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
func_result = function_body.evaluate
|
87
|
+
old_scope_lvl = $scope_lvl
|
88
|
+
|
89
|
+
if func_result.is_a?(VariableDecNode)
|
90
|
+
$scope_lvl = 0
|
91
|
+
func_result.evaluate
|
92
|
+
$scope_lvl = old_scope_lvl
|
93
|
+
end
|
94
|
+
|
95
|
+
$scope_lvl -= 1
|
96
|
+
$scopes.pop
|
97
|
+
return func_result
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
####################################################
|
102
|
+
|
103
|
+
class IfNode < Node
|
104
|
+
attr_accessor :argument
|
105
|
+
|
106
|
+
def initialize(argument, node)
|
107
|
+
@argument, @node = argument, node
|
108
|
+
end
|
109
|
+
|
110
|
+
def evaluate
|
111
|
+
if @argument.evaluate
|
112
|
+
@value = @node.evaluate
|
113
|
+
else
|
114
|
+
@value = nil
|
115
|
+
end
|
116
|
+
@value
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class ElseifNode < Node
|
121
|
+
def initialize(argument, node)
|
122
|
+
@argument, @node = argument, node
|
123
|
+
end
|
124
|
+
def evaluate
|
125
|
+
if @argument.evaluate
|
126
|
+
@value = @node.evaluate
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class ElseNode < Node
|
132
|
+
def initialize(node)
|
133
|
+
@node = node
|
134
|
+
end
|
135
|
+
|
136
|
+
def evaluate
|
137
|
+
@value = @node.evaluate
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class IfCompStmtNode < Node
|
142
|
+
def initialize(*nodes)
|
143
|
+
@nodes = nodes
|
144
|
+
end
|
145
|
+
def evaluate
|
146
|
+
if @nodes[0].argument.evaluate
|
147
|
+
return @nodes[0].evaluate
|
148
|
+
else
|
149
|
+
return nil if @nodes[1] == nil # hmm??
|
150
|
+
return @nodes[1].evaluate
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
####################################################
|
156
|
+
|
157
|
+
class WhileLoopNode < Node
|
158
|
+
attr_accessor :condition
|
159
|
+
|
160
|
+
def initialize(condition, statement)
|
161
|
+
@condition = condition
|
162
|
+
super(statement)
|
163
|
+
end
|
164
|
+
|
165
|
+
def evaluate
|
166
|
+
while @condition.evaluate
|
167
|
+
@value.evaluate
|
168
|
+
end
|
169
|
+
self.class
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
####################################################
|
174
|
+
|
175
|
+
class PrintNode
|
176
|
+
attr_accessor :value
|
177
|
+
|
178
|
+
def initialize(value)
|
179
|
+
@value = value
|
180
|
+
end
|
181
|
+
|
182
|
+
def evaluate
|
183
|
+
puts @value.evaluate
|
184
|
+
self.class # detta kanske är trevligare än nil, åter igen den diskussionen.
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class PauseNode < Node
|
189
|
+
def initialize(value)
|
190
|
+
super(value)
|
191
|
+
end
|
192
|
+
|
193
|
+
def evaluate
|
194
|
+
sleep @value.evaluate
|
195
|
+
end
|
196
|
+
end
|