rocampo3-rubycalc 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: bc5afde44ea9dcc37090beb4057586401c2aadea
4
+ data.tar.gz: 699f927e0670bbeb693a11e35d5c7b85fa3fda2a
5
+ SHA512:
6
+ metadata.gz: 44f6fd8468c7f21c5494395389a625c49a30f48f01905bb191b33074b12dc3a3511d6caa3ce5dcda20e600120e8ca23e66960f4de672c97f640f4e3ce9178a01
7
+ data.tar.gz: 555549a36d543e0b6e4a1d2d833d2439a9dddc3f97eac587f5032b69f0b5b0b032bd336f680268d51ab67f15b27a6daed0002676c319e9dfd0f15813706baec5
@@ -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,99 @@
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
+ # Operaciones Suma, Resta, Multiplicacion, Division y Modulo
21
+
22
+ class AddNode < BinaryNode
23
+ def initialize(left, right)
24
+ super(left,right) # Llama o recibe los atributos del padre
25
+ end
26
+
27
+ def evaluate()
28
+ return @left.evaluate() + @right.evaluate() #No es necesario el "Return"
29
+ end
30
+ end
31
+
32
+ class SubNode < BinaryNode
33
+ def initialize(left, right)
34
+ super(left,right)
35
+ end
36
+
37
+ def evaluate()
38
+ return @left.evaluate() - @right.evaluate()
39
+ end
40
+ end
41
+
42
+ class TimesNode < BinaryNode
43
+ def initialize(left, right)
44
+ super(left,right)
45
+ end
46
+
47
+ def evaluate()
48
+ return @left.evaluate() * @right.evaluate()
49
+ end
50
+ end
51
+
52
+ class DivideNode < BinaryNode
53
+ def initialize(left, right)
54
+ super(left,right)
55
+ end
56
+
57
+ def evaluate()
58
+ return @left.evaluate() / @right.evaluate()
59
+ end
60
+ end
61
+
62
+ class ModNode < BinaryNode
63
+ def initialize(left, right)
64
+ super(left,right)
65
+ end
66
+
67
+ def evaluate()
68
+ return @left.evaluate() % @right.evaluate()
69
+ end
70
+ end
71
+
72
+ class NumNode
73
+ def initialize(num)
74
+ @num = num
75
+ end
76
+
77
+ def evaluate()
78
+ return @num
79
+ end
80
+ end
81
+
82
+ class StoreNode < UnaryNode
83
+
84
+ def initialize(sub)
85
+ super (sub)
86
+ end
87
+
88
+ def evaluate()
89
+ $calc.memory = @subTree.evaluate
90
+ end
91
+ end
92
+
93
+ class RecallNode
94
+
95
+ def evaluate()
96
+ $calc.memory
97
+ end
98
+
99
+ end
@@ -0,0 +1,3 @@
1
+
2
+ class ParseError < Exception; end
3
+ class UnrecognizedTokenException < Exception; end
@@ -0,0 +1,16 @@
1
+ require 'parser'
2
+ require 'ast'
3
+
4
+ class Calculator
5
+ attr_accessor :memory
6
+
7
+ def initialize()
8
+ @memory = 0
9
+ end
10
+
11
+ def eval(expr)
12
+ parser = Parser.new(StringIO.new(expr))
13
+ ast = parser.parse()
14
+ return ast.evaluate()
15
+ end
16
+ end
@@ -0,0 +1,125 @@
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
+ unless t.type == :eof then
21
+ print "Expected EOF. Found ", t.type, ".\n"
22
+ raise ParseError.new #Raise para excepciones
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
+
50
+ RestTerm(Storable())
51
+ # Write your Term() code here. This code is just temporary
52
+ # so you can try the calculator out before finishing it.
53
+
54
+ # t = @scan.getToken()
55
+
56
+ # if t.type == :number then
57
+ # val = t.lex.to_i
58
+ # return NumNode.new(val)
59
+ # end
60
+
61
+ # puts "Term not implemented\n"
62
+
63
+ # raise ParseError.new
64
+ end
65
+
66
+ def RestTerm(e)
67
+ t = @scan.getToken
68
+
69
+ if t.type == :times then
70
+ return RestTerm(TimesNode.new(e, Storable()))
71
+
72
+ if t.type == :divide then
73
+ return RestTerm(DivideNode.new(e, Storable()))
74
+
75
+ @scan.putBackToken
76
+ e
77
+
78
+ end
79
+ end
80
+ return e
81
+ end
82
+
83
+ def Storable()
84
+
85
+ fact = Factor()
86
+ t = @scan.getToken
87
+
88
+ if t.type == :keyword then
89
+ if t.lex == "S" then
90
+ return StoreNode.new(fact)
91
+ else
92
+ raise ParserError.new
93
+ end
94
+ end
95
+ return fact
96
+ end
97
+
98
+ def Factor()
99
+ t = @scan.getToken
100
+
101
+ if t.type == :number then
102
+ return NumNode.new(t.lex.to_i)
103
+ end
104
+
105
+ if t.type == :keyword then
106
+ if lex == "R" then
107
+ return RecallNode.new
108
+ else
109
+ raise ParserError.new
110
+ end
111
+ end
112
+
113
+ if t.type == :lparen then
114
+ expr = Expr()
115
+ t = @scan.getToken
116
+ if t.type == :rparen then
117
+ return expr
118
+ else
119
+ raise ParserError.new
120
+ end
121
+ end
122
+ raise ParserError.new
123
+ end
124
+ end
125
+
@@ -0,0 +1,146 @@
1
+ require 'stringio'
2
+ require 'calcex'
3
+ require 'set'
4
+
5
+ class Scanner
6
+ def initialize(inStream) #Constructor
7
+ @istream = inStream
8
+ @keywords = Set.new(["S","R"]) #Set
9
+ @lineCount = 1
10
+ @colCount = -1
11
+ @needToken = true
12
+ @lastToken = nil
13
+ end
14
+
15
+ def putBackToken()
16
+ @needToken = false
17
+ end
18
+
19
+ def getToken()
20
+ if !@needToken
21
+ @needToken = true
22
+ return @lastToken #Return rompe la ejecucion de la funcion
23
+ end
24
+
25
+ state = 0
26
+ foundOne = false
27
+ c = @istream.getc()
28
+
29
+ if @istream.eof() then
30
+ @lastToken = Token.new(:eof,@lineCount,@colCount)
31
+ return @lastToken
32
+ end
33
+
34
+ until foundOne do
35
+ @colCount = @colCount + 1
36
+ case state
37
+ when 0
38
+ lex = ""
39
+ column = @colCount
40
+ line = @lineCount
41
+ if isLetter(c) then state=1
42
+ elsif isDigit(c) then state=2
43
+ elsif c == ?+ then state = 3
44
+ elsif c == ?- then state = 4
45
+ elsif c == ?* then state = 5
46
+ elsif c == ?/ then state = 6
47
+ elsif c == ?% then state = 7
48
+ elsif c == ?( then state = 8
49
+ elsif c == ?) then state = 9
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 = :mod
92
+ foundOne = true
93
+ when 8
94
+ type = :lparen
95
+ foundOne = true
96
+ when 9
97
+ type = :rparen
98
+ foundOne = true
99
+ end
100
+
101
+ if !foundOne then
102
+ lex.concat(c)
103
+ c = @istream.getc()
104
+ end
105
+
106
+ end
107
+
108
+ @istream.ungetc(c)
109
+ @colCount = @colCount - 1
110
+ if type == :number or type == :identifier or type == :keyword then
111
+ t = LexicalToken.new(type,lex,line,column)
112
+ else
113
+ t = Token.new(type,line,column)
114
+ end
115
+
116
+ @lastToken = t
117
+ return t
118
+ end
119
+
120
+ private
121
+ def isLetter(c)
122
+ if c.nil?
123
+ false
124
+ else
125
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
126
+ end
127
+ end
128
+
129
+ def isDigit(c)
130
+ if c.nil?
131
+ false
132
+ else
133
+ return (?0 <= c and c <= ?9)
134
+ end
135
+ end
136
+
137
+ def isWhiteSpace(c)
138
+ if c.nil?
139
+ false
140
+ else
141
+ return (c == ?\ or c == ?\n or c == ?\t)
142
+
143
+ end
144
+ end
145
+ end
146
+
@@ -0,0 +1,27 @@
1
+ class Token #Nombres de las clases deben empezar en mayusculas
2
+ attr_reader :type, :line, :col #Nombre de metodos
3
+
4
+ def initialize(type,lineNum,colNum) #constructor(initialize(debe tener parametros diferentes no se les pone el tipo))
5
+ @type = type # @ -> Variables de Instancia , $ -> Variables Globales
6
+ @line = lineNum
7
+ @col = colNum
8
+ end
9
+ end
10
+
11
+ class LexicalToken < Token #Herencia
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
20
+
21
+
22
+ =begin
23
+ attr_reader -> Da el metodo para leer la variable (get)
24
+ attr_writer -> (set)
25
+ attr_accessor -> reader + writer (get y set)
26
+ : -> inmutables
27
+ =end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rocampo3-rubycalc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Ricardo Ocampo Castro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: An calculator of a basic calculator on ruby
14
+ email: rocampo3@eafit.edu.co
15
+ executables:
16
+ - rubycalc
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/rubycalc
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: []