All Downloads are FREE. Search and download functionalities are using the official Maven repository.

axle.ast.LL.scala Maven / Gradle / Ivy

The newest version!

package axle.ast

import spire.algebra.Eq
import spire.implicits.IntAlgebra
import spire.implicits.eqOps

class Symbol(val label: String) {
  //override def toString() = "'" + label + "'"
  override def toString: String = label
}
object Symbol {
  implicit val symbolEq = new Eq[Symbol] {
    def eqv(x: Symbol, y: Symbol): Boolean = x equals y
  }
}

case class Terminal(_label: String) extends Symbol(_label)

case class NonTerminal(_label: String) extends Symbol(_label)

object NonTerminal {
  implicit val eqNT = new Eq[NonTerminal] {
    def eqv(x: NonTerminal, y: NonTerminal): Boolean = x equals y
  }
}

object ⊥ extends Terminal("⊥") // also known as '$'
object ε extends Symbol("ε") // TODO terminal or non-terminal?

case class LLRule(id: Int, from: NonTerminal, rhs: List[Symbol]) {
  override def toString: String = from.toString + " -> " + rhs.mkString("", " ", "")
}

sealed trait LLParserAction
case class Shift() extends LLParserAction
case class Reduce(rule: LLRule) extends LLParserAction
case class ParseError(msg: String) extends LLParserAction

case class LLParserState(
  grammar: LLLanguage,
  input: String,
  stack: List[Symbol],
  // derivation: List[LLParserAction],
  i: Int) {

  lazy val inputBufferWithMarker = input.substring(0, i) + "|" + input.substring(i, input.length)

  override def toString: String =
    inputBufferWithMarker + "\n" +
      stack.mkString("", " ", "")

  def inputSymbol: Terminal = grammar.terminalsByName(input(i).toString)

  def apply(action: LLParserAction): LLParserState = action match {
    case Shift() => {
      assert(stack.head === inputSymbol)
      LLParserState(grammar, input, stack.tail, i + 1)
    }
    case Reduce(rule) => {
      assert(stack.head === rule.from)
      LLParserState(grammar, input, rule.rhs ++ stack.tail, i)
    }
    case ParseError(msg) => { sys.error(this.toString + "\nparse error: " + msg) }
  }

  def nextAction(): LLParserAction = stack.head match {

    case sts if sts === inputSymbol => Shift()

    case foo @ NonTerminal(_) =>
      if (grammar.parseTable.contains((foo, inputSymbol))) {
        Reduce(grammar.parseTable((foo, inputSymbol)))
      } else {
        ParseError("no rule")
      }

    case _ => ParseError("stack = " + stack + ", inputSymbol = " + inputSymbol + ". A non-matching non-terminal")

  }

  def finished: Boolean = input.length === i && stack.head === ⊥

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy