linmeric 0.1.0

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.
@@ -0,0 +1,118 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative 'CnGal_new_classes.rb'
4
+
5
+ class Parser
6
+ def initialize()
7
+ @d = 0
8
+ @error = false
9
+ end
10
+
11
+ def reset()
12
+ @d = 0
13
+ @error = false
14
+ end
15
+
16
+ def parse(expr)
17
+ array = Array.new
18
+ until @d == expr.length
19
+ c = expr[@d]
20
+ case c
21
+ when "("
22
+ @d += 1
23
+ calc = parse(expr)
24
+ array.push calc if calc != nil
25
+ when ")"
26
+ @d += 1
27
+ return array
28
+ when /[\*\/]/
29
+ @d +=1
30
+ array.push c.to_sym
31
+ when /[\+\-\^]/
32
+ @d+=1
33
+ array.push c.to_sym
34
+ when /\=/
35
+ @d += 1
36
+ array.push c.to_sym
37
+ when /\>/
38
+ @d += 1
39
+ array.push c.to_sym
40
+ when /\"/
41
+ @d += 1
42
+ array.push extract(expr)
43
+ when /\~/
44
+ @d += 1
45
+ if expr[@d] == "("
46
+ @d +=1
47
+ calc = parse(expr)
48
+ array.push calc unless calc == nil
49
+ else
50
+ array.push expr[@d]
51
+ @d += 1
52
+ end
53
+ when /\./
54
+ if expr[@d-1] =~ /[0-9]+/
55
+ x = array.pop.to_s + c + expr[@d+1]
56
+ array.push x.to_n
57
+ else
58
+ unless @error
59
+ @error = true
60
+ puts "Problem evaluating expression at index:#{@d}"
61
+ puts "Invalid char '#{expr[@d]}' in string variable"
62
+ end
63
+ return
64
+ end
65
+ @d+=2
66
+ when /\:/
67
+ if expr[@d - 1] =~ /[a-zA-Z]+/ then
68
+ x = array.pop.to_s + c
69
+ array.push x.downcase.to_sym
70
+ else
71
+ unless @error
72
+ @error = true
73
+ puts "Problem evaluating expression at index:#{@d}"
74
+ puts "Invalid char '#{expr[@d]}' in numeric variable"
75
+ end
76
+ return
77
+ end
78
+ @d += 1
79
+ when /\_/
80
+ @d += 1
81
+ x = array.pop.to_s + c
82
+ array.push x
83
+ when /\p{Alnum}/
84
+ if expr[@d-1] =~ /[0-9\.x]/ && array.count>0
85
+ x = array.pop.to_s + c
86
+ array.push x.to_n
87
+ elsif (expr[@d-1] =~ /[a-z\A-Z]/ or expr[@d-1] == '_') && array.count>0
88
+ x = array.pop.to_s + c
89
+ array.push x
90
+ else
91
+ array.push c.to_n if c =~ /[0-9\.x]/
92
+ array.push c if c =~ /[a-zA-Z]/
93
+ end
94
+ @d += 1
95
+ else
96
+ unless @error
97
+ @error = true
98
+ puts "Problem evaluating expression at index:#{@d}"
99
+ puts "Char '#{expr[@d]}' not recognized"
100
+ end
101
+ return
102
+ end
103
+ end
104
+
105
+ return array
106
+ end
107
+
108
+ def extract(expr)
109
+ ext = '"'
110
+ while expr[@d] != '"' do
111
+ ext += expr[@d]
112
+ @d += 1
113
+ end
114
+ @d += 1
115
+ return ext + '"'
116
+ end
117
+ end
118
+
@@ -0,0 +1,206 @@
1
+ #! /usr/bin/env ruby
2
+ require_relative 'CnGal_new_classes.rb'
3
+ # per poter computare un'espressione in formato stringa
4
+ # devo prima creare un albero con un parsing.
5
+ # per poter fare queste operazioni necessito di racchiudere
6
+ # le operazioni con priorità maggiore tra parentesi; es:
7
+ # 1+2*3 => 1+(2*3)
8
+ # 1+2*9^4 => 1+(2*(9^(4))) N.B. anche l'argomento di una potenza
9
+ # deve essere tra parentesi.
10
+ # valgono le stesse regole per le parti di espressione tra parentesi; es:
11
+ # 3*(1+2/3) => (3*(1+(2/3)))
12
+ # non importa se ci sono parentesi inutili in più, basta che
13
+ # siano coerenti.
14
+ # se c'è un uguale le parti a sx e a dx devono essere chiuse tra
15
+ # parentesi; es: a=b*c => (a)=((b*c))
16
+ # per quanto riguarda le parole chiavi, la parola chive e il
17
+ # suo argomento vengono messi tra parentesi; es t: a => (t: a)
18
+ class Scp
19
+ def initialize
20
+ @i = 0
21
+ end
22
+
23
+ def scopify(expr)
24
+ expr = insert_b(expr)
25
+ @i = 0
26
+ n_expr = ""
27
+ last_empty = 0
28
+ open_b = 0
29
+ open_p_b = 0
30
+ open_m_b = 0
31
+ eq = false
32
+ stack = Array.new
33
+ last_e = Array.new
34
+ state = 0
35
+ while @i < expr.size
36
+ case expr[@i]
37
+ # ogni parte racchiusa tra parentesi viene interpretata come
38
+ # una sotto espressione, e la sistemo a parte con una ricorsione
39
+ when '('
40
+ scp = Scp.new
41
+ n_expr += expr[@i] + scp.scopify(extract(expr[(@i + 1)...expr.length]))
42
+ @i += scp.count
43
+ when /[\*\/]/
44
+ # se ho parentesi aperte da operazioni con priorità superiore
45
+ # le chiudo
46
+ if open_m_b > 0
47
+ n_expr += ')' * open_m_b
48
+ last_empty = last_e.pop
49
+ open_m_b = 0
50
+ #open_b -= 1
51
+ end
52
+ if state == 2
53
+ n_expr += ')' * open_p_b
54
+ open_p_b = 0
55
+ state = (stack.size > 0 ? stack.pop : 0)
56
+ end
57
+ # se non ho già in corso un inserimento di parentesi per
58
+ # moltiplicazione, le aggiungo
59
+ unless state == 1
60
+ n_expr.insert last_empty, '('
61
+ state = 1
62
+ open_b += 1
63
+ end
64
+ n_expr += expr[@i]
65
+ last_empty = n_expr.size # + 1
66
+ when /[\+\-]/
67
+ # chiudo le parentesi delle operazioni con priorità superiore
68
+ # faccio lo shift di last_empty
69
+ n_expr += ')' * open_p_b if open_p_b > 0
70
+ n_expr += ')' * open_b if open_b > 0
71
+ state = 0
72
+ open_b = 0
73
+ open_p_b = 0
74
+ n_expr += expr[@i]
75
+ last_empty = n_expr.size
76
+ when /\^/
77
+ # comincio a mettere tra parentesi l'operazione e il suo esponente
78
+
79
+ if open_m_b > 0 then
80
+ n_expr += ")" * open_m_b
81
+ last_empty = last_e.pop
82
+ #open_b -= 1
83
+ open_m_b = 0
84
+ end
85
+ n_expr.insert last_empty, '(' unless state == 2
86
+ last_empty += 1 unless state == 2
87
+ n_expr += expr[@i] + (expr[@i+1] == '(' ? '' : '(')
88
+ open_p_b += (expr[@i+1] == '(' ? 1 : (state == 2 ? 1:2))
89
+ stack.push state unless state == 2
90
+ state = 2
91
+ when /\=/
92
+ # metto tra parentesi la parte a sx dell'uguale e comincio a
93
+ # mettere tra parentesi quella a dx
94
+ # chiudendo eventuali parentesi di potenza o di prodotto
95
+ n_expr += ')' * open_p_b if open_p_b > 0
96
+ n_expr += ')' * open_b if open_b > 0
97
+ open_b = 0
98
+ open_p_b = 0
99
+ n_expr = '(' + n_expr + ')' + expr[@i]
100
+ n_expr += '('
101
+ last_empty = n_expr.size
102
+ state = 0
103
+ eq = true
104
+ when /\>/
105
+ n_expr += ')' * open_p_b if open_p_b > 0
106
+ n_expr += ')' * open_b if open_b > 0
107
+ open_b = 0
108
+ open_p_b = 0
109
+ n_expr = '(' + n_expr + ')' + expr[@i]
110
+ last_empty = n_expr.size
111
+ when /\:/
112
+ n_expr.insert last_empty, '('
113
+ n_expr += expr[@i]
114
+ last_k = n_expr[(last_empty+1)...n_expr.size]
115
+ open_m_b += 1 if "mx:integ:as:from:".include? last_k
116
+ last_e.pop if last_e.count > 0 and (last_k == "mx:" or last_k == "integ:")# or last_k == "solve:")
117
+ last_e.push last_empty if last_k == "mx:" or last_k == "integ:"# or last_k == "solve:"
118
+ last_empty = n_expr.size
119
+ open_b += 1 unless "mx:integ:as:from:".include? last_k
120
+ when /\"/
121
+ n_expr += expr[@i]
122
+ @i += 1
123
+ n_expr += discard(expr)
124
+ last_empty = n_expr.length
125
+ when /\~/
126
+ n_expr += ')' * open_p_b if open_p_b > 0
127
+ n_expr += ')' * (open_b - 1 ) if open_b - 1 > 0
128
+ open_p_b = 0
129
+ open_b = 1
130
+ state = (stack.size > 0 ? stack.pop : 0)
131
+ n_expr += expr[@i]
132
+ last_empty = n_expr.size
133
+ else
134
+ n_expr += expr[@i]
135
+ end
136
+ @i += 1
137
+ end
138
+ # chiudo parentesi aperte, e quella dell'uguale se stata aperta
139
+ n_expr += ')' * open_m_b if open_m_b > 0
140
+ n_expr += ')' * open_p_b if open_p_b > 0
141
+ n_expr += ')' * open_b if open_b > 0
142
+ n_expr += ')' if eq
143
+ return n_expr
144
+ end
145
+
146
+ def count()
147
+ return @i
148
+ end
149
+
150
+ def insert_b(expr)
151
+ @i = 0
152
+ string = false
153
+ while @i < expr.size
154
+ string = (expr[@i] == "\"") ? (string ? false : true) : (string)
155
+ if (expr[@i] == '-' or expr[@i] == '+') and ((expr[@i - 1] == '(') or (@i == 0)) and !string then
156
+ expr.insert @i, '()'
157
+ end
158
+ @i += 1
159
+ end
160
+ return expr
161
+ end
162
+
163
+ private
164
+
165
+ def extract(expr)
166
+ n_expr = ""
167
+ i = 0
168
+ open_b = 0
169
+ until (i == expr.size) or ((expr[i] == ')') and (open_b == 0))
170
+ n_expr += expr[i]
171
+ open_b += 1 if expr[i] == '('
172
+ open_b -= 1 if expr[i] == ')' and (i < expr.size - 1)
173
+ i += 1
174
+ end
175
+ return n_expr + ')'
176
+ end
177
+
178
+ def discard(expr)
179
+ extract = ""
180
+ while expr[@i] != '"' do
181
+ extract += expr[@i]
182
+ @i += 1
183
+ end
184
+ return extract + expr[@i]
185
+ end
186
+ end
187
+
188
+
189
+ #####################################
190
+ # Tests #
191
+ #####################################
192
+ =begin
193
+ print ">"
194
+ inp = gets.chomp.compact
195
+ scp = Scp.new
196
+
197
+ while inp != 'exit'
198
+ puts scp.scopify(inp)
199
+ print '>'; inp = gets.chomp.compact
200
+ end
201
+
202
+ =end
203
+
204
+
205
+
206
+
@@ -0,0 +1,328 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative 'Token.rb'
4
+ require_relative 'Lexer.rb'
5
+ require_relative 'Error_print.rb'
6
+ require_relative 'CnGal_new_classes.rb'
7
+
8
+ class Sizer
9
+ def initialize()
10
+ @lexer = Lexer.new
11
+ end
12
+
13
+ def analyze(string, equal = true)
14
+ @i = 0
15
+ state = 0
16
+ return false if string == ""
17
+ @@string = string if string.is_a? String
18
+ unless string.is_a? Array
19
+ unless balanced_brackets? string
20
+ puts "Sintax Error: unbalanced brackets"
21
+ return false
22
+ end
23
+ end
24
+ token = @lexer.tokenize(string) unless string.is_a? Array
25
+ token = string if string.is_a? Array
26
+ while @i < token.size
27
+ #puts "#{token[@i].me}";puts
28
+ case state
29
+ # beginning state
30
+ when 0
31
+ case token[@i].attribute
32
+ when "SUM_OPERATOR"
33
+ state = 1
34
+ when "VARIABLE"
35
+ state = 2
36
+ when "NUMBER"
37
+ state = 2
38
+ when "L_BRACE"
39
+ sizer = Sizer.new
40
+ return false unless sizer.analyze(token[(@i+1)...token.size])
41
+ @i += sizer.count + 1
42
+ state = 2
43
+ when "KEYWORD"
44
+ case token[@i].me
45
+ when "mx:"
46
+ state = 6
47
+ when "integ:"
48
+ state = 7
49
+ when "shwvar:"
50
+ unless equal
51
+ PrintError.reduced(token[@i],@@string)
52
+ return false
53
+ end
54
+ state = 5
55
+ when "solve:"
56
+ state = 8
57
+ when "f:"
58
+ state = 4
59
+ else
60
+ if ["t:","det:","norm:","id_mx:","shw:"].include? token[@i].me then
61
+ unless equal or token[@i].me != "shw:"
62
+ PrintError.reduced(token[@i],@@string)
63
+ return false
64
+ end
65
+ state = 3
66
+ elsif not Tool.keys.include? token[@i].me then
67
+ PrintError.unknown(token[@i],@@string)
68
+ return false
69
+ else
70
+ PrintError.reduced(token[@i],@@string)
71
+ return false
72
+ end
73
+ end
74
+ else
75
+ PrintError.default(token[@i],@@string)
76
+ return false
77
+ end
78
+
79
+ # expecting numbers,variables, keywords (
80
+ when 1
81
+ case token[@i].attribute
82
+ when "NUMBER"
83
+ state = 2
84
+ when "VARIABLE"
85
+ state = 2
86
+ when "L_BRACE"
87
+ sizer = Sizer.new
88
+ return false unless sizer.analyze(token[(@i+1)...token.size])
89
+ @i += sizer.count + 1
90
+ state = 2
91
+ when "KEYWORD"
92
+ case token[@i].me
93
+ when "mx:"
94
+ state = 6
95
+ when "integ:"
96
+ state = 7
97
+ when "shwvar:"
98
+ state = 5
99
+ when "solve:"
100
+ state = 8
101
+ when "f:"
102
+ state = 4
103
+ else
104
+ if ["t:","det:","norm:","id_mx:"].include? token[@i].me then
105
+ state = 3
106
+ elsif not Tool.keys.include? token[@i].me then
107
+ PrintError.unknown(token[@i],@@string)
108
+ return false
109
+ else
110
+ PrintError.reduced(token[@i],@@string)
111
+ return false
112
+ end
113
+ end
114
+ else
115
+ PrintError.default(token[@i],@@string)
116
+ return false
117
+ end
118
+
119
+ # expecting operators, )
120
+ when 2
121
+ case token[@i].attribute
122
+ when "OPERATOR"
123
+ state = 1
124
+ when "SUM_OPERATOR"
125
+ state = 1
126
+ when "EQUAL_OP"
127
+ if equal
128
+ unless @i + 1 >= token.size
129
+ sizer = Sizer.new
130
+ return sizer.analyze(token[(@i+1)...token.size],false)
131
+ end
132
+ PrintError.missing_expression_after_equal(@i+1,@@string)
133
+ return false
134
+ else
135
+ PrintError.default(token[@i],@@string)
136
+ return false
137
+ end
138
+ when "TO_FILE_OP"
139
+ unless equal
140
+ PrintError.default(token[@i],@@string)
141
+ return false
142
+ end
143
+ state = 4
144
+ when "R_BRACE"
145
+ return true
146
+ else
147
+ PrintError.default(token[@i],@@string)
148
+ return false
149
+ end
150
+
151
+ # expecting only variables or numbers
152
+ when 3
153
+ case token[@i].attribute
154
+ when "VARIABLE"
155
+ state = 2
156
+ when "NUMBER"
157
+ state = 2
158
+ else
159
+ PrintError.default(token[@i],@@string)
160
+ return false
161
+ end
162
+ state = 5 if token[@i-1].me == "shw:"
163
+
164
+ # expects blocks (full chek) than nothing
165
+ when 4
166
+ return false unless check_block(token)
167
+ state = 5
168
+
169
+ # expects nothing
170
+ when 5
171
+ PrintError.default(token[@i],@@string)
172
+ return false
173
+
174
+ # checking mx arguments (full)
175
+ when 6
176
+ case token[@i].attribute
177
+ when "KEYWORD"
178
+ if token[@i].me == "from:" then
179
+ @i += 1
180
+ unless @i < token.size
181
+ PrintError.missing(token[@i-1],@@string)
182
+ return false
183
+ end
184
+ return false unless check_block(token)
185
+ state = 2
186
+ else
187
+ PrintError.missmatch(token[@i],@@string,"keyword 'from:' or block")
188
+ return false
189
+ end
190
+ when "QUOTES"
191
+ return false unless check_block(token)
192
+ unless @i+1 >= token.size
193
+ if token[@i+1].attribute == "KEYWORD" then
194
+ @i += 1
195
+ unless @i < token.size
196
+ PrintError.missing(token[@i-1],@@string)
197
+ return false
198
+ end
199
+ unless token[@i].me == "as:"
200
+ PrintError.missmatch(token[@i],@@string,"keyword 'as:' or operator")
201
+ return false
202
+ end
203
+ @i += 1
204
+ unless @i < token.size
205
+ PrintError.missing_general_string(token[@i-1].position+token[@i-1],@@string)
206
+ return false
207
+ end
208
+ return false unless check_block(token)
209
+ end
210
+ end
211
+ state = 2
212
+ end
213
+
214
+ # checking integ arguments (full)
215
+ when 7
216
+ unless @i < token.size
217
+ PrintError.missing(token[@i-1],@@string)
218
+ return false
219
+ end
220
+ if token[@i].attribute == "QUOTES" then
221
+ return false unless check_block(token)
222
+ elsif token[@i].attribute != "VARIABLE" then
223
+ PrintError.missmatch(token[@i],@@string,"variable or block")
224
+ return false
225
+ end
226
+ @i += 1
227
+ unless @i < token.size
228
+ PrintError.missing_integ_range(token[@i-1].position+1,@@string)
229
+ return false
230
+ end
231
+ return false unless check_block(token)
232
+ @i += 1
233
+ unless @i < token.size
234
+ PrintError.numPoint_missing(token[@i-1].position+1,@@string)
235
+ return false
236
+ end
237
+ unless @i + 1 >= token.size
238
+ if token[@i+1].attribute == "QUOTES" then
239
+ @i += 1
240
+ return false unless check_block(token)
241
+ end
242
+ end
243
+ state = 2
244
+
245
+ # checking solve args (full)
246
+ when 8
247
+ inner_state = 0
248
+ while !(token[@i].attribute == "EQUALS_TO") and @i < token.size
249
+ case inner_state
250
+ when 0
251
+ if token[@i].attribute == "VARIABLE" or token[@i].attribute == "NUMBER" then
252
+ inner_state = 1
253
+ elsif token[@i].attribute == "L_BRACE"
254
+ sizer = Sizer.new
255
+ return false unless sizer.analyze(token[(@i+1)...token.size])
256
+ @i += sizer.count + 1
257
+ else
258
+ PrintError.unexpected_token_in_solve(token[@i],@@string)
259
+ return false
260
+ end
261
+ when 1
262
+ if token[@i].attribute == "OPERATOR" then
263
+ inner_state = 0
264
+ else
265
+ PrintError.unexpected_token_in_solve(token[@i],@@string)
266
+ return false
267
+ end
268
+ end
269
+ @i += 1
270
+ end
271
+ state = 1
272
+ end
273
+ @i += 1
274
+ end
275
+
276
+ unless state == 2 or state == 5
277
+ if token[@i-1].attribute == "R_BRACE" then
278
+ tk = token[@i-2]
279
+ else
280
+ tk = token[@i-1]
281
+ end
282
+ PrintError.missing(tk,@@string)
283
+ return false
284
+ end
285
+ return true
286
+ end
287
+
288
+ def count
289
+ return @i
290
+ end
291
+
292
+ private
293
+ def balanced_brackets?(exp)
294
+ open_b = 0
295
+ for i in 0...exp.size
296
+ open_b += 1 if exp[i] == "("
297
+ open_b -= 1 if exp[i] == ")"
298
+ end
299
+ open_b == 0 ? (return true) : (return false)
300
+ end
301
+
302
+ def check_block(token)
303
+ unless token[@i].attribute == "QUOTES" then
304
+ PrintError.missmatch(token[@i],@@string,"quotes for block")
305
+ return false
306
+ end
307
+ @i += 1
308
+ unless @i < token.size
309
+ PrintError.missing_general_string(token[@i-1].position+token[@i-1].me.size,@@string,)
310
+ return false
311
+ end
312
+ unless token[@i].attribute == "GENERAL_STRING" then
313
+ PrintError.missmatch(token[@i],@@string,"block argument")
314
+ return false
315
+ end
316
+ @i += 1
317
+ unless @i < token.size
318
+ PrintError.no_final_quotes(@@string,token[@i-1].position+token[@i-1].me.size)
319
+ return false
320
+ end
321
+ unless token[@i].attribute == "QUOTES" then
322
+ PrintError.missmatch(token[@i],@@string,"quotes for block")
323
+ return false
324
+ end
325
+ return true
326
+ end
327
+
328
+ end
@@ -0,0 +1,53 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require_relative 'CnGal_tools.rb'
4
+ require_relative 'CnGal_new_classes.rb'
5
+
6
+ class Token
7
+ OPERATORS = Tool.operators
8
+ VARIABLE = /[a-zA-Z_][a-zA-Z0-9_]*/
9
+ def initialize(to_token,pos,sugg = "")
10
+ @My_pos = pos
11
+ if OPERATORS.include? to_token then
12
+ @My_att = "OPERATOR" unless [">","=","+","-"].include? to_token
13
+ @My_att = "EQUAL_OP" if to_token == "="
14
+ @My_att = "TO_FILE_OP" if to_token == ">"
15
+ @My_att = "SUM_OPERATOR" if '+-'.include? to_token
16
+ elsif sugg != ""
17
+ @My_att = sugg
18
+ elsif to_token == "~"
19
+ @My_att = "EQUALS_TO"
20
+ elsif to_token.include? ":" then
21
+ @My_att = "KEYWORD"
22
+ elsif to_token.match(VARIABLE).to_s.size == to_token.size then
23
+ @My_att = "VARIABLE"
24
+ elsif to_token.number? then
25
+ @My_att = "NUMBER"
26
+ elsif to_token == "(" then
27
+ @My_att = "L_BRACE"
28
+ elsif to_token == ")" then
29
+ @My_att = "R_BRACE"
30
+ elsif to_token == '"' then
31
+ @My_att = "QUOTES"
32
+ else
33
+ @My_att = "GENERAL_STRING"
34
+ end
35
+ @My_self = (to_token.include? ':') ? (to_token.downcase) : (to_token)
36
+ end
37
+
38
+ def attribute
39
+ return @My_att
40
+ end
41
+
42
+ def position
43
+ return @My_pos
44
+ end
45
+
46
+ def me
47
+ return @My_self
48
+ end
49
+
50
+ def show
51
+ return [@My_att,@My_pos,@My_self]
52
+ end
53
+ end