calc_rocampo3 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 269b76887048a78495cbf0d96259d7cf4cc4a7c0
4
+ data.tar.gz: ba8ac3b22b11c5650a51b954159617e3915cc129
5
+ SHA512:
6
+ metadata.gz: 778fa6041d89ee4310e5031bae4be8b30cbc2c5d683138e2d096e09a8acd479e9207de2439bd1f67ba477770239d6211844f4a513e3e123ef5a74124c37b01d3
7
+ data.tar.gz: 7ac7fe5ecd1c144c12faf55b44867a391712043346bf6fef807a1e8cece55bf9778dcfa2ac5ad1c1199a70244fa4cb76c8462dec4b5bfb1ade8c0a7605eebb96
@@ -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,84 @@
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 #AddNode hereda de BinaryNode
21
+ def initialize(left, right)
22
+ super(left,right)
23
+ end
24
+
25
+ def evaluate()
26
+ return @left.evaluate() + @right.evaluate() #obtiene los hijos derecho e izquierdo
27
+ end
28
+ end
29
+
30
+ class SubNode < BinaryNode #Hereda de BinaryNode (SubNode)
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 TimesNode < BinaryNode #Hereda de BinaryNode (TimesNode)
41
+ def initialize(left, right)
42
+ super(left,right)
43
+ end
44
+
45
+ def evaluate()
46
+ return @left.evaluate() * @right.evaluate()
47
+ end
48
+ end
49
+
50
+ class DivideNode < BinaryNode #Hereda de BinaryNode (DivideNode)
51
+ def initialize(left, right)
52
+ super(left,right)
53
+ end
54
+
55
+ def evaluate()
56
+ return @left.evaluate() / @right.evaluate()
57
+ end
58
+ end
59
+
60
+ class StoreNode < UnaryNode
61
+ def initialize(sub)
62
+ super(sub)
63
+ end
64
+
65
+ def evaluate()
66
+ $calc.memory = subTree.evaluate
67
+ end
68
+ end
69
+
70
+ class RecallNode
71
+ def evaluate
72
+ $calc.memory
73
+ end
74
+ end
75
+
76
+ class NumNode
77
+ def initialize(num)
78
+ @num = num
79
+ end
80
+
81
+ def evaluate()
82
+ return @num
83
+ end
84
+ end
@@ -0,0 +1,3 @@
1
+
2
+ class ParseError < Exception; end
3
+ class UnrecognizedTokenException < Exception; end
@@ -0,0 +1,21 @@
1
+ #Memoria de la calculadora
2
+
3
+ require 'parser'
4
+ require 'ast'
5
+
6
+ class Calculator
7
+
8
+ attr_accessor :memory
9
+ #attr_reader :memory
10
+ #attr_writer :memory
11
+
12
+ def initialize()
13
+ @memory = 0
14
+ end
15
+
16
+ def eval(expr)
17
+ parser = Parser.new(StringIO.new(expr))
18
+ ast = parser.parse()
19
+ return ast.evaluate()
20
+ end
21
+ end
@@ -0,0 +1,133 @@
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
+ return result
26
+ end
27
+
28
+ def Expr()
29
+ return 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
+
80
+ end
81
+
82
+ def Storable()
83
+ result = Factor()
84
+
85
+ t = @scan.getToken()
86
+
87
+ if t.type == :keyword then
88
+ if t.lex == "S" then
89
+ return StoreNode.new(result)
90
+ end
91
+ puts "Expected S found: ",t.lex
92
+ raise ParseError.new
93
+ end
94
+
95
+ @scan.putBackToken
96
+ result
97
+ end
98
+
99
+ def Factor()
100
+
101
+
102
+ t = @scan.getToken
103
+
104
+ if t.type == :number then
105
+ return NumNode.new(t.lex.to_i)
106
+ end
107
+
108
+ if t.type == :keyword then
109
+ if t.lex == "R" then
110
+ return RecallNode.new
111
+ end
112
+
113
+ puts "Expected R found: " + t.lex
114
+ raise ParseError.new # "Parse Error"
115
+ end
116
+
117
+ if t.type == :lparen then
118
+ result = Expr()
119
+
120
+ t = @scan.getToken
121
+
122
+ if t.type == :rparen then
123
+ result = Expr()
124
+ end
125
+
126
+ puts "Expected ) found: " + t.type.to_s
127
+ raise ParseError.new
128
+ end
129
+
130
+ puts "Expected number, R, ( found: " + t.type.to_s
131
+ raise ParseError.new
132
+ end
133
+ end
@@ -0,0 +1,129 @@
1
+ #Analizar la "Frase introducida" y partirla en los lexemas correspondientes
2
+
3
+ require 'stringio'#Flujo de entrada en un String
4
+ require 'calcex' #Es el modulo de las excepciones de Ruby
5
+
6
+ class Scanner
7
+ def initialize(inStream)
8
+ @istream = inStream
9
+ @keywords = Set.new(["S","R"])
10
+ @lineCount = 1
11
+ @colCount = -1
12
+ @needToken = true
13
+ @lastToken = nil
14
+ end
15
+
16
+ def putBackToken()
17
+ @needToken = false
18
+ end
19
+
20
+ def getToken()
21
+ unless @needToken
22
+ @needToken = true
23
+ return @lastToken
24
+ end
25
+
26
+ state = 0
27
+ foundOne = false
28
+ c = @istream.getc()
29
+
30
+ if @istream.eof() then
31
+ @lastToken = Token.new(:eof,@lineCount,@colCount)
32
+ return @lastToken
33
+ end
34
+
35
+ until foundOne
36
+ @colCount = @colCount + 1
37
+ case state
38
+ when 0
39
+ lex = ""
40
+ column = @colCount
41
+ line = @lineCount
42
+ if isLetter(c) then state=1
43
+ elsif isDigit(c) then state=2
44
+ elsif c == ?+ then state = 3
45
+ elsif c == ?- then state = 4
46
+ elsif c == ?* then state = 5
47
+ elsif c == ?/ then state = 6
48
+ elsif c == ?( then state = 7
49
+ elsif c == ?) then state = 8
50
+ elsif c == ?\n then
51
+ @colCount = -1
52
+ @lineCount = @lineCount+1
53
+ elsif isWhiteSpace(c) then state = state #ignore whitespace
54
+ elsif @istream.eof() then
55
+ @foundOne = true
56
+ type = :eof
57
+ else
58
+ puts "Unrecognized Token found at line ",line," and column ",column,"\n"
59
+ raise UnrecognizedTokenException # "Unrecognized Token"
60
+ end
61
+ when 1
62
+ if isLetter(c) or isDigit(c) then state = 1
63
+ else
64
+ if @keywords.include?(lex) then
65
+ foundOne = true
66
+ type = :keyword
67
+ else
68
+ foundOne = true
69
+ type = :identifier
70
+ end
71
+ end
72
+ when 2
73
+ if isDigit(c) then state = 2
74
+ else
75
+ type = :number
76
+ foundOne = true
77
+ end
78
+ when 3
79
+ type = :add
80
+ foundOne = true
81
+ when 4
82
+ type = :sub
83
+ foundOne = true
84
+ when 5
85
+ type = :times
86
+ foundOne = true
87
+ when 6
88
+ type = :divide
89
+ foundOne = true
90
+ when 7
91
+ type = :lparen
92
+ foundOne = true
93
+ when 8
94
+ type = :rparen
95
+ foundOne = true
96
+ end
97
+
98
+ if !foundOne then
99
+ lex.concat(c)
100
+ c = @istream.getc()
101
+ end
102
+
103
+ end
104
+
105
+ @istream.ungetc(c)
106
+ @colCount = @colCount - 1
107
+ if type == :number or type == :identifier or type == :keyword then
108
+ t = LexicalToken.new(type,lex,line,column)
109
+ else
110
+ t = Token.new(type,line,column)
111
+ end
112
+
113
+ @lastToken = t
114
+ return t
115
+ end
116
+
117
+ private
118
+ def isLetter(c)
119
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
120
+ end
121
+
122
+ def isDigit(c)
123
+ return (?0 <= c and c <= ?9)
124
+ end
125
+
126
+ def isWhiteSpace(c)
127
+ return (c == ?\ or c == ?\n or c == ?\t)
128
+ end
129
+ end
@@ -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_rocampo3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An calculator implementation on ruby
14
+ email: fcardona@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: []