calc_mzabala1 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 06afbd260bd0b77c09ff150eb8157e11c0a851c7
4
+ data.tar.gz: cd596de9891fc30d9fc07dcdf9883f53164ec75d
5
+ SHA512:
6
+ metadata.gz: afdfe80ab78485cb0e66ce39e210694fbe2e8dec0d3f4e8d9dab1037f6a8f44939578ef46ea2dee93c2de179c12ffda83d8d1ef9ab12599d680383e8b7ab6041
7
+ data.tar.gz: 01fca5400792a95c2ec3795d892df2c64f99660e6c8bce1c7e0889593b6f2c7e297a78f5b8b3105932b5f562a518d3e99025a18af7c3cb7f523e0cee9f405a88
@@ -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,97 @@
1
+ require 'set'
2
+
3
+ #El @ es una variable instancia, un atributo de la clase
4
+ #Elreturn ni los () son necesarios en ruby
5
+
6
+ class BinaryNode
7
+ attr_reader :left, :right
8
+
9
+ def initialize(left,right)
10
+ @left = left
11
+ @right = right
12
+ end
13
+ end
14
+
15
+ class UnaryNode
16
+ attr_reader :subTree
17
+
18
+ def initialize(subTree)
19
+ @subTree = subTree
20
+ end
21
+ end
22
+
23
+ class AddNode < BinaryNode
24
+ def initialize(left, right)
25
+ super(left,right)
26
+ end
27
+
28
+ def evaluate()
29
+ return @left.evaluate() + @right.evaluate()
30
+ end
31
+ end
32
+
33
+ class SubNode < BinaryNode
34
+ def initialize(left, right)
35
+ super(left,right)
36
+ end
37
+
38
+ def evaluate()
39
+ return @left.evaluate() - @right.evaluate()
40
+ end
41
+ end
42
+
43
+ class TimesNode < BinaryNode
44
+ def initialize(left, right)
45
+ super(left,right)
46
+ end
47
+
48
+ def evaluate
49
+ return @left.evaluate() * @right.evaluate()
50
+ end
51
+ end
52
+
53
+ class DivideNode < BinaryNode
54
+ def initialize(left, right)
55
+ super(left,right)
56
+ end
57
+
58
+ def evaluate()
59
+ return @left.evaluate() / @right.evaluate()
60
+ end
61
+ end
62
+
63
+ # class ModuloNode < BinaryNode
64
+ # def initialize(left, right)
65
+ # super(left,right)
66
+ # end
67
+
68
+ # def evaluate
69
+ # return @left.evaluate() % @right.evaluate()
70
+ # end
71
+ # end
72
+
73
+ class StoreNode < UnaryNode
74
+ def initialize(subTree)
75
+ super(subTree)
76
+ end
77
+
78
+ def evaluate()
79
+ $calc.memory = subTree.evaluate()
80
+ end
81
+ end
82
+
83
+ class RecallNode
84
+ def evaluate
85
+ $calc.memory
86
+ end
87
+ end
88
+
89
+ class NumNode
90
+ def initialize(num)
91
+ @num = num
92
+ end
93
+
94
+ def evaluate()
95
+ return @num
96
+ end
97
+ end
@@ -0,0 +1,2 @@
1
+ class ParseError < Exception; end
2
+ 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,121 @@
1
+ require 'ast'
2
+ require 'scanner'
3
+ require 'token'
4
+ require 'calcex'
5
+
6
+ # cuando comienza por minuscula lo toma como metodo, si comienza por mayus lo toma como una clase
7
+
8
+ class Parser
9
+ def initialize(istream)
10
+ @scan = Scanner.new(istream)
11
+ end
12
+
13
+ def parse
14
+ return Prog()
15
+ end
16
+
17
+ private
18
+ def Prog
19
+ result = Expr()
20
+ t = @scan.getToken
21
+
22
+ if t.type != :eof then
23
+ print "Expected EOF. Found ", t.type, ".\n"
24
+ raise ParseError.new
25
+ end
26
+
27
+ return result
28
+ end
29
+
30
+ def Expr
31
+ RestExpr(Term())
32
+ end
33
+
34
+ def RestExpr(e)
35
+ t = @scan.getToken
36
+
37
+ if t.type == :add then
38
+ return RestExpr(AddNode.new(e,Term()))
39
+ end
40
+
41
+ if t.type == :sub then
42
+ return RestExpr(SubNode.new(e,Term()))
43
+ end
44
+
45
+ @scan.putBackToken
46
+
47
+ return e
48
+ end
49
+
50
+ def Term
51
+ RestTerm(Storable())
52
+ end
53
+
54
+ def RestTerm(e)
55
+ t = @scan.getToken
56
+
57
+ if t.type == :times
58
+ return RestExpr(TimesNode.new(e,Storable()))
59
+ end
60
+
61
+ if t.type == :divide
62
+ return RestExpr(DivideNode.new(e,Storable()))
63
+ end
64
+
65
+ # if t.type == :modulo
66
+ # return RestTerm(ModuloNode.new(e,Storable()))
67
+
68
+ @scan.putBackToken
69
+
70
+ e
71
+
72
+ end
73
+
74
+ def Storable()
75
+ result = Factor()
76
+
77
+ t = @scan.getToken()
78
+ if t.type == :keyword
79
+ if t.lex == "S"
80
+ return StoreNode.new(result)
81
+ end
82
+ puts "Expected S found: #{t.lex} at line: #{t.line} col: #{t.col}"
83
+ raise ParseError.new
84
+ end
85
+ @scan.putBackToken
86
+ return result
87
+
88
+ end
89
+
90
+ def Factor()
91
+
92
+ t = @scan.getToken
93
+
94
+ if t.type == :number
95
+ return NumNode.new t.lex.to_i
96
+ end
97
+
98
+ if t.type == :keyword
99
+ if t.lex == "R"
100
+ return RecallNode.new(result)
101
+ end
102
+ puts "Expected R found: #{t.lex} at line: #{t.line} col: #{t.col}"
103
+ raise ParseError.new
104
+ end
105
+
106
+ if t.type == :lparen
107
+ result = Expr()
108
+ t= @scan.getToken
109
+ if t.type == :rparen
110
+ return result
111
+ end
112
+ puts "Parser Error: expected ) found: #{t.lex}"
113
+ puts "at line: #{t.line} col: #{t.col}"
114
+ raise ParseError.new
115
+ end
116
+
117
+ puts "Parser Error: expected number, R, ( found: #{t.type}"
118
+ puts " at line: #{t.line} col: #{t.col}"
119
+ raise ParseError.new
120
+ end
121
+ end
@@ -0,0 +1,132 @@
1
+ require 'stringio'
2
+ require 'calcex'
3
+
4
+ # el ? retorna verdadero o falso
5
+
6
+ class Scanner
7
+ def initialize(inStream)
8
+ @istream = inStream
9
+ @keywords = Set.new(%w{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 += 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 = :modulo
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
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
123
+ end
124
+
125
+ def isDigit(c)
126
+ return (?0 <= c and c <= ?9)
127
+ end
128
+
129
+ def isWhiteSpace(c)
130
+ return (c == ?\ or c == ?\n or c == ?\t)
131
+ end
132
+ end
@@ -0,0 +1,21 @@
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
+ #Herencia en ruby por medio del hijo < padre
12
+
13
+ class LexicalToken < Token
14
+ attr_reader :lex
15
+
16
+ def initialize(type,lex,lineNum,colNum)
17
+ super(type,lineNum,colNum)
18
+
19
+ @lex = lex
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calc_mzabala1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc - Mateo Zabala
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: mzabala1@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: []