Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Library._
- import Untyped._
- case class NotImplementedException(s: String) extends RuntimeException(s)
- case class ParseOpException(s: String) extends ParseException(s)
- object Parser {
- def constructBinding(bind: SExpr): LetBindExt = bind match {
- case SList(SSym(name) :: value :: Nil) => {
- if (ExprExt.reservedWords.contains(name)) throw new ParseOpException("Id cannot be reserved keyword")
- else LetBindExt(name, parse(value))
- }
- case _ => throw new ParseOpException("Invalid let-bind format")
- }
- def extractParams(params: List[SExpr]): List[String] = params match {
- case Nil => Nil
- case param :: t => {
- val hd = parse(param)
- hd match {
- case IdExt(name) => name :: extractParams(params.tail)
- case _ => throw new ParseOpException("Extract params error")
- }
- }
- }
- def parse(str: String): ExprExt = parse(Reader.read(str))
- def parse(sexpr: SExpr): ExprExt = sexpr match{
- case SNum(x) => NumExt(x)
- case SSym("nil") => NilExt()
- case SSym("true") => TrueExt()
- case SSym("false") => FalseExt()
- case SSym(name) => {
- if (ExprExt.reservedWords.contains(name)) throw new ParseOpException("Id cannot be reserved keyword")
- else IdExt(name)
- }
- case SList(list: List[SExpr]) => list match {
- case (SSym(symbol) :: left :: right :: Nil) if ExprExt.binOps.contains(symbol) => BinOpExt(symbol, parse(left), parse(right))
- case (SSym(symbol) :: e :: Nil) if ExprExt.unOps.contains(symbol) => UnOpExt(symbol, parse(e))
- case SSym("if") :: c :: t :: e :: Nil => IfExt(parse(c), parse(t), parse(e))
- case SSym("let") :: SList(bindings) :: body :: Nil => {
- val letBindings: List[LetBindExt] = bindings.map(bind => constructBinding(bind))
- val letBindingsNames: List[String] = letBindings.map(bind => bind.name)
- if (letBindingsNames.size > 0 && letBindingsNames.toSet.size == letBindingsNames.size)
- LetExt(letBindings, parse(body))
- else throw new ParseOpException("A let expression can only bind a parameter name once")
- }
- case SSym("lambda") :: SList(params) :: body:: Nil => {
- val paramsNames: List[String] = extractParams(params)
- if (paramsNames.toSet.size == paramsNames.size)
- FdExt(paramsNames, parse(body))
- else throw new ParseOpException("A let expression can only bind a parameter name once")
- }
- case h :: t => AppExt(parse(h), t.map(parse)) // "App" case
- case _ => throw new ParseOpException("`e` does not evaluate to a function value")
- }
- case _ => throw new ParseOpException(s"Invalid type of SExpr: $sexpr")
- }
- }
Add Comment
Please, Sign In to add comment