alphalang 0.1.5 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9d0971b25f1f629686a4ca72899a014ab9dd0934b3021e1509faa46870e79fc
4
- data.tar.gz: 7ff3c836669793b4b58deea30bd8e8c485ca7ce9465ab3ac6ef490b8a7508d04
3
+ metadata.gz: daa1ca143b51a415a7888d29f6cec78e41fddaa637685af3534708c40cc6de5a
4
+ data.tar.gz: b2c26c887f7fcf6f14f4efab2787d61a1ce9f7df8e6cb872bfc0b2b7184fa961
5
5
  SHA512:
6
- metadata.gz: 7a44e1156d6e59488c1891af9eaa3d9a304ddd812b54ad44656762d169d84a2c1df057a8030654aea52c791037dfc1620a551b0e72b4f8882b20ea8d9c45edc2
7
- data.tar.gz: 1459484c62af5206acf1d9e657f25fae40cc8adfbb36838c59e1a37434034be283bdb48fbe4efb820eb0c6cb779e2a933925d4cbcc35796769df56e0bcce5f20
6
+ metadata.gz: f811511f84666e1148ea41d5706ed8289482dd8df76d2f0c3f25ebc8513ccf79b1869f83a35f586cbc6af0c1ded8f3ecf28403dc8495562a7f0d034daa0cc16b
7
+ data.tar.gz: e62cf96b852544722eb6aa3c33e9cbbc32bb5eb3fa03aec71d89121736be7c78f2a027e0b1885419eec53385afa2787a1a8b9d5953aa6720cb8571bd3749b8d2
data/bin/alphalang CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'optparse'
3
3
  require File.expand_path('../lib/alpha', __dir__)
4
+ require_relative '../lib/rdparse'
4
5
  ALPHA_VER = '0.1.5'.freeze
5
6
  ABORT_ANSWERS = [' ', '', 'none', 'abort'].freeze # something here? Some cases empty means yes tho..
6
7
  LOCALES_PATH = File.join(__dir__, '../lib/locales')
@@ -98,12 +99,6 @@ raise OptionParser::InvalidArgument, 'Too many files provided.
98
99
  Did you mean to use an --[option]? | alphalang -h' if ARGV.length > 1
99
100
  raise OptionParser::InvalidArgument, 'File must end with .alpha' unless verify_flag or ARGV[0].end_with?('.alpha')
100
101
 
101
- if verbose_flag
102
- require_relative '../lib/rdparse'
103
- else
104
- require_relative '../lib/rdparse_quiet'
105
- end
106
-
107
102
  if verify_flag
108
103
  unless ARGV.empty?
109
104
  puts 'Flag for verification found. Ignoring input file.'
@@ -111,5 +106,5 @@ if verify_flag
111
106
  end
112
107
  require_relative '../lib/tester/test_unit'
113
108
  else
114
- LangParser.new(language_flag).parse_file(ARGV[0])
109
+ LangParser.new(language_flag, verbose_flag).parse_file(ARGV[0])
115
110
  end
data/lib/alpha.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require_relative './nodes/scopemanager'
2
2
 
3
3
  class LangParser
4
- def initialize(locale = 'default')
5
- @langParser = Parser.new('lang parser', locale) do
4
+ def initialize(locale = 'default', debug_mode = false)
5
+
6
+ @langParser = Parser.new('lang parser', debug_mode, locale) do
6
7
  token(/;;.*$/)
7
8
  token(/while/) { |_| :WHILE }
8
9
  token(/print/) { |_| :PRINT }
@@ -137,6 +138,8 @@ class LangParser
137
138
  match('-', /\d+/) { |neg, a| NumberNode.new(neg + a) }
138
139
  match(/\d+/) { |a| NumberNode.new(a) }
139
140
  match(/(false|true)/) { |a| BoolNode.new(a) }
141
+ match(ScopeManager.true_value) { |a| BoolNode.new(a) }
142
+ match(ScopeManager.false_value) { |a| BoolNode.new(a) }
140
143
  match(:PRINT, :member) { |_, a| PrintNode.new(a) }
141
144
  match(:PRINT, :expr) { |_, a| PrintNode.new(a) }
142
145
  match(:member)
@@ -7,8 +7,7 @@ def set_default_locale(new_locale)
7
7
 
8
8
  available_locales.each do |locale|
9
9
  if locale == new_locale
10
- File.rename("#{LOCALES_PATH}/default", "#{LOCALES_PATH}/default.old")
11
- File.copy_stream("#{LOCALES_PATH}/#{new_locale}", "#{LOCALES_PATH}/default")
10
+ File.open("#{LOCALES_PATH}/default", 'w') { |f| f.write(new_locale)}
12
11
  puts "[alphalang] Default syntax locale is now set to #{locale}."
13
12
  return
14
13
  end
data/lib/locale_lister.rb CHANGED
@@ -20,7 +20,7 @@ def clean_locale_file_to_array(locale_name)
20
20
 
21
21
  clean_locale_file_array = []
22
22
  locale_file.each do |line|
23
- line.scan(/\b\p{Word}+\b/) do |word|
23
+ line.scan(/\p{Word}+[|]\p{Word}+|\p{Word}+/) do |word|
24
24
  clean_locale_file_array << word if word.size > 1
25
25
  end
26
26
  end
@@ -28,15 +28,18 @@ def clean_locale_file_to_array(locale_name)
28
28
  end
29
29
 
30
30
  def print_clean_locale_array(locale_name, clean_array)
31
- header = "\n[alphalang] Syntax for locale <#{locale_name}>."
31
+ longest_word = clean_array.max_by(&:length).size
32
+ padding = ' ' * (longest_word/2-5)
33
+
34
+ header = "#{padding}[alphalang] Syntax for locale <#{locale_name}>.#{padding}"
32
35
  puts header
33
36
  puts '+' * (header.size - 2)
34
37
  clean_line = ''
35
38
  clean_array.each_with_index do |word, index|
36
39
  if index.even?
37
- clean_line += "+ #{word}"
40
+ clean_line += "+ #{word}"
38
41
  else
39
- clean_line += (' ' * (20 - clean_line.size)) + "#{word}"
42
+ clean_line += (' ' * (20 -clean_line.size)) + "#{word}"
40
43
  clean_line += (' ' * (header.size - clean_line.size - 3) + '+')
41
44
  puts clean_line
42
45
  clean_line = ''
@@ -49,6 +52,10 @@ def list_specific_locale_file()
49
52
  list_locale_files
50
53
  specific_locale = gets.chomp
51
54
 
55
+ if specific_locale == 'default'
56
+ specific_locale = File.read("#{LOCALES_PATH}/#{specific_locale}")
57
+ end
58
+
52
59
  return if ABORT_ANSWERS.include?(specific_locale)
53
60
 
54
61
  specific_locale_array = clean_locale_file_to_array(specific_locale)
data/lib/locales/default CHANGED
@@ -1,18 +1 @@
1
- ;;.*$ ;;.*$
2
- while while
3
- print print
4
- pause pause
5
- def def
6
- end end
7
- if if
8
- elseif elseif
9
- else else
10
- (false|true) (false|true)
11
- (==|<=|>=) (==|<=|>=)
12
- (not|!) (not|!)
13
- (and|&&) (and|&&)
14
- (or|\|\|) (or|\|\|)
15
- \s+ \s+
16
- \d+ \d+
17
- \w+ \w+
18
- . .
1
+ en
@@ -59,8 +59,8 @@ end
59
59
  class BoolNode < Node
60
60
  def initialize(value)
61
61
  @value = false
62
- @value = true if value == "true"
63
- @value = false if value == "false"
62
+ @value = true if value == ScopeManager.true_value
63
+ @value = false if value == ScopeManager.false_value
64
64
  end
65
65
 
66
66
  def evaluate
@@ -2,52 +2,64 @@ require_relative 'stmtnodes'
2
2
 
3
3
  ####################################################
4
4
 
5
- $scopes = [{}]
6
- $scope_lvl = 0
7
5
  $test_nodes = false
8
6
 
9
- # Need to figure out how to move the scopes in here as class members in a sane way
10
7
  class ScopeManager
8
+ def initialize(true_value, false_value)
9
+ @@true_value = true_value
10
+ @@false_value = false_value
11
+ @@scopes = [{}]
12
+ @@scope_lvl = 0
13
+ end
14
+
15
+ def self.true_value
16
+ @@true_value
17
+ end
18
+
19
+ def self.false_value
20
+ @@false_value
21
+ end
22
+
11
23
  def self.scope_lvl
12
- $scope_lvl
24
+ @@scope_lvl
13
25
  end
14
26
 
15
27
  def self.scope_lvl=(value)
