VladNitu

ExtraParserVlad

Apr 12th, 2023
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.71 KB | None | 0 0
  1. import Library._
  2. import Untyped._
  3.  
  4. case class NotImplementedException(s: String) extends RuntimeException(s)
  5. case class ParseOpException(s: String) extends ParseException(s)
  6.  
  7.  
  8. object Parser {
  9.  
  10.  
  11.  
  12.   def constructBinding(bind: SExpr): LetBindExt = bind match {
  13.     case SList(SSym(name) :: value :: Nil) => {
  14.       if (ExprExt.reservedWords.contains(name)) throw new ParseOpException("Id cannot be reserved keyword")
  15.       else LetBindExt(name, parse(value))
  16.     }
  17.     case _ =>  throw new ParseOpException("Invalid let-bind format")
  18.   }
  19.  
  20.   def extractParams(params: List[SExpr]): List[String] = params match {
  21.     case Nil => Nil
  22.     case param :: t => {
  23.       val hd = parse(param)
  24.       hd match {
  25.         case IdExt(name) => name :: extractParams(params.tail)
  26.         case _ => throw new ParseOpException("Extract params error")
  27.       }
  28.     }
  29.   }
  30.  
  31.  
  32.  
  33.  
  34.   def parse(str: String): ExprExt = parse(Reader.read(str))
  35.  
  36.   def parse(sexpr: SExpr): ExprExt = sexpr match{
  37.  
  38.     case SNum(x) => NumExt(x)
  39.     case SSym("nil") => NilExt()
  40.     case SSym("true") => TrueExt()
  41.     case SSym("false") => FalseExt()
  42.     case SSym(name) => {
  43.       if (ExprExt.reservedWords.contains(name)) throw new ParseOpException("Id cannot be reserved keyword")
  44.       else IdExt(name)
  45.     }
  46.  
  47.  
  48.     case SList(list: List[SExpr]) => list match {
  49.  
  50.       case (SSym(symbol) :: left :: right :: Nil) if ExprExt.binOps.contains(symbol)  => BinOpExt(symbol, parse(left), parse(right))
  51.  
  52.       case (SSym(symbol) :: e :: Nil) if ExprExt.unOps.contains(symbol) => UnOpExt(symbol, parse(e))
  53.  
  54.       case SSym("if") :: c :: t :: e :: Nil => IfExt(parse(c), parse(t), parse(e))
  55.  
  56.       case SSym("let") :: SList(bindings) :: body :: Nil => {
  57.  
  58.         val letBindings: List[LetBindExt] = bindings.map(bind => constructBinding(bind))
  59.         val letBindingsNames: List[String] = letBindings.map(bind => bind.name)
  60.  
  61.  
  62.         if (letBindingsNames.size > 0 && letBindingsNames.toSet.size == letBindingsNames.size)
  63.           LetExt(letBindings, parse(body))
  64.         else throw new ParseOpException("A let expression can only bind a parameter name once")
  65.       }
  66.  
  67.       case SSym("lambda") :: SList(params) :: body:: Nil => {
  68.         val paramsNames: List[String] = extractParams(params)
  69.         if (paramsNames.toSet.size == paramsNames.size)
  70.           FdExt(paramsNames, parse(body))
  71.         else throw new ParseOpException("A let expression can only bind a parameter name once")
  72.       }
  73.  
  74.       case h :: t => AppExt(parse(h), t.map(parse)) // "App" case
  75.  
  76.       case _ =>  throw new ParseOpException("`e` does not evaluate to a function value")
  77.  
  78.     }
  79.  
  80.  
  81.  
  82.  
  83.  
  84.     case _ => throw new ParseOpException(s"Invalid type of SExpr: $sexpr")
  85.  
  86.   }
  87. }
  88.  
Add Comment
Please, Sign In to add comment