alphalang 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
+ . .
@@ -0,0 +1,17 @@
1
+ while
2
+ print
3
+ pause
4
+ def
5
+ end
6
+ if
7
+ elseif
8
+ else
9
+ (false|true)
10
+ (==|<=|>=)
11
+ (not|!)
12
+ (and|&&)
13
+ (or|\|\|)
14
+ \s+
15
+ \d+
16
+ \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