16
- $scope_lvl = value
28
+ @@scope_lvl = value
17
29
  end
18
30
 
19
31
  def self.lookup_var(name)
20
- temp_scope_lvl = $scope_lvl
32
+ temp_scope_lvl = @@scope_lvl
21
33
  while temp_scope_lvl >= 0
22
- if !$scopes[temp_scope_lvl].key?(name)
34
+ if !@@scopes[temp_scope_lvl].key?(name)
23
35
  temp_scope_lvl -= 1
24
36
  else
25
- return $scopes[temp_scope_lvl][name]
37
+ return @@scopes[temp_scope_lvl][name]
26
38
  end
27
39
  end
28
40
  raise ArgumentError, "Variable '#{name}' is not defined" unless @value
29
41
  end
30
42
 
31
43
  def self.increment_scope_level
32
- $scope_lvl += 1
33
- $scopes.push({})
44
+ @@scope_lvl += 1
45
+ @@scopes.push({})
34
46
  end
35
47
 
36
48
  def self.decrement_scope_level
37
- $scope_lvl -= 1
38
- $scopes.pop
49
+ @@scope_lvl -= 1
50
+ @@scopes.pop
39
51
  end
40
52
 
41
53
  def self.lookup_func(name)
42
- raise ArgumentError, "Function '#{name}' is not defined" if $scopes[0][name].is_a?(NilClass)
43
- return $scopes[0][name]
54
+ raise ArgumentError, "Function '#{name}' is not defined" if @@scopes[0][name].is_a?(NilClass)
55
+ return @@scopes[0][name]
44
56
  end
45
57
 
46
58
  def self.add_to_current_scope(name, value)
47
- $scopes[$scope_lvl][name.name] = value.evaluate
59
+ @@scopes[@@scope_lvl][name.name] = value.evaluate
48
60
  end
49
61
 
50
62
  def self.add_func_to_global_scope(name, value, args)
51
- $scopes[0][name.name] = [value, args]
63
+ @@scopes[0][name.name] = [value, args]
52
64
  end
53
65
  end
data/lib/rdparse.rb CHANGED
@@ -20,8 +20,9 @@ class Rule
20
20
 
21
21
  Match = Struct.new :pattern, :block
22
22
 
23
- def initialize(name, parser)
23
+ def initialize(name, parser, debug_bool)
24
24
  @logger = parser.logger
25
+ @debug_mode = debug_bool
25
26
  # The name of the expressions this rule matches
26
27
  @name = name
27
28
  # We need the parser to recursively parse sub-expressions occurring
@@ -80,7 +81,7 @@ class Rule
80
81
  result = nil
81
82
  break
82
83
  end
83
- @logger.debug("Matched '#{@name} = #{match.pattern[index..-1].inspect}'")
84
+ @logger.debug("Matched '#{@name} = #{match.pattern[index..-1].inspect}'") if @debug_mode
84
85
  else
85
86
  # Otherwise, we consume the token as part of applying this rule
86
87
  nt = @parser.expect(token)
@@ -91,7 +92,7 @@ class Rule
91
92
  else
92
93
  pattern = match.pattern
93
94
  end
94
- @logger.debug("Matched token '#{nt}' as part of rule '#{@name} <= #{pattern.inspect}'")
95
+ @logger.debug("Matched token '#{nt}' as part of rule '#{@name} <= #{pattern.inspect}'") if @debug_mode
95
96
  else
96
97
  result = nil
97
98
  break
@@ -104,7 +105,7 @@ class Rule
104
105
  else
105
106
  match_result = result[0]
106
107
  end
107
- @logger.debug("'#{@parser.string[start..@parser.pos-1]}' matched '#{@name}' and generated '#{match_result.inspect}'") unless match_result.nil?
108
+ @logger.debug("'#{@parser.string[start..@parser.pos-1]}' matched '#{@name}' and generated '#{match_result.inspect}'") unless match_result.nil? if @debug_mode
108
109
  break
109
110
  else
110
111
  # If this rule did not match the current token list, move
@@ -118,28 +119,45 @@ class Rule
118
119
  end
119
120
 
120
121
  class Parser
121
-
122
122
  attr_accessor :pos
123
123
  attr_reader :rules, :string, :logger
124
124
 
125
125
  class ParseError < RuntimeError
126
126
  end
127
127
 
