calc_esilvac 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 +7 -0
- data/bin/calc +55 -0
- data/lib/ast.rb +149 -0
- data/lib/calcex.rb +3 -0
- data/lib/calculator.rb +70 -0
- data/lib/parser.rb +169 -0
- data/lib/scanner.rb +142 -0
- data/lib/token.rb +19 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 16593a5279ec84214a8d4d9f23ff1ce276bb3e6d
|
4
|
+
data.tar.gz: b6931f4380cabfc14d81df6103493e73529728f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8e3c90af9bff0d99e2407618925757148442edb17ee714a0726756cdac51cfd53c26002cd1a6c22a22c8c634419fd192fd0ac0bcd51e55462298c5e169aedbcd
|
7
|
+
data.tar.gz: 684e318d602daede81648d7c44b5b042dd60b9e12e3e11d46c4c6a71ab732e6c913eab1975f93df5b3cba8019343f8f4d4ebdd51262c0e392bf4a29dc841e262
|
data/bin/calc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'calculator'
|
4
|
+
require 'calcex'
|
5
|
+
|
6
|
+
fichero = true
|
7
|
+
oper=:none
|
8
|
+
priori=:none
|
9
|
+
|
10
|
+
$calc = Calculator.new()
|
11
|
+
$calc.EnvVar
|
12
|
+
|
13
|
+
ARGV.each do |v|
|
14
|
+
if v.include? ?. then
|
15
|
+
oper=:fich
|
16
|
+
end
|
17
|
+
|
18
|
+
case v
|
19
|
+
when "-e"
|
20
|
+
oper=:e
|
21
|
+
when "-v"
|
22
|
+
if oper==:none then
|
23
|
+
oper=:v
|
24
|
+
end
|
25
|
+
else
|
26
|
+
case oper
|
27
|
+
when :e
|
28
|
+
$calc.ArgPri(v)
|
29
|
+
when :v
|
30
|
+
$calc.ArgNoPri(v)
|
31
|
+
when :fich
|
32
|
+
fichero = false
|
33
|
+
$calc.eval(v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if fichero then
|
39
|
+
$stdout.print "> "
|
40
|
+
end
|
41
|
+
|
42
|
+
while fichero && text = $stdin.gets do
|
43
|
+
|
44
|
+
begin
|
45
|
+
$calc.eval(text).to_s
|
46
|
+
rescue ParseError
|
47
|
+
puts "*parse error"
|
48
|
+
rescue UnrecognizedTokenException
|
49
|
+
puts "UnrecognizedTokenException"
|
50
|
+
rescue
|
51
|
+
puts "Unkown exception"
|
52
|
+
end
|
53
|
+
$stdout.print "> "
|
54
|
+
end
|
55
|
+
|
data/lib/ast.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
class BinaryNode
|
4
|
+
attr_reader :left, :right
|
5
|
+
|
6
|
+
def initialize(left,right)
|
7
|
+
@left = left
|
8
|
+
@right = right
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class UnaryNode
|
13
|
+
attr_reader :subTree
|
14
|
+
|
15
|
+
def initialize(subTree)
|
16
|
+
@subTree = subTree
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class AddNode < BinaryNode
|
21
|
+
def initialize(left, right)
|
22
|
+
super(left,right)
|
23
|
+
end
|
24
|
+
|
25
|
+
def evaluate()
|
26
|
+
return @left.evaluate() + @right.evaluate()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class SubNode < BinaryNode
|
31
|
+
def initialize(left, right)
|
32
|
+
super(left,right)
|
33
|
+
end
|
34
|
+
|
35
|
+
def evaluate
|
36
|
+
return @left.evaluate - @right.evaluate
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
class StoreNode < UnaryNode
|
42
|
+
def initialize(subTree)
|
43
|
+
super(subTree)
|
44
|
+
end
|
45
|
+
|
46
|
+
def evaluate
|
47
|
+
$calc.memory = subTree.evaluate
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class RecallNode
|
52
|
+
def evaluate
|
53
|
+
$calc.memory
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class CleanNode
|
58
|
+
def evaluate
|
59
|
+
$calc.memory = 0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
class MinusNode < UnaryNode
|
65
|
+
def initialize(subTree)
|
66
|
+
super(subTree)
|
67
|
+
end
|
68
|
+
|
69
|
+
def evaluate
|
70
|
+
val = subTree.evaluate.to_i
|
71
|
+
$calc.memory -= val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class PlusNode < UnaryNode
|
76
|
+
def initialize(subTree)
|
77
|
+
super(subTree)
|
78
|
+
end
|
79
|
+
|
80
|
+
def evaluate
|
81
|
+
val = subTree.evaluate
|
82
|
+
$calc.memory += val
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class NumNode
|
87
|
+
def initialize(num)
|
88
|
+
@num = num
|
89
|
+
end
|
90
|
+
|
91
|
+
def evaluate()
|
92
|
+
@num
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
class TimesNode < BinaryNode
|
98
|
+
def initialize(left, right)
|
99
|
+
super(left,right)
|
100
|
+
end
|
101
|
+
|
102
|
+
def evaluate()
|
103
|
+
@left.evaluate() * @right.evaluate()
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
class DivideNode < BinaryNode
|
109
|
+
def initialize(left, right)
|
110
|
+
super(left,right)
|
111
|
+
end
|
112
|
+
|
113
|
+
def evaluate
|
114
|
+
@left.evaluate() / @right.evaluate()
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
class ModuleNode < BinaryNode
|
120
|
+
def initialize(left, right)
|
121
|
+
super(left,right)
|
122
|
+
end
|
123
|
+
|
124
|
+
def evaluate
|
125
|
+
@left.evaluate() % @right.evaluate()
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class GuardarNode
|
130
|
+
def initialize(var,val)
|
131
|
+
@var = var
|
132
|
+
@val = val
|
133
|
+
end
|
134
|
+
|
135
|
+
def evaluate
|
136
|
+
$calc.guardar(@var,@val)
|
137
|
+
return @val
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class LlamarNode
|
142
|
+
def initialize(var)
|
143
|
+
@var = var
|
144
|
+
end
|
145
|
+
|
146
|
+
def evaluate
|
147
|
+
$calc.llamar(@var)
|
148
|
+
end
|
149
|
+
end
|
data/lib/calcex.rb
ADDED
data/lib/calculator.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'parser'
|
2
|
+
require 'ast'
|
3
|
+
|
4
|
+
class Calculator
|
5
|
+
attr_accessor :memory
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
@memory = 0
|
9
|
+
@map = Hash.new(0)
|
10
|
+
@vblis = ""
|
11
|
+
end
|
12
|
+
|
13
|
+
def eval(expr)
|
14
|
+
parser = Parser.new(expr)
|
15
|
+
parser.parse()
|
16
|
+
end
|
17
|
+
|
18
|
+
def guardar(var,val)
|
19
|
+
@map[var] = val
|
20
|
+
@vblis += var + " <- " + val.to_s + ", "
|
21
|
+
end
|
22
|
+
|
23
|
+
def guardarAE(var,val)
|
24
|
+
@map[var] = val
|
25
|
+
end
|
26
|
+
|
27
|
+
def llamar(var)
|
28
|
+
return @map[var]
|
29
|
+
end
|
30
|
+
|
31
|
+
def EnvVar
|
32
|
+
ENV.each do |k,v|
|
33
|
+
if k.match("CALCVAR") then
|
34
|
+
var = k[7,k.length]
|
35
|
+
val = v.to_i
|
36
|
+
$calc.guardarAE(var,val)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def ArgPri(varia)
|
42
|
+
pr = varia.index('=')
|
43
|
+
if pr != nil then
|
44
|
+
var = varia[0,pr]
|
45
|
+
if @map.has_key?(var) == false then
|
46
|
+
val = varia[pr+1,varia.length].to_i
|
47
|
+
$calc.guardarAE(var,val)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def ArgNoPri(varia)
|
53
|
+
pr = varia.index('=')
|
54
|
+
if pr != nil then
|
55
|
+
var = varia[0,pr]
|
56
|
+
val = varia[pr+1,varia.length].to_i
|
57
|
+
$calc.guardarAE(var,val)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def imprimir(line,result)
|
62
|
+
if line.include? "=" then
|
63
|
+
copva = @vblis.chop.chop
|
64
|
+
puts "=> " + result.to_s + " [" + copva + "]"
|
65
|
+
@vblis = ""
|
66
|
+
else
|
67
|
+
puts "=> " + result.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/parser.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'ast'
|
2
|
+
require 'scanner'
|
3
|
+
require 'token'
|
4
|
+
require 'calcex'
|
5
|
+
|
6
|
+
class Parser
|
7
|
+
def initialize(expr)
|
8
|
+
@fichi = expr
|
9
|
+
@scan = Scanner.new()
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse()
|
13
|
+
Prog()
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def Prog()
|
18
|
+
ListExpr()
|
19
|
+
end
|
20
|
+
|
21
|
+
def ListExpr()
|
22
|
+
if @fichi.include? ?. then
|
23
|
+
File.open(@fichi) do |f|
|
24
|
+
while line = f.gets
|
25
|
+
@scan.CogeLinea(line)
|
26
|
+
result = Expr()
|
27
|
+
t = @scan.getToken()
|
28
|
+
$calc.imprimir(line, result.evaluate())
|
29
|
+
if t.type != :eof then
|
30
|
+
raise ParseError.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
@scan.CogeLinea(@fichi)
|
36
|
+
result = Expr()
|
37
|
+
t = @scan.getToken()
|
38
|
+
$calc.imprimir(@fichi, result.evaluate())
|
39
|
+
if t.type != :eof then
|
40
|
+
raise ParseError.new
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def Expr()
|
46
|
+
return RestExpr(Term())
|
47
|
+
end
|
48
|
+
|
49
|
+
def RestExpr(e)
|
50
|
+
t = @scan.getToken()
|
51
|
+
|
52
|
+
if t.type == :add then
|
53
|
+
return RestExpr(AddNode.new(e,Term()))
|
54
|
+
end
|
55
|
+
|
56
|
+
if t.type == :sub then
|
57
|
+
return RestExpr(SubNode.new(e,Term()))
|
58
|
+
end
|
59
|
+
|
60
|
+
@scan.putBackToken()
|
61
|
+
|
62
|
+
return e
|
63
|
+
end
|
64
|
+
|
65
|
+
def Term()
|
66
|
+
RestTerm(Storable())
|
67
|
+
end
|
68
|
+
|
69
|
+
def RestTerm(e)
|
70
|
+
t = @scan.getToken
|
71
|
+
|
72
|
+
if t.type == :times then
|
73
|
+
return RestTerm(TimesNode.new(e,Storable()))
|
74
|
+
end
|
75
|
+
|
76
|
+
if t.type == :divide then
|
77
|
+
return RestTerm(DivideNode.new(e,Storable()))
|
78
|
+
end
|
79
|
+
|
80
|
+
if t.type == :module then
|
81
|
+
return RestTerm(ModuleNode.new(e,Storable()))
|
82
|
+
end
|
83
|
+
|
84
|
+
@scan.putBackToken
|
85
|
+
|
86
|
+
return e
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def Storable()
|
91
|
+
MemOperation(Factor())
|
92
|
+
end
|
93
|
+
|
94
|
+
def MemOperation(e)
|
95
|
+
|
96
|
+
t = @scan.getToken
|
97
|
+
if (t.type == :keyword) then
|
98
|
+
if (t.lex == "S") then
|
99
|
+
return StoreNode.new(e)
|
100
|
+
end
|
101
|
+
if (t.lex == "P") then
|
102
|
+
return PlusNode.new(e)
|
103
|
+
end
|
104
|
+
if (t.lex == "M") then
|
105
|
+
return MinusNode.new(e)
|
106
|
+
end
|
107
|
+
raise ParseError.new
|
108
|
+
end
|
109
|
+
|
110
|
+
@scan.putBackToken
|
111
|
+
return e
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def Factor()
|
116
|
+
|
117
|
+
t = @scan.getToken
|
118
|
+
|
119
|
+
if t.type == :number then
|
120
|
+
return NumNode.new(t.lex.to_i)
|
121
|
+
end
|
122
|
+
|
123
|
+
if t.type == :keyword then
|
124
|
+
if t.lex == "R" then
|
125
|
+
return RecallNode.new
|
126
|
+
end
|
127
|
+
if t.lex == "C" then
|
128
|
+
return CleanNode.new
|
129
|
+
end
|
130
|
+
|
131
|
+
raise ParseError.new
|
132
|
+
end
|
133
|
+
|
134
|
+
if t.type == :identifier then
|
135
|
+
@scan.putBackToken
|
136
|
+
return Assignable()
|
137
|
+
end
|
138
|
+
|
139
|
+
if t.type == :lparen then
|
140
|
+
result = Expr()
|
141
|
+
|
142
|
+
t = @scan.getToken
|
143
|
+
|
144
|
+
if t.type == :rparen then
|
145
|
+
return result
|
146
|
+
end
|
147
|
+
raise ParseError.new
|
148
|
+
end
|
149
|
+
raise ParseError.new
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def Assignable()
|
154
|
+
t = @scan.getToken
|
155
|
+
var = t.lex
|
156
|
+
Assign(var)
|
157
|
+
end
|
158
|
+
|
159
|
+
def Assign(var)
|
160
|
+
t = @scan.getToken
|
161
|
+
|
162
|
+
if t.type == :equ then
|
163
|
+
val = Expr().evaluate().to_i
|
164
|
+
return GuardarNode.new(var,val)
|
165
|
+
else
|
166
|
+
@scan.putBackToken
|
167
|
+
return LlamarNode.new(var)
|
168
|
+
end
|
169
|
+
end
|
data/lib/scanner.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'calcex'
|
3
|
+
|
4
|
+
class Scanner
|
5
|
+
def initialize()
|
6
|
+
@istream = StringIO.new("")
|
7
|
+
@keywords = Set.new(["S","R","M","P","C"])
|
8
|
+
@lineCount = 1
|
9
|
+
@colCount = -1
|
10
|
+
@needToken = true
|
11
|
+
@lastToken = nil
|
12
|
+
end
|
13
|
+
def CogeLinea(line)
|
14
|
+
@istream = StringIO.new(line)
|
15
|
+
end
|
16
|
+
|
17
|
+
def putBackToken
|
18
|
+
@needToken = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def getToken
|
22
|
+
unless @needToken
|
23
|
+
@needToken = true
|
24
|
+
return @lastToken
|
25
|
+
end
|
26
|
+
|
27
|
+
state = 0
|
28
|
+
foundOne = false
|
29
|
+
c = @istream.getc()
|
30
|
+
|
31
|
+
if @istream.eof() then
|
32
|
+
@lastToken = Token.new(:eof,@lineCount,@colCount)
|
33
|
+
return @lastToken
|
34
|
+
end
|
35
|
+
|
36
|
+
until foundOne
|
37
|
+
@colCount = @colCount + 1
|
38
|
+
case state
|
39
|
+
when 0
|
40
|
+
lex = ""
|
41
|
+
column = @colCount
|
42
|
+
line = @lineCount
|
43
|
+
if isLetter(c) then state=1
|
44
|
+
elsif isDigit(c) then state=2
|
45
|
+
elsif c == ?+ then state = 3
|
46
|
+
elsif c == ?- then state = 4
|
47
|
+
elsif c == ?* then state = 5
|
48
|
+
elsif c == ?/ then state = 6
|
49
|
+
elsif c == ?( then state = 7
|
50
|
+
elsif c == ?) then state = 8
|
51
|
+
elsif c == ?% then state = 9
|
52
|
+
elsif c == ?= then state = 10
|
53
|
+
elsif c == ?\n then
|
54
|
+
@colCount = -1
|
55
|
+
@lineCount = @lineCount+1
|
56
|
+
elsif isWhiteSpace(c) then state = state
|
57
|
+
elsif @istream.eof() then
|
58
|
+
@foundOne = true
|
59
|
+
type = :eof
|
60
|
+
else
|
61
|
+
raise UnrecognizedTokenException
|
62
|
+
end
|
63
|
+
when 1
|
64
|
+
if isLetter(c) or isDigit(c) then state = 1
|
65
|
+
else
|
66
|
+
if @keywords.include?(lex) then
|
67
|
+
foundOne = true
|
68
|
+
type = :keyword
|
69
|
+
else
|
70
|
+
foundOne = true
|
71
|
+
type = :identifier
|
72
|
+
end
|
73
|
+
end
|
74
|
+
when 2
|
75
|
+
if isDigit(c) then state = 2
|
76
|
+
else
|
77
|
+
type = :number
|
78
|
+
foundOne = true
|
79
|
+
end
|
80
|
+
when 3
|
81
|
+
type = :add
|
82
|
+
foundOne = true
|
83
|
+
when 4
|
84
|
+
type = :sub
|
85
|
+
foundOne = true
|
86
|
+
when 5
|
87
|
+
type = :times
|
88
|
+
foundOne = true
|
89
|
+
when 6
|
90
|
+
type = :divide
|
91
|
+
foundOne = true
|
92
|
+
when 7
|
93
|
+
type = :lparen
|
94
|
+
foundOne = true
|
95
|
+
when 8
|
96
|
+
type = :rparen
|
97
|
+
foundOne = true
|
98
|
+
when 9
|
99
|
+
type = :module
|
100
|
+
foundOne = true
|
101
|
+
when 10
|
102
|
+
type = :equ
|
103
|
+
foundOne = true
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
if !foundOne then
|
108
|
+
lex.concat(c)
|
109
|
+
if @istream.eof() and state == 0 then
|
110
|
+
@lastToken = Token.new(:eof,@lineCount,@colCount)
|
111
|
+
return @lastToken
|
112
|
+
end
|
113
|
+
c = @istream.getc()
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
@istream.ungetc(c)
|
119
|
+
@colCount = @colCount - 1
|
120
|
+
if type == :number or type == :identifier or type == :keyword then
|
121
|
+
t = LexicalToken.new(type,lex,line,column)
|
122
|
+
else
|
123
|
+
t = Token.new(type,line,column)
|
124
|
+
end
|
125
|
+
|
126
|
+
@lastToken = t
|
127
|
+
return t
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
def isLetter(c)
|
132
|
+
return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
|
133
|
+
end
|
134
|
+
|
135
|
+
def isDigit(c)
|
136
|
+
return (?0 <= c and c <= ?9)
|
137
|
+
end
|
138
|
+
|
139
|
+
def isWhiteSpace(c)
|
140
|
+
return (c == ?\ or c == ?\n or c == ?\t)
|
141
|
+
end
|
142
|
+
end
|
data/lib/token.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class Token
|
2
|
+
attr_reader :type, :line, :col
|
3
|
+
|
4
|
+
def initialize(type,lineNum,colNum)
|
5
|
+
@type = type
|
6
|
+
@line = lineNum
|
7
|
+
@col = colNum
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class LexicalToken < Token
|
12
|
+
attr_reader :lex
|
13
|
+
|
14
|
+
def initialize(type,lex,lineNum,colNum)
|
15
|
+
super(type,lineNum,colNum)
|
16
|
+
|
17
|
+
@lex = lex
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: calc_esilvac
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kent D. Lee - Juan Francisco Cardona Mc - Esteban Silva
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: An calculator implementation on ruby
|
14
|
+
email: fcardona@eafit.edu.co - esilvac@eafit.edu.co
|
15
|
+
executables:
|
16
|
+
- calc
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/calc
|
21
|
+
- lib/ast.rb
|
22
|
+
- lib/calcex.rb
|
23
|
+
- lib/calculator.rb
|
24
|
+
- lib/parser.rb
|
25
|
+
- lib/scanner.rb
|
26
|
+
- lib/token.rb
|
27
|
+
homepage: http://www1.eafit.edu.co/fcardona/cursos/st0244/rubycal
|
28
|
+
licenses:
|
29
|
+
- ARTISTIC
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.2.2
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Another calculator in ruby
|
51
|
+
test_files: []
|