calc_wramire5 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d92cc794d0616bb31649b199ae0c9bfa1a4f4af
4
+ data.tar.gz: f8178f6b4cac1d55f360fbc6769a7b05dc9c0d2a
5
+ SHA512:
6
+ metadata.gz: 47e04acea91791d44af51d12163797665f38474691c1ad2d0c6e78f5c55715b7d23a932d697371bd84ddb0b0dc6f841568f2929d2b076900508f3af9c6a4632d
7
+ data.tar.gz: a2e66fa31c00c10fb0838b3f3c7e2f1c10b55a14a3434ceffa185539cc7d22f6e9b0c864c144cf9cd14f34a6644db7d26af4d3456a0905196dabc77aaf432854
data/bin/calc ADDED
@@ -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
data/lib/ast.rb ADDED
@@ -0,0 +1,94 @@
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 TimesNode < 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 DivideNode < 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 ModNode < 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 StoreNode< UnaryNode
71
+ def initialize(subTree)
72
+ super(subTree)
73
+ end
74
+
75
+ def evaluate()
76
+ $calc.memory=@subTree.evaluate()
77
+ end
78
+ end
79
+
80
+ class RecallNode
81
+ def evaluate
82
+ $calc.memory
83
+ end
84
+ end
85
+
86
+ class NumNode
87
+ def initialize(num)
88
+ @num = num
89
+ end
90
+
91
+ def evaluate()
92
+ return @num
93
+ end
94
+ end
data/lib/calcex.rb ADDED
@@ -0,0 +1,3 @@
1
+
2
+ class ParseError < Exception; end
3
+ class UnrecognizedTokenException < Exception; end
data/lib/calculator.rb ADDED
@@ -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
data/lib/parser.rb ADDED
@@ -0,0 +1,120 @@
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
+ e
46
+ end
47
+
48
+ def Term
49
+ RestTerm(Storable())
50
+ end
51
+
52
+ def RestTerm(e)
53
+ t = @scan.getToken
54
+
55
+ if t.type == :times then
56
+ return RestTerm(TimesNode.new(e, Storable()))
57
+ end
58
+
59
+ if t.type == :divide then
60
+ return Resterm(DivideNode.new(e, Storable()))
61
+ end
62
+
63
+ if t.type == :mod then
64
+ return Resterm(ModNode.new(e, Storable()))
65
+ end
66
+
67
+ @scan.putBackToken
68
+
69
+ e
70
+
71
+ end
72
+
73
+ def Storable
74
+
75
+ result=Factor()
76
+
77
+ t = @scan.getToken
78
+
79
+ if t.type == :keyword then
80
+ if t.lex == "S" then
81
+ return StoreNode.new(result)
82
+ end
83
+
84
+ puts "Expected S found #{t.lex} at line: #{t.line} col: #{t.col}"
85
+ raise ParserError.new # "Parse Error"
86
+ end
87
+ @scan.putBackToken
88
+
89
+ result
90
+
91
+ end
92
+
93
+ def Factor
94
+ t = @scan.getToken
95
+ if t.type == :number then
96
+ return NumNode.new(t.lex.to_i)
97
+ end
98
+ if t.type == :keyword then
99
+ if t.lex == "R" then
100
+ return RecallNode.new
101
+ end
102
+ else
103
+ puts "Expected R found: #{t.lex} at line: #{t.line} col: #{t.col}"
104
+ raise ParserError.new
105
+ end
106
+ if t.type == :lparen then
107
+ result = Expr()
108
+ t = @scan.getToken
109
+ if t.type == :rparen then
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 "Factor not implemented"
118
+ raise ParserError.new # "Parse Error"
119
+ end
120
+ end
data/lib/scanner.rb ADDED
@@ -0,0 +1,131 @@
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
+ elsif c == ?\n then
50
+ @colCount = -1
51
+ @lineCount = @lineCount+1
52
+ elsif isWhiteSpace(c) then state = state #ignore whitespace
53
+ elsif @istream.eof() then
54
+ @foundOne = true
55
+ type = :eof
56
+ else
57
+ puts "Unrecognized Token found at line ",line," and column ",column,"\n"
58
+ raise UnrecognizedTokenException # "Unrecognized Token"
59
+ end
60
+ when 1
61
+ if isLetter(c) or isDigit(c) then state = 1
62
+ else
63
+ if @keywords.include?(lex) then
64
+ foundOne = true
65
+ type = :keyword
66
+ else
67
+ foundOne = true
68
+ type = :identifier
69
+ end
70
+ end
71
+ when 2
72
+ if isDigit(c) then state = 2
73
+ else
74
+ type = :number
75
+ foundOne = true
76
+ end
77
+ when 3
78
+ type = :add
79
+ foundOne = true
80
+ when 4
81
+ type = :sub
82
+ foundOne = true
83
+ when 5
84
+ type = :times
85
+ foundOne = true
86
+ when 6
87
+ type = :divide
88
+ foundOne = true
89
+ when 7
90
+ type = :lparen
91
+ foundOne = true
92
+ when 8
93
+ type = :rparen
94
+ foundOne = true
95
+ when 9
96
+ type = :mod
97
+ foundOne = true
98
+ end
99
+
100
+ if !foundOne then
101
+ lex.concat(c)
102
+ c = @istream.getc()
103
+ end
104
+
105
+ end
106
+
107
+ @istream.ungetc(c)
108
+ @colCount = @colCount - 1
109
+ if type == :number or type == :identifier or type == :keyword then
110
+ t = LexicalToken.new(type,lex,line,column)
111
+ else
112
+ t = Token.new(type,line,column)
113
+ end
114
+
115
+ @lastToken = t
116
+ return t
117
+ end
118
+
119
+ private
120
+ def isLetter(c)
121
+ return ((?a <= c and c <= ?z) or (?A <= c and c <= ?Z))
122
+ end
123
+
124
+ def isDigit(c)
125
+ return (?0 <= c and c <= ?9)
126
+ end
127
+
128
+ def isWhiteSpace(c)
129
+ return (c == ?\ or c == ?\n or c == ?\t)
130
+ end
131
+ end
data/lib/token.rb ADDED
@@ -0,0 +1,19 @@
1
+ class Token
2
+ attr_reader :type, :line, :col # : Es el prefijo para los symbol representan nombres y strings es global para todo el prog
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 #el signo < o menor es la 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
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: calc_wramire5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kent D. Lee - Juan Francisco Cardona Mc - William Ramirez
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: wramire5@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: []