128
- def initialize(language_name, locale = 'default', &block)
128
+ def initialize(language_name, debug_bool, locale, &block)
129
+ @debug_mode = debug_bool
130
+ @logger = Logger.new(STDOUT) if @debug_mode
131
+ @lex_tokens = []
132
+ @rules = {}
133
+ @start = nil
134
+ @language_name = language_name
135
+
136
+ create_tokens_from_locale(locale)
137
+
138
+ false_value = @token_list['(false|true)'].split('|')[0]# Hacky solution to convoluted tokens
139
+ true_value = @token_list['(false|true)'].split('|')[1]
140
+ true_value = true_value[0..-2]
141
+ false_value = false_value[1..]
142
+
143
+ ScopeManager.new(true_value, false_value) # Hacky solution to convoluted tokens
144
+
145
+ instance_eval(&block)
146
+ end
129
147
 
130
- token_pairs = File.readlines("#{LOCALES_PATH}/#{locale}")
148
+ # Recreate the tokenlist using locale_template and the chosen locale file
149
+ def create_tokens_from_locale(locale)
150
+ if locale == 'default'
151
+ lang_file = File.read("#{LOCALES_PATH}/#{locale}")
152
+ token_pairs = File.readlines("#{LOCALES_PATH}/#{lang_file}")
153
+ else
154
+ token_pairs = File.readlines("#{LOCALES_PATH}/#{locale}")
155
+ end
131
156
  @token_list = Hash.new
132
157
  token_pairs.each do |pair|
133
158
  default_value, locale_value = pair.split(' ')
134
159
  @token_list[default_value] = locale_value
135
160
  end
136
-
137
- @logger = Logger.new(STDOUT)
138
- @lex_tokens = []
139
- @rules = {}
140
- @start = nil
141
- @language_name = language_name
142
- instance_eval(&block)
143
161
  end
144
162
 
145
163
  # Tokenize the string into small pieces
@@ -153,7 +171,7 @@ class Parser
153
171
  match = tok.pattern.match(string)
154
172
  # The regular expression of a token has matched the beginning of 'string'
155
173
  if match
156
- @logger.debug("Token #{match[0]} consumed as #{match[0]}")
174
+ @logger.debug("Token #{match[0]} consumed as #{match[0]}") if @debug_mode
157
175
  # Also, evaluate this expression by using the block
158
176
  # associated with the token
159
177
  @tokens << tok.block.call(match.to_s) if tok.block
@@ -182,6 +200,11 @@ class Parser
182
200
  result = @start.parse
183
201
  # If there are unparsed extra tokens, signal error
184
202
  if @pos != @tokens.size
203
+
204
+ if @tokens[@max_pos] == '(' || @tokens[@max_pos] == ')'
205
+ raise ParseError, 'Mismatched parenthesis! In Emacs: M-x check-parens RET'
206
+ end
207
+
185
208
  raise ParseError, "Parse error. expected: '#{@expected.join(', ')}', found '#{@tokens[@max_pos]}'"
186
209
  end
187
210
  return result
@@ -223,7 +246,7 @@ class Parser
223
246
  end
224
247
 
225
248
  def rule(name,&block)
226
- @current_rule = Rule.new(name, self)
249
+ @current_rule = Rule.new(name, self, @debug_mode)
227
250
  @rules[name] = @current_rule
228
251
  instance_eval &block # In practise, calls match 1..N times
229
252
  @current_rule = nil
@@ -1,217 +1,241 @@
1
- require 'test/unit'
1
+ require "test/unit"
2
+ require_relative "../locale_lister"
3
+
4
+ locale_used = File.read("#{LOCALES_PATH}/#{"default"}")
5
+ words_array = clean_locale_file_to_array(locale_used)
6
+ word_pair_hash = {}
7
+ words_array.each_with_index do |word, index|
8
+ if index.even?
9
+ word_pair_hash[word] = words_array[index + 1]
10
+ end
11
+ end
12
+
13
+ $while = word_pair_hash["while"]
14
+ $print = word_pair_hash["print"]
15
+ $pause = word_pair_hash["pause"]
16
+ $def = word_pair_hash["def"]
17
+ $end = word_pair_hash["end"]
18
+ $if = word_pair_hash["if"]
19
+ $else_if = word_pair_hash["elseif"]
20
+ $else = word_pair_hash["else"]
21
+ $false = word_pair_hash["false|true"].split("|")[0]
22
+ $true = word_pair_hash["false|true"].split("|")[1]
23
+ $not = word_pair_hash["not"]
24
+ $and = word_pair_hash["and"]
25
+ $or = word_pair_hash["or"]
2
26
 
