Created
April 19, 2016 13:15
-
-
Save zoren/a44f6a6c15962e6975744d2e6b155658 to your computer and use it in GitHub Desktop.
A implementation of the Operator precedence parser from Wikipedia in Swift 2
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
// Created by Søren Sjørup on 16/04/16. | |
// Copyright © 2016 Søren Sjørup. All rights reserved. | |
import Foundation | |
indirect enum Exp{ | |
case C(Int) | |
case Bin(Exp, String, Exp) | |
} | |
indirect enum S{ | |
case Primary(Exp) | |
case Operator(String) | |
} | |
enum Errors :ErrorType { | |
case ExpectedPrimExpAtIndex(Int) | |
case ExpectedOperatorAtIndex(Int) | |
case ExpectedExpFoundEOF | |
} | |
func parseExp(prec:[String:Int], _ s:[S]) throws -> Exp { | |
var index = 0 | |
func parsePrim() throws -> Exp { | |
if index >= s.count{ | |
throw Errors.ExpectedExpFoundEOF | |
} | |
switch s[index] { | |
case .Primary(let e): | |
index += 1 | |
return e | |
case .Operator(_): | |
throw Errors.ExpectedPrimExpAtIndex(index) | |
} | |
} | |
func peekNextOperator() throws -> String { | |
let i = index | |
if i >= s.count{ | |
return "" | |
} | |
switch s[i] { | |
case .Primary(_): | |
throw Errors.ExpectedOperatorAtIndex(i) | |
case .Operator(let opString): | |
return opString | |
} | |
} | |
func parseExp1(inout lhs:Exp, minPrec:Int) throws -> Exp{ | |
var lookahead = try peekNextOperator() | |
while prec[lookahead] >= minPrec { | |
let op = lookahead | |
index += 1 | |
var rhs = try parsePrim() | |
lookahead = try peekNextOperator() | |
while prec[lookahead] > prec[op] { | |
rhs = try parseExp1(&rhs, minPrec: prec[lookahead]!) | |
lookahead = try peekNextOperator() | |
} | |
lhs = .Bin(lhs, op, rhs) | |
} | |
return lhs | |
} | |
var pp = try parsePrim() | |
return try parseExp1(&pp, minPrec: 0) | |
} | |
// testing | |
let prec : [String:Int] = ["+":140, "%":150, "*":150] | |
let stream : [S] = | |
[.Primary(.C(2)), .Operator("+"), .Primary(.C(3)), .Operator("%"), .Primary(.C(4)), .Operator("*"), .Primary(.C(5))] | |
let v = try parseExp(prec, stream) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment