calc_dmuneto1 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: dca6cc20549e17e003bc0a90e8d121754b606a95
4
+ data.tar.gz: 88d58962434490166885bb409298b42226118327
5
+ SHA512:
6
+ metadata.gz: cb6a19a798f66be09441b95173c21cd3a996667bb8e1b80ca8250ae83a990f9599b3db2aa23121ccf180772195f55e0264d09b60f6e8a7661f36091c75892a59
7
+ data.tar.gz: 17120bb3833782c8c8f820aff1341533ada985880cb82c65d9164f61b46f9c11e518eea5d5204f07e5649de050893346b0c21789ae95f6023759b91f72c13b28
@@ -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,112 @@
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 DivideNode < BinaryNode
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 TimesNode < BinaryNode
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 PowNode < BinaryNode
61
+ def initialize(left, right)
62
+ super(left,right)
63
+ end
64
+
65
+ def evaluate()
66
+ return @left.evaluate()**@right.evaluate()
67
+ end
68
+ end
69
+
70
+ class ModuleNode < BinaryNode
71
+ def initialize(left, right)
72
+ super(left,right)
73
+ end
74
+
75
+ def evaluate()
76
+ return @left.evaluate()%@right.evaluate()
77
+ end
78
+ end
79
+
80
+
81
+ class StoreNode < UnaryNode
82
+ def initilize (subTree)
83
+ super (subTree)
84
+ end
85
+ def evaluate ()
86
+ #Se obvian los parentesis y el return por ruby hay dos caminos tambien puede hacerse por '@'
87
+
88
+ $calc.memory = subTree.evaluate()
89
+ end
90
+ end
91
+
92
+
93
+ class RecallNode
94
+ def evaluate
95
+ $calc.memory
96
+ end
97
+ end
98
+
99
+
100
+
101
+
102
+
103
+
104
+ class NumNode
105
+ def initialize(num)
106
+ @num = num
107
+ end
108
+
109
+ def evaluate()
110
+ return @num
111
+ end
112
+ 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,150 @@
1
+ require 'ast'
2
+ require 'scanner'
3
+ require 'token'
4
+ require 'calcex'
5
+
6
+
7
+ class Parser
8
+ def initialize(istream)
9
+ @scan = Scanner.new(istream)
10
+ end
11
+
12
+ def parse()
13
+ return Prog()
14
+ end
15
+
16
+ private
17
+ def Prog()
18
+ result = Expr()
19
+ t = @scan.getToken
20
+
21
+ if t.type != :eof then
22
+ print "Expected EOF. Found ", t.type, ".\n"
23
+ raise ParseError.new
24
+ end
25
+
26
+ return result
27
+ end
28
+
29
+
30
+
31
+
32
+ def Expr()
33
+ RestExpr(Term())
34
+ end
35
+
36
+ def RestExpr(e)
37
+ t = @scan.getToken
38
+
39
+ if t.type == :add then
40
+ return RestExpr(AddNode.new(e,Term()))
41
+ end
42
+
43
+ if t.type == :sub then
44
+ return RestExpr(SubNode.new(e,Term()))
45
+ end
46
+
47
+ @scan.putBackToken()
48
+
49
+ return e
50
+ end
51
+
52
+ def Term()
53
+
54
+ RestTerm(Storable())
55
+ end
56
+
57
+
58
+ def RestTerm(e)
59
+
60
+ t = @scan.getToken
61
+
62
+
63
+ # if t.type == :times then
64
+ # return RestTerm(TimesNode.new(e,Storable()))
65
+ # end
66
+
67
+ if t.type == :divide then
68
+ return RestTerm(DivideNode.new(e,Storable()))
69
+ end
70
+
71
+ if t.type == :module then
72
+ return RestTerm(ModuleNode.new(e, Storable()))
73
+ end
74
+
75
+
76
+ if t.type == :times then
77
+ t=@scan.getToken
78
+ if t.type == :times then
79
+
80
+ return RestTerm(PowNode.new(e,Storable()))
81
+ end
82
+ @scan.putBackToken()
83
+
84
+ return RestTerm(TimesNode.new(e,Storable()))
85
+ end
86
+
87
+ @scan.putBackToken()
88
+
89
+ return e
90
+
91
+ end
92
+
93
+
94
+
95
+ def Storable()
96
+
97
+ result = Factor()
98
+ t = @scan.getToken
99
+
100
+ if t.type == :keyword then
101
+ if t.lex == 'S' then
102
+ return StoreNode.new(result)
103
+ end
104
+ puts "Excepted S found: #{t.lex} at line #{t.line} col: #{t.col}"
105
+ raise ParseError.new
106
+ end
107
+
108
+ @scan.putBackToken()
109
+
110
+ return result
111
+
112
+ end
113
+
114
+ def Factor()
115
+
116
+ t=@scan.getToken
117
+
118
+ if t.type== :number then
119
+ return NumNode.new t.lex.to_i
120
+ end
121
+
122
+ if t.type == :keyword then
123
+ if t.lex =='R' then
124
+ return RecallNode.new
125
+ end
126
+
127
+ puts "Parser error: expected " +tlex
128
+ puts "at line" + t.line.to_s + " col:" + t.col.to_s
129
+ raise ParseError.new
130
+ end
131
+
132
+ if t.type == :lparen then
133
+ result = Expr()
134
+ t=@scan.getToken
135
+
136
+ if t.type == :rparen then
137
+ return result
138
+ end
139
+
140
+ puts "Syntax error expected ')': #{t.lex}"
141
+ puts "at line: #{t.line}"
142
+ raise ParseError.new
143
+ end
144
+
145
+ puts "parser error : expected number r (: #{t.type}"
146
+ puts "at line: #{t.line} at col: #{t.col}"
147
+ raise ParseError.new
148
+
149
+ end
150
+ end
@@ -0,0 +1,132 @@
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== ?% then state = 9
49
+
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
+ when 9
97
+ type= :module
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,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_dmuneto1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc - Dillan Muñeton Avendaño
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: dmuneto1@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: []