3
27
  class TestArithmetic < Test::Unit::TestCase
4
28
  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))'))
29
+ assert_equal(3, LangParser.new.calc_test("1 + 2"))
30
+ assert_equal(3, LangParser.new.calc_test("(1 + 2)"))
31
+ assert_equal(3, LangParser.new.calc_test("((1 + 2))"))
32
+
33
+ assert_equal(6, LangParser.new.calc_test("1 + 2 + 3"))
34
+ assert_equal(6, LangParser.new.calc_test("(1 + 2) + 3"))
35
+ assert_equal(6, LangParser.new.calc_test("((1 + 2) + 3)"))
36
+ assert_equal(10, LangParser.new.calc_test("((1 + 2) + 3) + 4"))
37
+ assert_equal(10, LangParser.new.calc_test("4 + ((3) + (2 + 1))"))
14
38
  end
15
39
 
16
40
  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)'))
41
+ assert_equal(1, LangParser.new.calc_test("2 - 1"))
42
+ assert_equal(-3, LangParser.new.calc_test("(-2) - 1"))
43
+ assert_equal(1, LangParser.new.calc_test("(2 - 1)"))
44
+ assert_equal(1, LangParser.new.calc_test("((2 - 1))"))
45
+
46
+ assert_equal(0, LangParser.new.calc_test("3 - 2 - 1"))
47
+ assert_equal(0, LangParser.new.calc_test("(3 - 2) - 1"))
48
+ assert_equal(0, LangParser.new.calc_test("((3 - 2)) - 1"))
49
+ assert_equal(2, LangParser.new.calc_test("(4 - (3 - 2)) - 1"))
50
+ assert_equal(2, LangParser.new.calc_test("(4 - ((3) - 2)) - 1"))
51
+ assert_equal(4, LangParser.new.calc_test("4 - (((3) - 2) - 1)"))
28
52
  end
29
53
 
30
54
  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)'))
55
+ assert_equal(2, LangParser.new.calc_test("2 * 1"))
56
+ assert_equal(2, LangParser.new.calc_test("1 * 2"))
57
+ assert_equal(2, LangParser.new.calc_test("1 * (2)"))
58
+ assert_equal(2, LangParser.new.calc_test("(1) * (2)"))
59
+
60
+ assert_equal(6, LangParser.new.calc_test("(1) * (2 * 3)"))
61
+ assert_equal(6, LangParser.new.calc_test("(1 * 2 * 3)"))
62
+ assert_equal(6, LangParser.new.calc_test("(1 * 2) * 3"))
63
+ assert_equal(18, LangParser.new.calc_test("(3) * 2 * (3)"))
64
+ assert_equal(-6, LangParser.new.calc_test("(3) * (0 - 2) * (1)"))
41
65
  end
42
66
 
43
67
  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)'))
68
+ assert_equal(2, LangParser.new.calc_test("2 / 1"))
69
+ assert_equal(1, LangParser.new.calc_test("2 / 2"))
70
+ assert_equal(0.5, LangParser.new.calc_test("1 / 2"))
71
+ assert_equal(-0.5, LangParser.new.calc_test("-1 / 2"))
72
+ assert_equal(-2.5, LangParser.new.calc_test("-5 / 2"))
73
+
74
+ assert_equal(0, LangParser.new.calc_test("(-1 + 1) / 2"))
75
+ assert_equal(1, LangParser.new.calc_test("(3 / (3 / 1)) / 1"))
76
+ assert_equal(1, LangParser.new.calc_test("(3 / (3 / 1)) / (1)"))
77
+ assert_equal(3, LangParser.new.calc_test("(3 / (3 / 1-1-1)) / (1)"))
54
78
  end
55
79
  end
56
80
 
57
81
  class TestLogic < Test::Unit::TestCase
58
82
  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'))
