calc_jmoral33 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b03799e06e05f328a4dcb967e97666f2241a44e6
4
+ data.tar.gz: 538c6fca6fc7a92a8cc06c494bee2590598011b1
5
+ SHA512:
6
+ metadata.gz: cc1a872f1e934c7cb78d02175b68b18885599bbf91afd4e29f183b726b81eb1c47cf72ce27941fd4abd4fb1f43e88f5872d1f21030ea7c57aacf3455077f30a7
7
+ data.tar.gz: 6ec3cd874518cd16813631f44496118f5601722343882f139df25652ab525ea5353cd23a1844f6d8f72369f13840856c981d876abed812f5edbd569ae010ca92
data/bin/calc ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'calculator'
5
+ require 'calcex'
6
+
7
+
8
+ $calc = Calculator.new()
9
+
10
+ file = File.new("bin/operaciones.txt")
11
+
12
+ $calc.evalFile(file)
13
+
14
+ begin
15
+ $stdout.print "> "
16
+ $stdout.flush
17
+ text = gets
18
+ if(!text)
19
+ break
20
+ end
21
+
22
+ # line_num=0
23
+ # text=File.open('operaciones.txt').read
24
+ # text.gsub!(/\r\n?/, "\n")
25
+ # text.each_line do |line|
26
+ # print "= " + $calc.eval(line).to_s
27
+ # end
28
+
29
+ if(text!="\n")
30
+
31
+ print "= " + $calc.eval(text).to_s
32
+
33
+ if(!$calc.assigns.empty?)
34
+ assigns = $calc.assigns
35
+ print "[ "
36
+ assigns.each {|key,value| print "#{value} "}
37
+ print "]"
38
+
39
+ puts ""
40
+ else
41
+ puts ""
42
+ end
43
+ $calc.assigns.clear
44
+ else
45
+ puts "Parse Error, needed an expresion"
46
+
47
+ end
48
+
49
+ rescue ParseError
50
+ puts "Parse Error"
51
+ rescue UnrecognizedTokenException
52
+ puts "UnrecognizedTokenException"
53
+ rescue
54
+ puts "Unkown exception"
55
+ end until ($calc.eol and $calc.eof)
data/lib/ast.rb ADDED
@@ -0,0 +1,147 @@
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 AssignNode < UnaryNode
21
+ def initialize(id,subTree)
22
+ super(subTree)
23
+ @id=id
24
+ end
25
+
26
+ def evaluate
27
+ val = @subTree.evaluate
28
+ $calc.insert(@id,val)
29
+ #realizar asignacion
30
+ return val
31
+ end
32
+ end
33
+
34
+ class IdentifierNode
35
+ def initialize(id)
36
+ @id=id
37
+ end
38
+
39
+ def evaluate
40
+ return $calc.search(@id)
41
+ end
42
+ end
43
+
44
+ class AddNode < BinaryNode
45
+ def initialize(left, right)
46
+ super(left,right)
47
+ end
48
+
49
+ def evaluate
50
+ @left.evaluate + @right.evaluate
51
+ end
52
+ end
53
+
54
+ class SubNode < BinaryNode
55
+ def initialize(left, right)
56
+ super(left,right)
57
+ end
58
+
59
+ def evaluate
60
+ @left.evaluate - @right.evaluate
61
+ end
62
+ end
63
+
64
+ class NumNode
65
+ def initialize(num)
66
+ @num = num
67
+ end
68
+
69
+ def evaluate
70
+ @num
71
+ end
72
+ end
73
+
74
+ class StoreNode < UnaryNode
75
+ def initialize(subTree)
76
+ super(subTree)
77
+ end
78
+
79
+ def evaluate
80
+ $calc.memory=subTree.evaluate
81
+ end
82
+ end
83
+
84
+ class PlusNode < UnaryNode
85
+ def initialize(subTree)
86
+ super(subTree)
87
+ end
88
+
89
+ def evaluate
90
+ $calc.memory+=subTree.evaluate
91
+ end
92
+ end
93
+
94
+ class MinusNode < UnaryNode
95
+ def initialize(subTree)
96
+ super(subTree)
97
+ end
98
+
99
+ def evaluate
100
+ $calc.memory-=subTree.evaluate
101
+ end
102
+ end
103
+
104
+ class ClearNode
105
+ def evaluate
106
+ $calc.memory2.clear
107
+ $calc.memory=0
108
+
109
+ end
110
+ end
111
+
112
+ class RecallNode
113
+ def evaluate
114
+ $calc.memory
115
+ end
116
+ end
117
+
118
+
119
+ class TimesNode < 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 DivideNode < BinaryNode
130
+ def initialize(left,right)
131
+ super(left,right)
132
+ end
133
+
134
+ def evaluate
135
+ @left.evaluate/@right.evaluate
136
+ end
137
+ end
138
+
139
+ class ModuloNode < BinaryNode
140
+ def initialize(left,right)
141
+ super(left,right)
142
+ end
143
+
144
+ def evaluate
145
+ @left.evaluate%@right.evaluate
146
+ end
147
+ end
data/lib/calcex.rb ADDED
@@ -0,0 +1,3 @@
1
+
2
+ class ParseError < Exception; end
3
+ class UnrecognizedTokenException < Exception; end
data/lib/calculator.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'parser'
2
+ require 'ast'
3
+
4
+ class Calculator
5
+ attr_accessor :memory
6
+ attr_accessor :memory2
7
+ attr_accessor :eol
8
+ attr_accessor :eof
9
+ attr_accessor :countAssigns
10
+ attr_accessor :assigns
11
+ def initialize()
12
+ @memory = 0
13
+ @memory2 = Hash.new(0)
14
+ @eol = false
15
+ @eof = false
16
+ @assigns = Hash.new("")
17
+ @countAssigns = 0
18
+ end
19
+
20
+ def eval(expr)
21
+ parser = Parser.new(StringIO.new(expr))
22
+ ast = parser.parse()
23
+ return ast.evaluate()
24
+ end
25
+
26
+ def insert(id,val)
27
+ @assigns[countAssigns] = id.to_s + " <- " + val.to_s
28
+ @countAssigns += 1
29
+ @memory2[id] = val
30
+
31
+ end
32
+
33
+ def evalFile(file)
34
+ file.each{|line|
35
+ if(line!="\n")
36
+ puts "= " + $calc.eval(line).to_s
37
+ else
38
+ puts "Needed an expresion"
39
+ end
40
+ }
41
+ end
42
+
43
+ def search(id)
44
+ if(@memory2.keys.include?(id))
45
+ return @memory2[id]
46
+ else
47
+ return 0
48
+ end
49
+ end
50
+ end
data/lib/parser.rb ADDED
@@ -0,0 +1,163 @@
1
+ require 'ast'
2
+ require 'scanner'
3
+ require 'token'
4
+ require 'calcex'
5
+
6
+ class Parser
7
+ def initialize(istream)
8
+ @scan = Scanner.new(istream)
9
+ end
10
+
11
+ def parse
12
+ return Prog()
13
+ end
14
+
15
+ private
16
+ def Prog
17
+ result = Expr()
18
+ t = @scan.getToken
19
+
20
+ if t.type == :eol
21
+ $calc.eol=true
22
+ else
23
+ $calc.eol=false
24
+ $calc.eof=true
25
+
26
+ end
27
+
28
+ return result
29
+
30
+ if t.type != :eof then
31
+ print "Expected EOF. Found ", t.type, ".\n"
32
+ raise ParseError.new
33
+ end
34
+
35
+
36
+ end
37
+
38
+ def Expr
39
+ return RestExpr(Term())
40
+ end
41
+
42
+ def RestExpr(e)
43
+ t = @scan.getToken()
44
+
45
+ if t.type == :add then
46
+ return RestExpr(AddNode.new(e,Term()))
47
+ end
48
+
49
+ if t.type == :sub then
50
+ return RestExpr(SubNode.new(e,Term()))
51
+ end
52
+
53
+ @scan.putBackToken
54
+
55
+ return e
56
+ end
57
+
58
+ def Term
59
+ # Write your Term() code here. This code is just temporary
60
+ # so you can try the calculator out before finishing it.
61
+
62
+ return RestTerm(Storable())
63
+
64
+
65
+ puts "Term not implemented\n"
66
+
67
+ raise ParseError.new
68
+ end
69
+
70
+ def RestTerm(e)
71
+ t = @scan.getToken
72
+
73
+ if t.type == :times then
74
+ return RestTerm(TimesNode.new(e,Term()))
75
+ end
76
+
77
+ if t.type == :divide then
78
+ return RestTerm(DivideNode.new(e,Term()))
79
+ end
80
+
81
+ if t.type == :modulo then
82
+ return RestTerm(ModuloNode.new(e,Term()))
83
+ end
84
+
85
+ @scan.putBackToken
86
+
87
+ return e
88
+
89
+ puts "RestTerm not implemented"
90
+ raise ParseError.new # "Parse Error"
91
+
92
+ end
93
+
94
+ def Storable
95
+ return MemOperation(Factor())
96
+
97
+ end
98
+
99
+ def MemOperation(e)
100
+ t=@scan.getToken()
101
+ if (t.type==:keyword)
102
+ if (t.lex=="S")
103
+ return StoreNode.new(e)
104
+ elsif(t.lex=="M")
105
+ return MinusNode.new(e)
106
+ elsif(t.lex=="P")
107
+ return PlusNode.new(e)
108
+ end
109
+ end
110
+
111
+ @scan.putBackToken
112
+ return e
113
+
114
+ end
115
+
116
+ def Assignable
117
+ t=@scan.getToken
118
+ if(t.type == :identifier)
119
+
120
+ result=Assign(t.lex.to_s)
121
+ return result
122
+ end
123
+
124
+ end
125
+
126
+ def Assign(id)
127
+ t=@scan.getToken
128
+ if(t.type==:assign)
129
+ return AssignNode.new(id,Expr())
130
+ end
131
+ @scan.putBackToken
132
+ return IdentifierNode.new(id)
133
+ end
134
+
135
+
136
+ def Factor
137
+
138
+ t = @scan.getToken
139
+
140
+ if t.type == :number then
141
+ val = t.lex.to_i
142
+ return NumNode.new(val)
143
+ elsif(t.type == :keyword)
144
+ if(t.lex == "R")
145
+ return RecallNode.new
146
+ elsif(t.lex== "C")
147
+ return ClearNode.new
148
+ end
149
+ elsif(t.type == :lparen)
150
+ result=Expr()
151
+ t=@scan.getToken
152
+ if(t.type== :rparen)
153
+ return result
154
+ else
155
+ puts "Expected right parentheses"
156
+ end
157
+ end
158
+
159
+ @scan.putBackToken
160
+ return Assignable()
161
+
162
+ end
163
+ end
data/lib/scanner.rb ADDED
@@ -0,0 +1,140 @@
1
+ require 'stringio'
2
+ require 'calcex'
3
+
4
+ class Scanner
5
+ def initialize(inStream)
6
+ @istream = inStream
7
+ @keywords = Set.new(["S","R","M","P","C"])
8
+ @lineCount = 1
9
+ @colCount = -1
10
+ @needToken = true
11
+ @lastToken = nil
12
+ end
13
+
14
+ def putBackToken
15
+ @needToken = false
16
+ end
17
+
18
+ def getToken
19
+ unless @needToken
20
+ @needToken = true
21
+ return @lastToken
22
+ end
23
+
24
+ state = 0
25
+ foundOne = false
26
+ c = @istream.getc
27
+
28
+ if @istream.eof? then
29
+ @lastToken = Token.new(:eof,@lineCount,@colCount)
30
+ return @lastToken
31
+ end
32
+
33
+ until foundOne
34
+ @colCount +=1
35
+ case state
36
+ when 0
37
+ lex = ""
38
+ column = @colCount
39
+ line = @lineCount
40
+ if isLetter(c) then state=1
41
+ elsif isDigit(c) then state=2
42
+ elsif c == ?+ then state = 3
43
+ elsif c == ?- then state = 4
44
+ elsif c == ?* then state = 5
45
+ elsif c == ?/ then state = 6
46
+ elsif c == ?( then state = 7
47
+ elsif c == ?) then state = 8
48
+ elsif c == ?% then state=9
49
+ elsif c == ?= then state = 10
50
+ elsif c == ?\n then
51
+ state =11
52
+ @colCount = -1
53
+ @lineCount = @lineCount+1
54
+ elsif isWhiteSpace(c) then state = state #ignore whitespace
55
+ elsif @istream.eof() then
56
+ @foundOne = true
57
+ type = :eof
58
+ else
59
+ puts "Unrecognized Token found at line ",line," and column ",column,"\n"
60
+ raise UnrecognizedTokenException # "Unrecognized Token"
61
+ end
62
+ when 1
63
+ if isLetter(c) or isDigit(c) then state = 1
64
+ else
65
+ if @keywords.include?(lex) then
66
+ foundOne = true
67
+ type = :keyword
68
+ else
69
+ foundOne = true
70
+ type = :identifier
71
+ end
72
+ end
73
+ when 2
74
+ if isDigit(c) then state = 2
75
+ else
76
+ type = :number
77
+ foundOne = true
78
+ end
79
+ when 3
80
+ type = :add
81
+ foundOne = true
82
+ when 4
83
+ type = :sub
84
+ foundOne = true
85
+ when 5
86
+ type = :times
87
+ foundOne = true
88
+ when 6
89
+ type = :divide
90
+ foundOne = true
91
+ when 7
92
+ type = :lparen
93
+ foundOne = true
94
+ when 8
95
+ type = :rparen
96
+ foundOne = true
97
+ when 9
98
+ type = :modulo
99
+ foundOne = true
100
+ when 10
101
+ type = :assign
102
+ foundOne = true
103
+ when 11
104
+ type = :eol
105
+ foundOne = true
106
+ end
107
+
108
+ if !foundOne then
109
+ lex.concat(c)
110
+ c = @istream.getc()
111
+ end
112
+
113
+ end
114
+
115
+ @istream.ungetc(c)
116
+ @colCount = @colCount - 1
117
+ if type == :number or type == :identifier or type == :keyword then
118
+ t = LexicalToken.new(type,lex,line,column)
119
+ else
120
+ t = Token.new(type,line,column)
121
+ end
122
+
123
+ @lastToken = t
124
+ return t
125
+
126
+ end
127
+
128
+ private
129
+ def isLetter(c)
130
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
131
+ end
132
+
133
+ def isDigit(c)
134
+ return (?0 <= c and c <= ?9)
135
+ end
136
+
137
+ def isWhiteSpace(c)
138
+ return (c == ?\ or c == ?\n or c == ?\t)
139
+ end
140
+ 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_jmoral33
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc - Juan Daniel Morales
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An calculator implementation on ruby
14
+ email: jmoral33@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.4.8
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Another calculator in ruby
51
+ test_files: []