calc_egonza21 0.0.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0a4a2baaaf483f0f2bd2ff9834fdcb3dd0371969
4
+ data.tar.gz: a5712945c01a2e9e2c70716b03e50d76096c0539
5
+ SHA512:
6
+ metadata.gz: b657b9fd89e55c981e4e7c2b3ae67c1e6779cee1a6cbece240c5b995b22b920f5c504a9eb3c48214472005c89ea72269d347fd11250056d1ae3fd162ee019f49
7
+ data.tar.gz: dc8471c50b52600f80082618d10dc7f257570d45c7d73900500fe63e34ba160e250e699c7a066a6764255ce0605083166899c63425aa670c59b01ff4cdede1e4
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'calculator'
5
+ require 'calcex'
6
+
7
+ $stdout.print "> "
8
+ $stdout.flush
9
+
10
+ text = gets
11
+
12
+ $calc = Calculator.new()
13
+
14
+ begin
15
+ puts "= " + $calc.eval(text).to_s
16
+ rescue ParseError
17
+ puts "Parse Error"
18
+ rescue UnrecognizedTokenException
19
+ puts "UnrecognizedTokenException"
20
+ rescue
21
+ puts "Unkown exception"
22
+ end
@@ -0,0 +1,83 @@
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
+ class StoreNode < UnaryNode
41
+ def initialize(subTree)
42
+ super(subTree)
43
+ end
44
+ def evaluate()
45
+ return $calc.memory = @subTree.evaluate()
46
+ end
47
+ end
48
+
49
+ class RecallNode
50
+ def evaluate
51
+ $calc.memory
52
+ end
53
+ end
54
+
55
+ class NumNode
56
+ def initialize(num)
57
+ @num = num
58
+ end
59
+
60
+ def evaluate()
61
+ return @num
62
+ end
63
+ end
64
+
65
+ class TimesNode < BinaryNode
66
+ def initialize(left, right)
67
+ super(left, right)
68
+ end
69
+
70
+ def evaluate()
71
+ return @left.evaluate() * @right.evaluate()
72
+ end
73
+ end
74
+
75
+ class DivideNode < BinaryNode
76
+ def initialize(left, right)
77
+ super(left, right)
78
+ end
79
+
80
+ def evaluate()
81
+ return @left.evaluate() / @right.evaluate()
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+
2
+ class ParseError < Exception; end
3
+ class UnrecognizedTokenException < Exception; end
@@ -0,0 +1,17 @@
1
+ require 'parser'
2
+ require 'ast'
3
+
4
+ class Calculator
5
+ attr_reader :memory
6
+ attr_writer :memory
7
+
8
+ def initialize()
9
+ @memory = 0
10
+ end
11
+
12
+ def eval(expr)
13
+ parser = Parser.new(StringIO.new(expr))
14
+ ast = parser.parse()
15
+ return ast.evaluate()
16
+ end
17
+ end
@@ -0,0 +1,129 @@
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 != :eof then
21
+ print "Expected EOF. Found ", t.type, ".\n"
22
+ raise ParseError.new
23
+ end
24
+
25
+ result
26
+ end
27
+
28
+ def Expr
29
+ RestExpr(Term())
30
+ end
31
+
32
+ def RestExpr(e)
33
+ t = @scan.getToken
34
+
35
+ if t.type == :add then
36
+ return RestExpr(AddNode.new(e,Term()))
37
+ end
38
+
39
+ if t.type == :sub then
40
+ return RestExpr(SubNode.new(e,Term()))
41
+ end
42
+
43
+ @scan.putBackToken()
44
+
45
+ return e
46
+ end
47
+
48
+ 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
+ RestTerm(Storable())
63
+ end
64
+
65
+ def RestTerm(e)
66
+ t = @scan.getToken
67
+
68
+ if t.type == :times then
69
+ return RestTerm(TimesNode.new(e,Storable()))
70
+ end
71
+
72
+ if t.type == :divide then
73
+ return RestTerm(DivideNode.new(e,Storable()))
74
+ end
75
+
76
+ @scan.putBackToken
77
+
78
+ return e
79
+ end
80
+
81
+ def Storable
82
+ result = Factor()
83
+
84
+ t = @scan.getToken
85
+ if t.type == :keyword then
86
+ if t.lex == "S" then
87
+ return StoreNode.new(result)
88
+ end
89
+ puts "Expected S found: #{t.lex} at line: #{t.line} col: #{t.col}"
90
+
91
+ raise ParseError.new
92
+ end
93
+
94
+ @scan.putBackToken
95
+ result
96
+ end
97
+
98
+ def Factor()
99
+ t = @scan.getToken
100
+
101
+ if t.type == :number then
102
+ num = t.lex.to_i
103
+ return NumNode.new(num)
104
+ end
105
+
106
+ if t.type == :keyword then
107
+ if t.lex == "R" then
108
+ return RecallNode.new
109
+ end
110
+ puts "Parser Error: expected R found: " + t.lex
111
+ puts "at line: " + t.line.to_s + " col: " + t.col.to_s
112
+ raise ParseError.new
113
+ end
114
+
115
+ if t.type == :lparen then
116
+ result = Expr()
117
+ t = @scan.getToken
118
+ if t.type == :rparen then
119
+ return result
120
+ end
121
+ puts "Parse Error: Expected ) found: #{t.lex}"
122
+ puts "at line: #{t.line} col: #{t.col}"
123
+ raise ParseError.new
124
+ end
125
+ print "Parse Error: Expected number , R , ( found : #{t.type}"
126
+ puts " at line: #{t.line} col: #{t.col}"
127
+ raise ParseError
128
+ end
129
+ end
@@ -0,0 +1,127 @@
1
+ require 'stringio'
2
+ require 'calcex'
3
+
4
+ class Scanner
5
+ def initialize(inStream)
6
+ @istream = inStream
7
+ @keywords = Set.new(%w{S R})
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 == ?\n then
49
+ @colCount = -1
50
+ @lineCount = @lineCount+1
51
+ elsif isWhiteSpace(c) then state = state #ignore whitespace
52
+ elsif @istream.eof() then
53
+ @foundOne = true
54
+ type = :eof
55
+ else
56
+ puts "Unrecognized Token found at line ",line," and column ",column,"\n"
57
+ raise UnrecognizedTokenException # "Unrecognized Token"
58
+ end
59
+ when 1
60
+ if isLetter(c) or isDigit(c) then state = 1
61
+ else
62
+ if @keywords.include?(lex) then
63
+ foundOne = true
64
+ type = :keyword
65
+ else
66
+ foundOne = true
67
+ type = :identifier
68
+ end
69
+ end
70
+ when 2
71
+ if isDigit(c) then state = 2
72
+ else
73
+ type = :number
74
+ foundOne = true
75
+ end
76
+ when 3
77
+ type = :add
78
+ foundOne = true
79
+ when 4
80
+ type = :sub
81
+ foundOne = true
82
+ when 5
83
+ type = :times
84
+ foundOne = true
85
+ when 6
86
+ type = :divide
87
+ foundOne = true
88
+ when 7
89
+ type = :lparen
90
+ foundOne = true
91
+ when 8
92
+ type = :rparen
93
+ foundOne = true
94
+ end
95
+
96
+ if !foundOne then
97
+ lex.concat(c)
98
+ c = @istream.getc()
99
+ end
100
+
101
+ end
102
+
103
+ @istream.ungetc(c)
104
+ @colCount = @colCount - 1
105
+ if type == :number or type == :identifier or type == :keyword then
106
+ t = LexicalToken.new(type,lex,line,column)
107
+ else
108
+ t = Token.new(type,line,column)
109
+ end
110
+
111
+ @lastToken = t
112
+ return t
113
+ end
114
+
115
+ private
116
+ def isLetter(c)
117
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
118
+ end
119
+
120
+ def isDigit(c)
121
+ return (?0 <= c and c <= ?9)
122
+ end
123
+
124
+ def isWhiteSpace(c)
125
+ return (c == ?\ or c == ?\n or c == ?\t)
126
+ end
127
+ end
@@ -0,0 +1,20 @@
1
+
2
+ class Token
3
+ attr_reader :type, :line, :col
4
+
5
+ def initialize(type,lineNum,colNum)
6
+ @type = type
7
+ @line = lineNum
8
+ @col = colNum
9
+ end
10
+ end
11
+
12
+ class LexicalToken < Token
13
+ attr_reader :lex
14
+
15
+ def initialize(type,lex,lineNum,colNum)
16
+ super(type,lineNum,colNum)
17
+
18
+ @lex = lex
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calc_egonza21
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-10 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An calculator implementation on ruby
14
+ email: egonza21@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.7
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Another calculator in ruby
51
+ test_files: []