83
+ assert_equal(true, LangParser.new.calc_test("#{$true}"))
84
+ assert_equal(true, LangParser.new.calc_test("#{$true} #{$and} #{$true}"))
85
+ assert_equal(true, LangParser.new.calc_test("#{$true} #{$or} #{$true}"))
86
+ assert_equal(true, LangParser.new.calc_test("#{$true} #{$or} #{$false}"))
87
+ assert_equal(true, LangParser.new.calc_test(" #{$not} #{$false}"))
64
88
 
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'))
89
+ assert_equal(false, LangParser.new.calc_test("#{$false}"))
90
+ assert_equal(false, LangParser.new.calc_test("#{$false} #{$and} #{$false}"))
91
+ assert_equal(false, LangParser.new.calc_test("#{$false} #{$and} #{$true}"))
92
+ assert_equal(false, LangParser.new.calc_test("#{$not} #{$true}"))
69
93
 
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'))
94
+ assert_equal(true, LangParser.new.calc_test("(#{$not} #{$false}) #{$and} #{$true}"))
95
+ assert_equal(true, LangParser.new.calc_test("(#{$not} #{$false}) #{$or} #{$false}"))
96
+ assert_equal(true, LangParser.new.calc_test("#{$true} #{$and} #{$true} #{$or} #{$false}"))
73
97
 
74
98
  end
75
99
  end
76
100
 
77
101
  class TestComparisons < Test::Unit::TestCase
78
102
  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'))
103
+ assert_equal(true, LangParser.new.calc_test("1 < 2"))
104
+ assert_equal(false, LangParser.new.calc_test("1 > 2"))
105
+ assert_equal(true, LangParser.new.calc_test("1 < 2 #{$and} #{$true}"))
106
+ assert_equal(false, LangParser.new.calc_test("1 > 2 #{$and} #{$true}"))
107
+ assert_equal(false, LangParser.new.calc_test("1 > 2 + 3 #{$and} #{$true}"))
108
+ assert_equal(true, LangParser.new.calc_test("1+2 < 2+2 #{$and} #{$true}"))
109
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 > 2 #{$and} #{$true}"))
110
+ assert_equal(true, LangParser.new.calc_test(" #{$true} #{$and} #{$not} 1 > 2"))
111
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 > 2 #{$and} #{$true}"))
112
+
113
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 > 2 #{$and} #{$true} #{$or} #{$false}"))
114
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 > 2 #{$and} (#{$true} #{$or} #{$false})"))
115
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 > 2 #{$and} #{$false} #{$or} #{$true} #{$and} #{$true}"))
116
+
117
+ assert_equal(true, LangParser.new.calc_test(" 1 == 1"))
118
+ assert_equal(false, LangParser.new.calc_test(" 1 == 2"))
119
+ assert_equal(true, LangParser.new.calc_test(" #{$not} 1 == 2"))
120
+ assert_equal(false, LangParser.new.calc_test(" #{$not} 1 == 1"))
121
+
122
+ assert_equal(true, LangParser.new.calc_test(" 1 <= 1"))
123
+ assert_equal(false, LangParser.new.calc_test(" 3 <= 2"))
124
+ assert_equal(true, LangParser.new.calc_test(" 1 <= 2"))
125
+
126
+ assert_equal(true, LangParser.new.calc_test(" 1 >= 1"))
127
+ assert_equal(true, LangParser.new.calc_test(" 3 >= 2"))
128
+ assert_equal(false, LangParser.new.calc_test(" 1 >= 2"))
105
129
  end
106
130
  end
107
131
 
108
132
  class TestIf < Test::Unit::TestCase
109
133
  def test_if
