alphalang 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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