Created
June 21, 2016 04:58
-
-
Save tautologico/e93ce90c8fe8bf31c9e867d24b1b8fec to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Linguagem de expressoes aritmeticas | |
// Interpretador, compilador para maquina de pilha | |
// | |
//--- expressoes aritmeticas --------------------- | |
enum Exp { | |
case Const(Int) | |
indirect case Soma(Exp, Exp) | |
indirect case Sub(Exp, Exp) | |
indirect case Mult(Exp, Exp) | |
} | |
func showExp(e: Exp) -> String { | |
switch e { | |
case let .Const(i): | |
return String(i) | |
case let .Soma(e1, e2): | |
return "(\(showExp(e1)) + \(showExp(e2)))" | |
case let .Sub(e1, e2): | |
return "(\(showExp(e1)) - \(showExp(e2)))" | |
case let .Mult(e1, e2): | |
return "(\(showExp(e1)) * \(showExp(e2)))" | |
} | |
} | |
func eval(e: Exp) -> Int { | |
switch e { | |
case let .Const(i): | |
return i | |
case let .Soma(e1, e2): | |
return eval(e1) + eval(e2) | |
case let .Sub(e1, e2): | |
return eval(e1) - eval(e2) | |
case let .Mult(e1, e2): | |
return eval(e1) * eval(e2) | |
} | |
} | |
//--- maquina de pilha --------------------------- | |
enum Operacao { | |
case OpSoma | |
case OpSub | |
case OpMult | |
} | |
enum Instrucao { | |
case Empilha(Int) | |
case Oper(Operacao) | |
} | |
struct Pilha { | |
var itens = [Int]() | |
mutating func empilha(i: Int) { | |
self.itens.append(i) | |
} | |
func topo() -> Int? { | |
return self.itens.last | |
} | |
mutating func operandos() -> (Int, Int)? { | |
if self.itens.count < 2 { | |
return nil | |
} else { | |
let r1 = self.itens.removeLast() | |
let r2 = self.itens.removeLast() | |
return (r1, r2) | |
} | |
} | |
} | |
extension Operacao { | |
func oper() -> (Int, Int) -> Int { | |
switch self { | |
case .OpSoma: | |
return (+) | |
case .OpSub: | |
return (-) | |
case .OpMult: | |
return (*) | |
} | |
} | |
} | |
func execInst(i: Instrucao, inout pilha: Pilha) { | |
switch i { | |
case let .Empilha(i): | |
pilha.empilha(i) | |
case let .Oper(op): | |
if let (v1, v2) = pilha.operandos() { | |
pilha.empilha(op.oper()(v1, v2)) | |
} | |
} | |
} | |
func execProg(prog: [Instrucao]) -> Pilha { | |
var p = Pilha() | |
for i in prog { | |
execInst(i, pilha: &p) | |
} | |
return p | |
} | |
func executa(prog: [Instrucao]) -> Int? { | |
let pilha = execProg(prog) | |
return pilha.topo() | |
} | |
let p1 = [Instrucao.Empilha(5), | |
Instrucao.Empilha(7), | |
Instrucao.Oper(Operacao.OpSoma), | |
Instrucao.Empilha(10), | |
Instrucao.Oper(Operacao.OpMult)] | |
if let res = executa(p1) { | |
print("resultado do programa: \(res)") | |
} else { | |
print("programa sem resultado") | |
} | |
func compila(e: Exp) -> [Instrucao] { | |
switch e { | |
case let .Const(i): | |
return [Instrucao.Empilha(i)] | |
case let .Soma(e1, e2): | |
var prog = compila(e2) | |
prog.appendContentsOf(compila(e1)) | |
prog.append(Instrucao.Oper(Operacao.OpSoma)) | |
return prog | |
case let .Sub(e1, e2): | |
var prog = compila(e2) | |
prog.appendContentsOf(compila(e1)) | |
prog.append(Instrucao.Oper(Operacao.OpSub)) | |
return prog | |
case let .Mult(e1, e2): | |
var prog = compila(e2) | |
prog.appendContentsOf(compila(e1)) | |
prog.append(Instrucao.Oper(Operacao.OpMult)) | |
return prog | |
} | |
} | |
let e1 = Exp.Mult(Exp.Const(3), | |
Exp.Soma(Exp.Const(4), Exp.Const(2))) | |
print(compila(e1)) | |
print(eval(e1)) | |
print(executa(compila(e1))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment