calc_emonto15 0.0.1 → 0.0.2
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 +4 -4
- data/bin/calc +99 -12
- data/lib/ast.rb +57 -0
- data/lib/calculator.rb +5 -0
- data/lib/parser.rb +67 -35
- data/lib/scanner.rb +20 -6
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d01a7350e2aa58eb7bb63fdeb3fe4a396585119
|
4
|
+
data.tar.gz: 608ac2f43274a72b2f9e078830a80f444e075635
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e16fdb29a2e93b7489561a760462816149ee7128af5d25072e210f0a1d6902f0880e53809d153ee97f485b34106c5c64c5e7b3b2a71f1fdc11faf0ce4e489b04
|
7
|
+
data.tar.gz: d2d3d968d709d86e21589fe561eb968a91d8fcfb9abfc873558f79918aab73350fb4dc6badef3caa287b1135d9af887766c63d2a4295670054f7deb9a168101d
|
data/bin/calc
CHANGED
@@ -1,22 +1,109 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
2
3
|
|
3
4
|
require 'rubygems'
|
4
5
|
require 'calculator'
|
5
6
|
require 'calcex'
|
7
|
+
interactivo=true;
|
8
|
+
$calc = Calculator.new()
|
6
9
|
|
7
|
-
|
8
|
-
|
10
|
+
if ARGV[0]=="-e" then
|
11
|
+
i=0
|
12
|
+
ARGV.each do |val|
|
13
|
+
if val=="-v"
|
14
|
+
i+=1
|
15
|
+
particion = ARGV[i].partition("=")
|
16
|
+
$calc.mem2[particion[0]]=particion[2].to_i
|
17
|
+
else
|
18
|
+
i+=1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ENV.each do |val,v|
|
23
|
+
if val.match(/CALCVAR.*/) then
|
24
|
+
$calc.mem2[(val.delete "CALCVAR")]=v.to_i
|
25
|
+
end
|
26
|
+
end
|
27
|
+
else
|
28
|
+
ENV.each do |val,v|
|
29
|
+
if val.match(/CALCVAR.*/) then
|
30
|
+
$calc.mem2[(val.delete "CALCVAR")]=v.to_i
|
31
|
+
end
|
32
|
+
end
|
33
|
+
i=0
|
34
|
+
ARGV.each do |k|
|
35
|
+
if k=="-v"
|
36
|
+
i+=1
|
37
|
+
particion = ARGV[i].partition("=")
|
38
|
+
$calc.mem2[particion[0]]=particion[2].to_i
|
39
|
+
else
|
40
|
+
i+=1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
9
44
|
|
10
|
-
|
45
|
+
cont=0
|
46
|
+
ARGV.each do |k|
|
47
|
+
cont+=1
|
48
|
+
end
|
11
49
|
|
12
|
-
|
50
|
+
i=-1
|
51
|
+
ARGV.each do |var|
|
52
|
+
i+=1
|
53
|
+
if var!="-v" and var!="-e" then
|
54
|
+
if i!=0 then
|
55
|
+
if ARGV[i-1]!="-v"
|
56
|
+
File.open(ARGV[i], 'r') do |f1|
|
57
|
+
while linea = f1.gets
|
58
|
+
begin
|
59
|
+
result=$calc.eval(linea).to_s
|
60
|
+
if $calc.assign!=""
|
61
|
+
puts "=> " + result + " [" + $calc.assign.partition(" ")[2] + "]"
|
62
|
+
else
|
63
|
+
puts "=> " + result
|
64
|
+
end
|
65
|
+
rescue ParseError
|
66
|
+
rescue UnrecognizedTokenException
|
67
|
+
end
|
68
|
+
interactivo=false;
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
File.open(ARGV[i], 'r').each do |f1|
|
74
|
+
begin
|
75
|
+
result=$calc.eval(f1).to_s
|
76
|
+
if $calc.assign!=""
|
77
|
+
puts "=> " + result + " [" + $calc.assign.partition(" ")[2] + "]"
|
78
|
+
else
|
79
|
+
puts "=> " + result
|
80
|
+
end
|
81
|
+
rescue ParseError
|
82
|
+
rescue UnrecognizedTokenException
|
83
|
+
end
|
84
|
+
interactivo=false;
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
13
90
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
91
|
+
if interactivo==true then
|
92
|
+
$stdout.print "> "
|
93
|
+
$stdout.flush
|
94
|
+
while text=$stdin.gets
|
95
|
+
begin
|
96
|
+
result=$calc.eval(text).to_s
|
97
|
+
if $calc.assign!=""
|
98
|
+
puts "=> " + result + " [" + $calc.assign.partition(" ")[2] + "]"
|
99
|
+
else
|
100
|
+
puts "=> " + result
|
101
|
+
end
|
102
|
+
rescue ParseError
|
103
|
+
rescue UnrecognizedTokenException
|
104
|
+
end
|
105
|
+
$stdout.print "> "
|
106
|
+
$stdout.flush
|
107
|
+
end
|
108
|
+
$stdout.print "\n"
|
22
109
|
end
|
data/lib/ast.rb
CHANGED
@@ -57,6 +57,16 @@ class DivideNode < BinaryNode
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
class ModNode < BinaryNode
|
61
|
+
def initialize(left, right)
|
62
|
+
super(left,right)
|
63
|
+
end
|
64
|
+
|
65
|
+
def evaluate
|
66
|
+
return @left.evaluate % @right.evaluate()
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
60
70
|
class StoreNode < UnaryNode
|
61
71
|
def initialize(sub)
|
62
72
|
super sub
|
@@ -83,3 +93,50 @@ class NumNode
|
|
83
93
|
end
|
84
94
|
end
|
85
95
|
|
96
|
+
class ClearNode
|
97
|
+
def evaluate
|
98
|
+
$calc.memory=0
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class PlusNode < UnaryNode
|
103
|
+
def initialize(sub)
|
104
|
+
super sub
|
105
|
+
end
|
106
|
+
|
107
|
+
def evaluate
|
108
|
+
aux = subTree.evaluate().to_i
|
109
|
+
$calc.memory=$calc.memory+aux
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class MinusNode < UnaryNode
|
114
|
+
def initialize(sub)
|
115
|
+
super sub
|
116
|
+
end
|
117
|
+
|
118
|
+
def evaluate
|
119
|
+
aux = subTree.evaluate().to_i
|
120
|
+
$calc.memory=$calc.memory-aux
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class AssignNode < UnaryNode
|
125
|
+
def initialize(sub,name)
|
126
|
+
super sub
|
127
|
+
@name=name
|
128
|
+
end
|
129
|
+
|
130
|
+
def evaluate
|
131
|
+
$calc.mem2[@name] = subTree.evaluate()
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class IdNode
|
136
|
+
def initialize(name)
|
137
|
+
@name=name
|
138
|
+
end
|
139
|
+
def evaluate
|
140
|
+
$calc.mem2[@name]
|
141
|
+
end
|
142
|
+
end
|
data/lib/calculator.rb
CHANGED
@@ -2,14 +2,19 @@ require 'parser'
|
|
2
2
|
require 'ast'
|
3
3
|
|
4
4
|
class Calculator
|
5
|
+
attr_accessor :assign
|
5
6
|
attr_accessor :memory
|
7
|
+
attr_accessor :mem2
|
6
8
|
|
7
9
|
|
8
10
|
def initialize()
|
11
|
+
@assign=""
|
9
12
|
@memory = 0
|
13
|
+
@mem2= Hash.new(0)
|
10
14
|
end
|
11
15
|
|
12
16
|
def eval(expr)
|
17
|
+
@assign=""
|
13
18
|
parser = Parser.new(StringIO.new(expr))
|
14
19
|
ast = parser.parse()
|
15
20
|
return ast.evaluate()
|
data/lib/parser.rb
CHANGED
@@ -4,6 +4,7 @@ require 'token'
|
|
4
4
|
require 'calcex'
|
5
5
|
|
6
6
|
class Parser
|
7
|
+
|
7
8
|
def initialize(istream)
|
8
9
|
@scan = Scanner.new(istream)
|
9
10
|
end
|
@@ -14,21 +15,27 @@ class Parser
|
|
14
15
|
|
15
16
|
private
|
16
17
|
def Prog
|
18
|
+
t = @scan.getToken
|
19
|
+
if t.type == :eof
|
20
|
+
print "* ParseError: Expected EOF. Found eol.\n"
|
21
|
+
raise ParseError
|
22
|
+
|
23
|
+
end
|
24
|
+
@scan.putBackToken
|
17
25
|
result = Expr()
|
18
26
|
t = @scan.getToken
|
19
|
-
|
20
27
|
if t.type != :eof then
|
21
|
-
print "Expected EOF. Found ", t.type, ".\n"
|
28
|
+
print "* ParseError: Expected EOF. Found ", t.type, ".\n"
|
22
29
|
raise ParseError.new
|
23
30
|
end
|
24
|
-
|
25
31
|
result
|
26
32
|
end
|
27
|
-
|
33
|
+
|
34
|
+
|
28
35
|
def Expr
|
29
36
|
return RestExpr(Term())
|
30
37
|
end
|
31
|
-
|
38
|
+
|
32
39
|
def RestExpr(e)
|
33
40
|
t = @scan.getToken
|
34
41
|
|
@@ -46,46 +53,46 @@ class Parser
|
|
46
53
|
end
|
47
54
|
|
48
55
|
def Term
|
49
|
-
# Write your Term() code here. This code is just temporary
|
50
|
-
# so you can try the calculator out before finishing it.
|
51
|
-
|
52
|
-
# t = @scan.getToken
|
53
|
-
|
54
|
-
# if t.type == :number then
|
55
|
-
# val = t.lex.to_i
|
56
|
-
# return NumNode.new(val)
|
57
|
-
# end
|
58
|
-
|
59
|
-
# puts "Term not implemented\n"
|
60
|
-
|
61
|
-
# raise ParseError.new
|
62
|
-
# end
|
63
|
-
|
64
56
|
RestTerm(Storable())
|
65
|
-
end
|
57
|
+
end
|
58
|
+
|
66
59
|
def RestTerm(e)
|
67
60
|
t = @scan.getToken
|
68
61
|
if t.type == :times
|
69
|
-
return
|
62
|
+
return RestTerm(TimesNode.new(e,Storable()))
|
70
63
|
end
|
71
64
|
|
72
65
|
if t.type == :divide
|
73
66
|
return RestTerm(DivideNode.new(e,Storable()))
|
74
67
|
end
|
68
|
+
|
69
|
+
if t.type == :mod
|
70
|
+
return RestTerm(ModNode.new(e,Storable()))
|
71
|
+
end
|
75
72
|
|
76
73
|
@scan.putBackToken
|
77
74
|
e
|
78
75
|
end
|
79
|
-
|
76
|
+
|
80
77
|
def Storable
|
81
|
-
|
78
|
+
return MemOperation(Factor());
|
79
|
+
end
|
80
|
+
|
81
|
+
def MemOperation(result)
|
82
82
|
t = @scan.getToken
|
83
83
|
|
84
84
|
if t.type == :keyword
|
85
85
|
if t.lex == "S"
|
86
86
|
return StoreNode.new(result)
|
87
87
|
end
|
88
|
-
|
88
|
+
if t.lex == "P"
|
89
|
+
return PlusNode.new(result)
|
90
|
+
end
|
91
|
+
if t.lex == "M"
|
92
|
+
return MinusNode.new(result)
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "* ParseError: Expected 'S','P' or 'M' , found #{t.lex}"
|
89
96
|
raise ParseError.new
|
90
97
|
|
91
98
|
end
|
@@ -96,34 +103,59 @@ class Parser
|
|
96
103
|
|
97
104
|
def Factor
|
98
105
|
t = @scan.getToken
|
99
|
-
|
106
|
+
|
100
107
|
if t.type == :number
|
101
108
|
return NumNode.new(t.lex.to_i)
|
102
109
|
end
|
103
|
-
|
110
|
+
|
104
111
|
if t.type == :keyword
|
105
112
|
if t.lex == "R"
|
106
113
|
return RecallNode.new
|
107
114
|
end
|
108
|
-
|
115
|
+
if t.lex == "C"
|
116
|
+
return ClearNode.new
|
117
|
+
end
|
118
|
+
puts "* ParseError: Expected R or C. Fount #{t.type}"
|
109
119
|
raise ParseError.new
|
110
120
|
end
|
111
|
-
|
112
|
-
|
121
|
+
|
122
|
+
|
113
123
|
if t.type == :lparen
|
114
124
|
result = Expr()
|
115
125
|
t = @scan.getToken
|
116
126
|
if t.type == :rparen
|
117
127
|
return result
|
118
128
|
end
|
119
|
-
|
120
|
-
puts "Parse Erro: expected ) found #{t.lex} at line: #{t.lex} col #{t.col}"
|
129
|
+
puts "* Parse Error: expected )."
|
121
130
|
raise ParseError.new
|
122
131
|
end
|
123
|
-
|
124
|
-
puts "Expected number, R or (Expr). Found#{t.lex} at line #{t.line} col #{t.col}"
|
125
|
-
raise ParseError.new
|
126
132
|
|
133
|
+
|
134
|
+
@scan.putBackToken
|
135
|
+
return Assignable()
|
136
|
+
end
|
137
|
+
|
138
|
+
def Assignable
|
139
|
+
t = @scan.getToken
|
140
|
+
if t.type == :identifier
|
141
|
+
@scan.putBackToken
|
142
|
+
return Assign()
|
143
|
+
end
|
144
|
+
puts "* ParseError: Expected number, R, C, Assignable, eol or (Expr). Found #{t.type}"
|
145
|
+
raise ParseError.new
|
127
146
|
end
|
128
147
|
|
148
|
+
def Assign
|
149
|
+
t=@scan.getToken
|
150
|
+
name=t.lex
|
151
|
+
t=@scan.getToken
|
152
|
+
if t.type == :igual
|
153
|
+
result= Expr()
|
154
|
+
valor=result.evaluate()
|
155
|
+
$calc.assign+=", "+name+" <- "+valor.to_s
|
156
|
+
return AssignNode.new(result,name)
|
157
|
+
end
|
158
|
+
@scan.putBackToken
|
159
|
+
return IdNode.new(name)
|
160
|
+
end
|
129
161
|
end
|
data/lib/scanner.rb
CHANGED
@@ -4,7 +4,7 @@ require 'calcex'
|
|
4
4
|
class Scanner
|
5
5
|
def initialize(inStream)
|
6
6
|
@istream = inStream
|
7
|
-
@keywords = Set.new(%w{S R}) #definicion de colecciones
|
7
|
+
@keywords = Set.new(%w{S R C P M}) #definicion de colecciones
|
8
8
|
@lineCount = 1
|
9
9
|
@colCount = -1
|
10
10
|
@needToken = true
|
@@ -45,6 +45,8 @@ class Scanner
|
|
45
45
|
elsif c == ?/ then state = 6
|
46
46
|
elsif c == ?( then state = 7
|
47
47
|
elsif c == ?) then state = 8
|
48
|
+
elsif c == ?% then state = 9
|
49
|
+
elsif c == ?= then state = 10
|
48
50
|
elsif c == ?\n then
|
49
51
|
@colCount = -1
|
50
52
|
@lineCount = @lineCount+1
|
@@ -91,16 +93,28 @@ class Scanner
|
|
91
93
|
when 8
|
92
94
|
type = :rparen
|
93
95
|
foundOne = true
|
96
|
+
when 9
|
97
|
+
type = :mod
|
98
|
+
foundOne = true
|
99
|
+
when 10
|
100
|
+
type = :igual
|
101
|
+
foundOne = true
|
94
102
|
end
|
95
103
|
|
96
104
|
if !foundOne then
|
97
105
|
lex.concat(c)
|
98
106
|
c = @istream.getc()
|
107
|
+
if state==0 && @istream.eof?
|
108
|
+
@lastToken = Token.new(:eof, @lineCount, @colCount)
|
109
|
+
return @lastToken
|
110
|
+
end
|
99
111
|
end
|
100
|
-
|
101
112
|
end
|
113
|
+
|
114
|
+
|
115
|
+
@istream.ungetc(c)
|
116
|
+
|
102
117
|
|
103
|
-
@istream.ungetc(c)
|
104
118
|
@colCount = @colCount - 1
|
105
119
|
if type == :number or type == :identifier or type == :keyword then
|
106
120
|
t = LexicalToken.new(type,lex,line,column)
|
@@ -114,14 +128,14 @@ class Scanner
|
|
114
128
|
|
115
129
|
private
|
116
130
|
def isLetter(c)
|
117
|
-
return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
|
131
|
+
return ((?a <= c.to_s and c.to_s <= ?z) or (?A <= c.to_s and c.to_s <= ?Z))
|
118
132
|
end
|
119
133
|
|
120
134
|
def isDigit(c)
|
121
|
-
return (?0 <= c and c <= ?9)
|
135
|
+
return (?0 <= c.to_s and c.to_s <= ?9)
|
122
136
|
end
|
123
137
|
|
124
138
|
def isWhiteSpace(c)
|
125
|
-
return (c == ?\ or c == ?\n or c == ?\t)
|
139
|
+
return (c.to_s == ?\ or c.to_s == ?\n or c == ?\t)
|
126
140
|
end
|
127
141
|
end
|