110
- assert_equal(2, LangParser.new.calc_test(' if true
134
+ assert_equal(2, LangParser.new.calc_test(" #{$if} #{$true}
111
135
  1+1
112
- end'))
136
+ #{$end}"))
113
137
 
114
- assert_equal(2, LangParser.new.calc_test(' if 3 == 3
138
+ assert_equal(2, LangParser.new.calc_test(" #{$if} 3 == 3
115
139
  1+1
116
- end'))
140
+ #{$end}"))
117
141
 
118
- assert_equal(nil, LangParser.new.calc_test('if 3 == 2
142
+ assert_equal(nil, LangParser.new.calc_test("#{$if} 3 == 2
119
143
  1+1
120
- end'))
144
+ #{$end}"))
121
145
  end
122
146
  end
123
147
  class TestVariables < Test::Unit::TestCase
124
148
  def test_variables
125
- assert_equal(1, LangParser.new.calc_test('x = 1
126
- x'))
149
+ assert_equal(1, LangParser.new.calc_test("x = 1
150
+ x"))
127
151
 
128
- assert_equal(1, LangParser.new.calc_test('x = 1
152
+ assert_equal(1, LangParser.new.calc_test("x = 1
129
153
  x
130
- x'))
154
+ x"))
131
155
 
132
- assert_equal(1, LangParser.new.calc_test('x = 1
156
+ assert_equal(1, LangParser.new.calc_test("x = 1
133
157
  x
134
158
  x + 1
135
- x'))
159
+ x"))
136
160
 
137
- assert_equal(3, LangParser.new.calc_test('x = 1
138
- x + 2'))
161
+ assert_equal(3, LangParser.new.calc_test("x = 1
162
+ x + 2"))
139
163
 
140
- assert_equal(2, LangParser.new.calc_test('x = 1
164
+ assert_equal(2, LangParser.new.calc_test("x = 1
141
165
  x = 2
142
- x'))
166
+ x"))
143
167
 
144
- assert_equal(5, LangParser.new.calc_test('x = 1 + 2
145
- x + 2'))
168
+ assert_equal(5, LangParser.new.calc_test("x = 1 + 2
169
+ x + 2"))
146
170
 
147
- assert_equal(5, LangParser.new.calc_test('x = 1 + 2
171
+ assert_equal(5, LangParser.new.calc_test("x = 1 + 2
148
172
  x = x + 2
149
- x'))
173
+ x"))
150
174
  end
151
175
  end
152
176
 
153
177
  class TestFunction < Test::Unit::TestCase
154
178
  def test_function
155
- assert_equal(nil, LangParser.new.calc_test(' def foo()
179
+ assert_equal(nil, LangParser.new.calc_test(" #{$def} foo()
156
180
  5+5
157
- end'))
181
+ #{$end}"))
158
182
 
159
- assert_equal(10, LangParser.new.calc_test(' def foo()
183
+ assert_equal(10, LangParser.new.calc_test(" #{$def} foo()
160
184
  5+5
161
- end
162
- foo()'))
185
+ #{$end}
186
+ foo()"))
163
187
 
164
- assert_equal(10, LangParser.new.calc_test(' def boo()
188
+ assert_equal(10, LangParser.new.calc_test(" #{$def} boo()
165
189
  a = 5
166
190
  a
167
- end
191
+ #{$end}
168
192
  b = 5 + boo()
169
- b'))
193
+ b"))
170
194
  end
171
195
  end
172
196
 
173
197
  class TestLoop < Test::Unit::TestCase
174
198
  def test_while
175
- assert_equal(WhileLoopNode, LangParser.new.calc_test('x = 5
176
- while x < 10
199
+ assert_equal(WhileLoopNode, LangParser.new.calc_test("x = 5
200
+ #{$while} x < 10
177
201
  x = x + 1
178
- end'))
202
+ #{$end}"))
179
203
 
180
- assert_equal(10, LangParser.new.calc_test('x = 5
181
- while x < 10
204
+ assert_equal(10, LangParser.new.calc_test("x = 5
205
+ #{$while} x < 10
182
206
  x = x + 1
183
- end
184
- x'))
207
+ #{$end}
208
+ x"))
185
209
 
186
- assert_equal(-10, LangParser.new.calc_test('x = 0
187
- while x > -10
210
+ assert_equal(-10, LangParser.new.calc_test("x = 0
211
+ #{$while} x > -10
188
212
  x = x - 1
189
- end
190
- x'))
213
+ #{$end}
214
+ x"))
191
215
 
192
- # assert_equal(0, LangParser.new.calc_test('x = 10
193
- # while -x < 0 # fundera på negering av variabler
216
+ # assert_equal(0, LangParser.new.calc_test("x = 10
217
+ # #{$while} -x < 0 # fundera på negering av variabler
194
218
  # x = x + 1
195
- # end
196
- # x'))
219
+ # #{$end}
220
+ # x"))
197
221
  end
198
222
  end
199
223
 
200
224
  class TesCompactIf < Test::Unit::TestCase
201
225
  def test_CompactIf
202
- assert_equal(4, LangParser.new.calc_test('x = 4
203
- if 7 <= 10 and > 5
226
+ assert_equal(4, LangParser.new.calc_test("x = 4
227
+ #{$if} 7 <= 10 #{$and} > 5
204
228
  x
205
- end'))
229
+ #{$end}"))
206
230
 
207
- assert_equal(8, LangParser.new.calc_test('x = 8
208
- if x < 10 and > 5
231
+ assert_equal(8, LangParser.new.calc_test("x = 8
232
+ #{$if} x < 10 #{$and} > 5
209
233
  x
210
- end'))
234
+ #{$end}"))
211
235
 
212
- assert_equal(nil, LangParser.new.calc_test('x = 2
213
- if x <= 10 and >= 5
236
+ assert_equal(nil, LangParser.new.calc_test("x = 2
237
+ #{$if} x <= 10 #{$and} >= 5
214
238
  x
215
- end'))
239
+ #{$end}"))
216
240
  end
217
241
  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.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - mattias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-04 00:00:00.000000000 Z
11
+ date: 2024-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logger
@@ -73,7 +73,6 @@ files:
73
73
  - lib/nodes/scopemanager.rb
74
74
  - lib/nodes/stmtnodes.rb
75
75
  - lib/rdparse.rb
76
- - lib/rdparse_quiet.rb
77
76
  - lib/tester/demo_de.alpha
78
77
  - lib/tester/demo_sv.alpha
79
78
  - lib/tester/fibonacci.alpha
data/lib/rdparse_quiet.rb DELETED
@@ -1,236 +0,0 @@
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 = 'default', &block)
130
-
131
- token_pairs = File.readlines("#{LOCALES_PATH}/#{locale}")
132
- @token_list = Hash.new
133
- token_pairs.each do |pair|
134
- default_value, locale_value = pair.split(' ')
135
- @token_list[default_value] = locale_value
136
- end
137
-
138
- @lex_tokens = []
139
- @rules = {}
140
- @start = nil
141
- @language_name = language_name
142
- instance_eval(&block)
143
- end
144
-
145
- # Tokenize the string into small pieces
146
- def tokenize(string)
147
- @tokens = []
148
- @string = string.clone
149
- until string.empty?
150
- # Unless any of the valid tokens of our language are the prefix of
151
- # 'string', we fail with an exception
152
- raise ParseError, "unable to lex '#{string}" unless @lex_tokens.any? do |tok|
153
- match = tok.pattern.match(string)
154
- # The regular expression of a token has matched the beginning of 'string'
155
- if match
156
-
157
- # Also, evaluate this expression by using the block
158
- # associated with the token
159
- @tokens << tok.block.call(match.to_s) if tok.block
160
- # consume the match and proceed with the rest of the string
161
- string = match.post_match
162
- true
163
- else
164
- # this token pattern did not match, try the next
165
- false
166
- end # if
167
- end # raise
168
- end # until
169
- end
170
-
171
- def parse(string)
172
- # First, split the string according to the "token" instructions given.
173
- # Afterwards @tokens contains all tokens that are to be parsed.
174
- tokenize(string)
175
-
176
- # These variables are used to match if the total number of tokens
177
- # are consumed by the parser
178
- @pos = 0
179
- @max_pos = 0
180
- @expected = []
181
- # Parse (and evaluate) the tokens received
182
- result = @start.parse
183
- # If there are unparsed extra tokens, signal error
184
- if @pos != @tokens.size
185
- raise ParseError, "Parse error. expected: '#{@expected.join(', ')}', found '#{@tokens[@max_pos]}'"
186
- end
187
- return result
188
- end
189
-
190
- def next_token
191
- @pos += 1
192
- return @tokens[@pos - 1]
193
- end
194
-
195
- # Return the next token in the queue
196
- def expect(tok)
197
- return tok if tok == :empty
198
- t = next_token
199
- if @pos - 1 > @max_pos
200
- @max_pos = @pos - 1
201
- @expected = []
202
- end
203
- return t if tok === t
204
- @expected << tok if @max_pos == @pos - 1 && !@expected.include?(tok)
205
- return nil
206
- end
207
-
208
- def to_s
209
- "Parser for #{@language_name}"
210
- end
211
-
212
- private
213
-
214
- LexToken = Struct.new(:pattern, :block)
215
-
216
- def token(pattern, &block)
217
- @lex_tokens << LexToken.new(Regexp.new('\\A' + @token_list[pattern.source]), block)
218
- end
219
-
220
- def start(name, &block)
221
- rule(name, &block)
222
- @start = @rules[name]
223
- end
224
-
225
- def rule(name,&block)
226
- @current_rule = Rule.new(name, self)
227
- @rules[name] = @current_rule
228
- instance_eval &block # In practise, calls match 1..N times
229
- @current_rule = nil
230
- end
231
-
232
- def match(*pattern, &block)
233
- # Basically calls memberfunction "match(*pattern, &block)
234
- @current_rule.send(:match, *pattern, &block)
235
- end
236
- end