alphalang 0.1.1
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 +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
@@ -0,0 +1,237 @@
|
|
1
|
+
# This file is called rdparse.rb because it implements a Recursive
|
2
|
+
# Descent Parser. Read more about the theory on e.g.
|
3
|
+
# http://en.wikipedia.org/wiki/Recursive_descent_parser
|
4
|
+
|
5
|
+
# 2010-02-11 New version of this file for the 2010 instance of TDP007
|
6
|
+
# which handles false return values during parsing, and has an easy way
|
7
|
+
# of turning on and off debug messages.
|
8
|
+
# 2014-02-16 New version that handles { false } blocks and :empty tokens.
|
9
|
+
|
10
|
+
require 'logger'
|
11
|
+
|
12
|
+
|
13
|
+
class Rule
|
14
|
+
|
15
|
+
# A rule is created through the rule method of the Parser class, like this:
|
16
|
+
# rule :term do
|
17
|
+
# match(:term, '*', :dice) {|a, _, b| a * b }
|
18
|
+
# match(:term, '/', :dice) {|a, _, b| a / b }
|
19
|
+
# match(:dice)
|
20
|
+
# end
|
21
|
+
|
22
|
+
Match = Struct.new :pattern, :block
|
23
|
+
|
24
|
+
def initialize(name, parser)
|
25
|
+
|
26
|
+
# The name of the expressions this rule matches
|
27
|
+
@name = name
|
28
|
+
# We need the parser to recursively parse sub-expressions occurring
|
29
|
+
# within the pattern of the match objects associated with this rule
|
30
|
+
@parser = parser
|
31
|
+
@matches = []
|
32
|
+
# Left-recursive matches
|
33
|
+
@lrmatches = []
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add a matching expression to this rule, as in this example:
|
37
|
+
# match(:term, '*', :dice) {|a, _, b| a * b }
|
38
|
+
# The arguments to 'match' describe the constituents of this expression.
|
39
|
+
def match(*pattern, &block)
|
40
|
+
match = Match.new(pattern, block)
|
41
|
+
# If the pattern is left-recursive, then add it to the left-recursive set
|
42
|
+
if pattern[0] == @name
|
43
|
+
pattern.shift
|
44
|
+
@lrmatches << match
|
45
|
+
else
|
46
|
+
@matches << match
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse
|
51
|
+
# Try non-left-recursive matches first, to avoid infinite recursion
|
52
|
+
match_result = try_matches(@matches)
|
53
|
+
return nil if match_result.nil?
|
54
|
+
loop do
|
55
|
+
result = try_matches(@lrmatches, match_result)
|
56
|
+
return match_result if result.nil?
|
57
|
+
match_result = result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Try out all matching patterns of this rule
|
64
|
+
def try_matches(matches, pre_result = nil)
|
65
|
+
match_result = nil
|
66
|
+
# Begin at the current position in the input string of the parser
|
67
|
+
start = @parser.pos
|
68
|
+
matches.each do |match|
|
69
|
+
# pre_result is a previously available result from evaluating expressions
|
70
|
+
result = pre_result.nil? ? [] : [pre_result]
|
71
|
+
|
72
|
+
# We iterate through the parts of the pattern, which may be e.g.
|
73
|
+
# [:expr,'*',:term]
|
74
|
+
match.pattern.each_with_index do |token,index|
|
75
|
+
|
76
|
+
# If this "token" is a compound term, add the result of
|
77
|
+
# parsing it to the "result" array
|
78
|
+
if @parser.rules[token]
|
79
|
+
result << @parser.rules[token].parse
|
80
|
+
if result.last.nil?
|
81
|
+
result = nil
|
82
|
+
break
|
83
|
+
end
|
84
|
+
|
85
|
+
else
|
86
|
+
# Otherwise, we consume the token as part of applying this rule
|
87
|
+
nt = @parser.expect(token)
|
88
|
+
if nt
|
89
|
+
result << nt
|
90
|
+
if @lrmatches.include?(match.pattern) then
|
91
|
+
pattern = [@name]+match.pattern
|
92
|
+
else
|
93
|
+
pattern = match.pattern
|
94
|
+
end
|
95
|
+
|
96
|
+
else
|
97
|
+
result = nil
|
98
|
+
break
|
99
|
+
end
|
100
|
+
end # pattern.each
|
101
|
+
end # matches.each
|
102
|
+
if result
|
103
|
+
if match.block
|
104
|
+
match_result = match.block.call(*result)
|
105
|
+
else
|
106
|
+
match_result = result[0]
|
107
|
+
end
|
108
|
+
|
109
|
+
break
|
110
|
+
else
|
111
|
+
# If this rule did not match the current token list, move
|
112
|
+
# back to the scan position of the last match
|
113
|
+
@parser.pos = start
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
return match_result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class Parser
|
122
|
+
|
123
|
+
attr_accessor :pos
|
124
|
+
attr_reader :rules, :string, :logger
|
125
|
+
|
126
|
+
class ParseError < RuntimeError
|
127
|
+
end
|
128
|
+
|
129
|
+
def initialize(language_name, locale='en', &block)
|
130
|
+
|
131
|
+
locales_path = File.join(__dir__, "locales", locale)
|
132
|
+
token_pairs = File.readlines(locales_path)
|
133
|
+
@token_list = Hash.new
|
134
|
+
token_pairs.each do |pair|
|
135
|
+
default_value, locale_value = pair.split(' ')
|
136
|
+
@token_list[default_value] = locale_value
|
137
|
+
end
|
138
|
+
|
139
|
+
@lex_tokens = []
|
140
|
+
@rules = {}
|
141
|
+
@start = nil
|
142
|
+
@language_name = language_name
|
143
|
+
instance_eval(&block)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Tokenize the string into small pieces
|
147
|
+
def tokenize(string)
|
148
|
+
@tokens = []
|
149
|
+
@string = string.clone
|
150
|
+
until string.empty?
|
151
|
+
# Unless any of the valid tokens of our language are the prefix of
|
152
|
+
# 'string', we fail with an exception
|
153
|
+
raise ParseError, "unable to lex '#{string}" unless @lex_tokens.any? do |tok|
|
154
|
+
match = tok.pattern.match(string)
|
155
|
+
# The regular expression of a token has matched the beginning of 'string'
|
156
|
+
if match
|
157
|
+
|
158
|
+
# Also, evaluate this expression by using the block
|
159
|
+
# associated with the token
|
160
|
+
@tokens << tok.block.call(match.to_s) if tok.block
|
161
|
+
# consume the match and proceed with the rest of the string
|
162
|
+
string = match.post_match
|
163
|
+
true
|
164
|
+
else
|
165
|
+
# this token pattern did not match, try the next
|
166
|
+
false
|
167
|
+
end # if
|
168
|
+
end # raise
|
169
|
+
end # until
|
170
|
+
end
|
171
|
+
|
172
|
+
def parse(string)
|
173
|
+
# First, split the string according to the "token" instructions given.
|
174
|
+
# Afterwards @tokens contains all tokens that are to be parsed.
|
175
|
+
tokenize(string)
|
176
|
+
|
177
|
+
# These variables are used to match if the total number of tokens
|
178
|
+
# are consumed by the parser
|
179
|
+
@pos = 0
|
180
|
+
@max_pos = 0
|
181
|
+
@expected = []
|
182
|
+
# Parse (and evaluate) the tokens received
|
183
|
+
result = @start.parse
|
184
|
+
# If there are unparsed extra tokens, signal error
|
185
|
+
if @pos != @tokens.size
|
186
|
+
raise ParseError, "Parse error. expected: '#{@expected.join(', ')}', found '#{@tokens[@max_pos]}'"
|
187
|
+
end
|
188
|
+
return result
|
189
|
+
end
|
190
|
+
|
191
|
+
def next_token
|
192
|
+
@pos += 1
|
193
|
+
return @tokens[@pos - 1]
|
194
|
+
end
|
195
|
+
|
196
|
+
# Return the next token in the queue
|
197
|
+
def expect(tok)
|
198
|
+
return tok if tok == :empty
|
199
|
+
t = next_token
|
200
|
+
if @pos - 1 > @max_pos
|
201
|
+
@max_pos = @pos - 1
|
202
|
+
@expected = []
|
203
|
+
end
|
204
|
+
return t if tok === t
|
205
|
+
@expected << tok if @max_pos == @pos - 1 && !@expected.include?(tok)
|
206
|
+
return nil
|
207
|
+
end
|
208
|
+
|
209
|
+
def to_s
|
210
|
+
"Parser for #{@language_name}"
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
|
215
|
+
LexToken = Struct.new(:pattern, :block)
|
216
|
+
|
217
|
+
def token(pattern, &block)
|
218
|
+
@lex_tokens << LexToken.new(Regexp.new('\\A' + @token_list[pattern.source]), block)
|
219
|
+
end
|
220
|
+
|
221
|
+
def start(name, &block)
|
222
|
+
rule(name, &block)
|
223
|
+
@start = @rules[name]
|
224
|
+
end
|
225
|
+
|
226
|
+
def rule(name,&block)
|
227
|
+
@current_rule = Rule.new(name, self)
|
228
|
+
@rules[name] = @current_rule
|
229
|
+
instance_eval &block # In practise, calls match 1..N times
|
230
|
+
@current_rule = nil
|
231
|
+
end
|
232
|
+
|
233
|
+
def match(*pattern, &block)
|
234
|
+
# Basically calls memberfunction "match(*pattern, &block)
|
235
|
+
@current_rule.send(:match, *pattern, &block)
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
class TestArithmetic < Test::Unit::TestCase
|
4
|
+
def test_addition
|
5
|
+
assert_equal(3, LangParser.new.calc_test('1 + 2'))
|
6
|
+
assert_equal(3, LangParser.new.calc_test('(1 + 2)'))
|
7
|
+
assert_equal(3, LangParser.new.calc_test('((1 + 2))'))
|
8
|
+
|
9
|
+
assert_equal(6, LangParser.new.calc_test('1 + 2 + 3'))
|
10
|
+
assert_equal(6, LangParser.new.calc_test('(1 + 2) + 3'))
|
11
|
+
assert_equal(6, LangParser.new.calc_test('((1 + 2) + 3)'))
|
12
|
+
assert_equal(10, LangParser.new.calc_test('((1 + 2) + 3) + 4'))
|
13
|
+
assert_equal(10, LangParser.new.calc_test('4 + ((3) + (2 + 1))'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_subtraction
|
17
|
+
assert_equal(1, LangParser.new.calc_test('2 - 1'))
|
18
|
+
assert_equal(-3, LangParser.new.calc_test('(-2) - 1'))
|
19
|
+
assert_equal(1, LangParser.new.calc_test('(2 - 1)'))
|
20
|
+
assert_equal(1, LangParser.new.calc_test('((2 - 1))'))
|
21
|
+
|
22
|
+
assert_equal(0, LangParser.new.calc_test('3 - 2 - 1'))
|
23
|
+
assert_equal(0, LangParser.new.calc_test('(3 - 2) - 1'))
|
24
|
+
assert_equal(0, LangParser.new.calc_test('((3 - 2)) - 1'))
|
25
|
+
assert_equal(2, LangParser.new.calc_test('(4 - (3 - 2)) - 1'))
|
26
|
+
assert_equal(2, LangParser.new.calc_test('(4 - ((3) - 2)) - 1'))
|
27
|
+
assert_equal(4, LangParser.new.calc_test('4 - (((3) - 2) - 1)'))
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_multiply
|
31
|
+
assert_equal(2, LangParser.new.calc_test('2 * 1'))
|
32
|
+
assert_equal(2, LangParser.new.calc_test('1 * 2'))
|
33
|
+
assert_equal(2, LangParser.new.calc_test('1 * (2)'))
|
34
|
+
assert_equal(2, LangParser.new.calc_test('(1) * (2)'))
|
35
|
+
|
36
|
+
assert_equal(6, LangParser.new.calc_test('(1) * (2 * 3)'))
|
37
|
+
assert_equal(6, LangParser.new.calc_test('(1 * 2 * 3)'))
|
38
|
+
assert_equal(6, LangParser.new.calc_test('(1 * 2) * 3'))
|
39
|
+
assert_equal(18, LangParser.new.calc_test('(3) * 2 * (3)'))
|
40
|
+
assert_equal(-6, LangParser.new.calc_test('(3) * (0 - 2) * (1)'))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_division
|
44
|
+
assert_equal(2, LangParser.new.calc_test('2 / 1'))
|
45
|
+
assert_equal(1, LangParser.new.calc_test('2 / 2'))
|
46
|
+
assert_equal(0.5, LangParser.new.calc_test('1 / 2'))
|
47
|
+
assert_equal(-0.5, LangParser.new.calc_test('-1 / 2'))
|
48
|
+
assert_equal(-2.5, LangParser.new.calc_test('-5 / 2'))
|
49
|
+
|
50
|
+
assert_equal(0, LangParser.new.calc_test('(-1 + 1) / 2'))
|
51
|
+
assert_equal(1, LangParser.new.calc_test('(3 / (3 / 1)) / 1'))
|
52
|
+
assert_equal(1, LangParser.new.calc_test('(3 / (3 / 1)) / (1)'))
|
53
|
+
assert_equal(3, LangParser.new.calc_test('(3 / (3 / 1-1-1)) / (1)'))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TestLogic < Test::Unit::TestCase
|
58
|
+
def test_logic
|
59
|
+
assert_equal(true, LangParser.new.calc_test('true'))
|
60
|
+
assert_equal(true, LangParser.new.calc_test('true and true'))
|
61
|
+
assert_equal(true, LangParser.new.calc_test('true or true'))
|
62
|
+
assert_equal(true, LangParser.new.calc_test('true or false'))
|
63
|
+
assert_equal(true, LangParser.new.calc_test(' not false'))
|
64
|
+
|
65
|
+
assert_equal(false, LangParser.new.calc_test('false'))
|
66
|
+
assert_equal(false, LangParser.new.calc_test('false and false'))
|
67
|
+
assert_equal(false, LangParser.new.calc_test('false and true'))
|
68
|
+
assert_equal(false, LangParser.new.calc_test('not true'))
|
69
|
+
|
70
|
+
assert_equal(true, LangParser.new.calc_test('(not false) and true'))
|
71
|
+
assert_equal(true, LangParser.new.calc_test('(not false) or false'))
|
72
|
+
assert_equal(true, LangParser.new.calc_test('true and true or false'))
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class TestComparisons < Test::Unit::TestCase
|
78
|
+
def test_comparisons
|
79
|
+
assert_equal(true, LangParser.new.calc_test('1 < 2'))
|
80
|
+
assert_equal(false, LangParser.new.calc_test('1 > 2'))
|
81
|
+
assert_equal(true, LangParser.new.calc_test('1 < 2 and true'))
|
82
|
+
assert_equal(false, LangParser.new.calc_test('1 > 2 and true'))
|
83
|
+
assert_equal(false, LangParser.new.calc_test('1 > 2 + 3 and true'))
|
84
|
+
assert_equal(true, LangParser.new.calc_test('1+2 < 2+2 and true'))
|
85
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 > 2 and true'))
|
86
|
+
assert_equal(true, LangParser.new.calc_test(' true and not 1 > 2'))
|
87
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 > 2 and true'))
|
88
|
+
|
89
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 > 2 and true or false'))
|
90
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 > 2 and (true or false)'))
|
91
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 > 2 and false or true and true'))
|
92
|
+
|
93
|
+
assert_equal(true, LangParser.new.calc_test(' 1 == 1'))
|
94
|
+
assert_equal(false, LangParser.new.calc_test(' 1 == 2'))
|
95
|
+
assert_equal(true, LangParser.new.calc_test(' not 1 == 2'))
|
96
|
+
assert_equal(false, LangParser.new.calc_test(' not 1 == 1'))
|
97
|
+
|
98
|
+
assert_equal(true, LangParser.new.calc_test(' 1 <= 1'))
|
99
|
+
assert_equal(false, LangParser.new.calc_test(' 3 <= 2'))
|
100
|
+
assert_equal(true, LangParser.new.calc_test(' 1 <= 2'))
|
101
|
+
|
102
|
+
assert_equal(true, LangParser.new.calc_test(' 1 >= 1'))
|
103
|
+
assert_equal(true, LangParser.new.calc_test(' 3 >= 2'))
|
104
|
+
assert_equal(false, LangParser.new.calc_test(' 1 >= 2'))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class TestIf < Test::Unit::TestCase
|
109
|
+
def test_if
|
110
|
+
assert_equal(2, LangParser.new.calc_test(' if true
|
111
|
+
1+1
|
112
|
+
end'))
|
113
|
+
|
114
|
+
assert_equal(2, LangParser.new.calc_test(' if 3 == 3
|
115
|
+
1+1
|
116
|
+
end'))
|
117
|
+
|
118
|
+
assert_equal(nil, LangParser.new.calc_test('if 3 == 2
|
119
|
+
1+1
|
120
|
+
end'))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
class TestVariables < Test::Unit::TestCase
|
124
|
+
def test_variables
|
125
|
+
assert_equal(1, LangParser.new.calc_test('x = 1
|
126
|
+
x'))
|
127
|
+
|
128
|
+
assert_equal(1, LangParser.new.calc_test('x = 1
|
129
|
+
x
|
130
|
+
x'))
|
131
|
+
|
132
|
+
assert_equal(1, LangParser.new.calc_test('x = 1
|
133
|
+
x
|
134
|
+
x + 1
|
135
|
+
x'))
|
136
|
+
|
137
|
+
assert_equal(3, LangParser.new.calc_test('x = 1
|
138
|
+
x + 2'))
|
139
|
+
|
140
|
+
assert_equal(2, LangParser.new.calc_test('x = 1
|
141
|
+
x = 2
|
142
|
+
x'))
|
143
|
+
|
144
|
+
assert_equal(5, LangParser.new.calc_test('x = 1 + 2
|
145
|
+
x + 2'))
|
146
|
+
|
147
|
+
assert_equal(5, LangParser.new.calc_test('x = 1 + 2
|
148
|
+
x = x + 2
|
149
|
+
x'))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class TestFunction < Test::Unit::TestCase
|
154
|
+
def test_function
|
155
|
+
assert_equal(nil, LangParser.new.calc_test(' def foo()
|
156
|
+
5+5
|
157
|
+
end'))
|
158
|
+
|
159
|
+
assert_equal(10, LangParser.new.calc_test(' def foo()
|
160
|
+
5+5
|
161
|
+
end
|
162
|
+
foo()'))
|
163
|
+
|
164
|
+
assert_equal(10, LangParser.new.calc_test(' def boo()
|
165
|
+
a = 5
|
166
|
+
a
|
167
|
+
end
|
168
|
+
b = 5 + boo()
|
169
|
+
b'))
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class TestLoop < Test::Unit::TestCase
|
174
|
+
def test_while
|
175
|
+
assert_equal(WhileLoopNode, LangParser.new.calc_test('x = 5
|
176
|
+
while x < 10
|
177
|
+
x = x + 1
|
178
|
+
end'))
|
179
|
+
|
180
|
+
assert_equal(10, LangParser.new.calc_test('x = 5
|
181
|
+
while x < 10
|
182
|
+
x = x + 1
|
183
|
+
end
|
184
|
+
x'))
|
185
|
+
|
186
|
+
assert_equal(-10, LangParser.new.calc_test('x = 0
|
187
|
+
while x > -10
|
188
|
+
x = x - 1
|
189
|
+
end
|
190
|
+
x'))
|
191
|
+
|
192
|
+
# assert_equal(0, LangParser.new.calc_test('x = 10
|
193
|
+
# while -x < 0 # fundera på negering av variabler
|
194
|
+
# x = x + 1
|
195
|
+
# end
|
196
|
+
# x'))
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
class TesCompactIf < Test::Unit::TestCase
|
201
|
+
def test_CompactIf
|
202
|
+
assert_equal(4, LangParser.new.calc_test('x = 4
|
203
|
+
if 7 <= 10 and > 5
|
204
|
+
x
|
205
|
+
end'))
|
206
|
+
|
207
|
+
assert_equal(8, LangParser.new.calc_test('x = 8
|
208
|
+
if x < 10 and > 5
|
209
|
+
x
|
210
|
+
end'))
|
211
|
+
|
212
|
+
assert_equal(nil, LangParser.new.calc_test('x = 2
|
213
|
+
if x <= 10 and >= 5
|
214
|
+
x
|
215
|
+
end'))
|
216
|
+
end
|
217
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alphalang
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mattias
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-05-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: optparse
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.3.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.3.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: logger
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.5'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.5.0
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.5'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.5.0
|
53
|
+
description: Abstract Syntax Tree building language with a recursive descent parser
|
54
|
+
email:
|
55
|
+
- mattiasreuterskiold@gmail.com
|
56
|
+
executables:
|
57
|
+
- alphalang
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- bin/alphalang
|
62
|
+
- lib/alpha.rb
|
63
|
+
- lib/lang_creator.rb
|
64
|
+
- lib/locales/de
|
65
|
+
- lib/locales/en
|
66
|
+
- lib/locales/locale_template
|
67
|
+
- lib/locales/sv
|
68
|
+
- lib/nodes/#stmtnodes.rb#
|
69
|
+
- lib/nodes/basenodes.rb
|
70
|
+
- lib/nodes/stmtnodes.rb
|
71
|
+
- lib/rdparse.rb
|
72
|
+
- lib/rdparse_quiet.rb
|
73
|
+
- lib/tester/fibonacci.alpha
|
74
|
+
- lib/tester/test_unit.rb
|
75
|
+
homepage: https://portfolio.reuterskiold.dev
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubygems_version: 3.5.4
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: alphalanguage
|
98
|
+
test_files: []
|