parsers.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,932 行 · 第 1/5 页

SCALA
1,932
字号
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author  Martin Odersky */// $Id: Parsers.scala 14561 2008-04-09 09:57:10Z odersky $//todo: allow infix type patternspackage scala.tools.nsc.ast.parserimport scala.tools.nsc.util.{ListBuffer, Position, OffsetPosition, NoPosition, BatchSourceFile}import symtab.Flagsimport Tokens._//todo verify when stableId's should be just plain qualified type ids/** <p>Performs the following context-free rewritings:</p> *  <ol> *    <li> *      Places all pattern variables in Bind nodes. In a pattern, for *      identifiers <code>x</code>:<pre> *                 x  => x @ _ *               x:T  => x @ (_ : T)</pre> *    </li> *    <li>Removes pattern definitions (PatDef's) as follows: *      If pattern is a simple (typed) identifier:<pre> *        <b>val</b> x = e     ==>  <b>val</b> x = e *        <b>val</b> x: T = e  ==>  <b>val</b> x: T = e</pre> *     *      if there are no variables in pattern<pre> *        <b>val</b> p = e  ==>  e match (case p => ())</pre> *     *      if there is exactly one variable in pattern<pre> *        <b>val</b> x_1 = e <b>match</b> (case p => (x_1))</pre> *     *      if there is more than one variable in pattern<pre> *        <b>val</b> p = e  ==>  <b>private synthetic val</b> t$ = e <b>match</b> (case p => (x_1, ..., x_N)) *                        <b>val</b> x_1 = t$._1 *                        ... *                        <b>val</b> x_N = t$._N</pre> *    </li> *    <li> *       Removes function types as follows:<pre> *        (argtpes) => restpe   ==>   scala.Function_n[argtpes, restpe]</pre> *    </li> *    <li> *      Wraps naked case definitions in a match as follows:<pre> *        { cases }   ==>   (x => x.match {cases})<span style="font-family:normal;">, except when already argument to match</span></pre> *    </li> *  </ol> */trait Parsers extends NewScanners with MarkupParsers {  val global : Global   import global._  private val glob: global.type = global  import global.posAssigner.atPos  case class OpInfo(operand: Tree, operator: Name, pos: Int)  /** ...   *   *  @author Sean McDirmid   */  class UnitParser(val unit: global.CompilationUnit) extends Parser {    val in = new UnitScanner(unit)    def freshName(pos : Position, prefix : String) = unit.fresh.newName(pos, prefix)    implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source,offset)    def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg)    def incompleteInputError(msg: String) : Unit =      unit.incompleteInputError(unit.source.asInstanceOf[BatchSourceFile].content.length - 1, msg)    def deprecationWarning(pos : Int, msg : String) : Unit = unit.deprecationWarning(pos, msg)    def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg)        /** the markup parser */    def xmlp = {      if (xmlp0 == null)         xmlp0 = new MarkupParser(this, true)      xmlp0    }    object symbXMLBuilder extends SymbolicXMLBuilder(treeBuilder, this, true) { // DEBUG choices      val global: Parsers.this.global.type = Parsers.this.global      def freshName(prefix: String): Name = UnitParser.this.freshName(NoPosition, prefix)    }    private var xmlp0: MarkupParser = null    def xmlLiteral : Tree = xmlp.xLiteral    def xmlLiteralPattern : Tree = xmlp.xLiteralPattern  }  // parser constants, here so they don't pollute parser debug listing  private object ParserConfiguration {    final val Local = 0    final val InBlock = 1    final val InTemplate = 2    final val MINUS: Name = "-"    final val PLUS : Name = "+"    final val BANG : Name = "!"    final val TILDE: Name = "~"    final val AMP  : Name = "&"    final val SLASH: Name = "/"    final val STAR : Name = "*"    final val BAR  : Name = "|"    final val OPT  : Name = "?"    final val LT   : Name = "<"  }  abstract class Parser {    ParserConfiguration.hashCode    import ParserConfiguration._    val in: ParserScanner    //val unit : CompilationUnit    //import in.ScanPosition    protected def freshName(pos : Position, prefix: String): Name    protected def posToReport: Int = in.currentPos        protected implicit def i2p(offset : Int) : Position    private implicit def p2i(pos : Position) = pos.offset.get        private def inToken = in.token    private def inSkipToken = in.skipToken    private def inNextToken = in.nextToken    private def inCurrentPos = in.currentPos    private def inNextTokenCode : Int = in.nextTokenCode    private def inName = in.name    private def charVal = in.charVal      private def intVal(isNegated : Boolean) = in.intVal(isNegated).asInstanceOf[Int]    private def longVal(isNegated : Boolean) = in.intVal(isNegated)    private def floatVal(isNegated : Boolean) = in.floatVal(isNegated).asInstanceOf[Float]    private def doubleVal(isNegated : Boolean) = in.floatVal(isNegated)    private def stringVal = in.stringVal    /** whether a non-continuable syntax error has been seen */    //private var syntaxErrorSeen = false     private var lastErrorPos : Int = -1    object treeBuilder extends TreeBuilder {      val global: Parsers.this.global.type = Parsers.this.global      def freshName(pos : Position, prefix: String): Name = Parser.this.freshName(pos, prefix)    }    import treeBuilder._    /** The implicit view parameters of the surrounding class */    var implicitClassViews: List[Tree] = Nil    /** this is the general parse method     */    def parse(): Tree = {      val t = compilationUnit()      accept(EOF)      t    }/////////// PLACEHOLDERS ///////////////////////////////////////////////////////        /** The implicit parameters introduced by `_' in the current expression.     *  Parameters appear in reverse order      */    var placeholderParams: List[ValDef] = Nil    /** The placeholderTypes introduced by `_' in the current type.     *  Parameters appear in reverse order      */    var placeholderTypes: List[TypeDef] = Nil    def checkNoEscapingPlaceholders[T](op: => T): T = {      val savedPlaceholderParams = placeholderParams      val savedPlaceholderTypes = placeholderTypes      placeholderParams = List()      placeholderTypes = List()      val res = op            placeholderParams match {        case vd :: _ =>           syntaxError(vd.pos, "unbound placeholder parameter", false)          placeholderParams = List()        case _ =>      }      placeholderTypes match {        case td :: _ =>           syntaxError(td.pos, "unbound wildcard type", false)          placeholderTypes = List()        case _ =>      }      placeholderParams = savedPlaceholderParams      placeholderTypes = savedPlaceholderTypes      res    }    def placeholderTypeBoundary(op: => Tree): Tree = {      val savedPlaceholderTypes = placeholderTypes      placeholderTypes = List()      var t = op      if (!placeholderTypes.isEmpty && t.isInstanceOf[AppliedTypeTree]) {        t = ExistentialTypeTree(t, placeholderTypes.reverse)        placeholderTypes = List()      }       placeholderTypes = placeholderTypes ::: savedPlaceholderTypes      t    }/////// ERROR HANDLING //////////////////////////////////////////////////////    protected def skip() {      var nparens = 0      var nbraces = 0      while (true) {        inToken match {          case EOF =>            return          case SEMI =>            if (nparens == 0 && nbraces == 0) return          case NEWLINE =>            if (nparens == 0 && nbraces == 0) return          case NEWLINES =>            if (nparens == 0 && nbraces == 0) return          case RPAREN =>            nparens -= 1          case RBRACE =>            if (nbraces == 0) return            nbraces -= 1          case LPAREN =>            nparens += 1          case LBRACE =>            nbraces += 1          case _ =>        }        inNextToken      }    }    def warning(pos : Int, msg : String) : Unit    def incompleteInputError(msg: String) : Unit    def deprecationWarning(pos : Int, msg : String) : Unit    def syntaxError(pos: Int, msg: String) : Unit    def syntaxError(msg: String, skipIt: Boolean) {      syntaxError(inCurrentPos, msg, skipIt)    }        def syntaxError(pos: Int, msg: String, skipIt: Boolean) {      if (pos > lastErrorPos) {        syntaxError(pos, msg)        // no more errors on this token.        lastErrorPos = inCurrentPos      }      if (skipIt)         skip()    }    def warning(msg: String) : Unit = warning(inCurrentPos, msg)        def syntaxErrorOrIncomplete(msg: String, skipIt: Boolean) {      val inToken = this.inToken      if (inToken == EOF)        incompleteInputError(msg)      else        syntaxError(inCurrentPos, msg, skipIt)    }    // unused.    def mismatch(expected: Int, found: Int) {      val posToReport = this.posToReport      val msg =        ScannerConfiguration.token2string(expected) + " expected but " +        ScannerConfiguration.token2string(found) + " found."      if (found == EOF)        incompleteInputError(msg)      else        syntaxError(posToReport, msg, true)    }    /** Consume one token of the specified type, or      * signal an error if it is not there.      */    def accept(token: Int): Int = {      val pos = inCurrentPos      if (inToken != token) {        val posToReport =           //if (inCurrentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0))          //  in.lastPos          //else            inCurrentPos        val msg =          ScannerConfiguration.token2string(token) + " expected but " +            ScannerConfiguration.token2string(inToken) + " found."        if (inToken == EOF)          incompleteInputError(msg)        else          syntaxError(posToReport, msg, true)      }      if (inToken == token) inNextToken      pos    }    def surround[T](open : Int, close : Int)(f : => T, orElse : T) : T = {      val wasOpened = inToken == open      accept(open)      if (wasOpened) {        val ret = f        accept(close)        ret      } else orElse    }        /** semi = nl {nl} | `;'      *  nl  = `\n' // where allowed     */    def acceptStatSep() : Boolean = {      if (inToken == NEWLINE || inToken == NEWLINES) { inNextToken; true }      else {        val ret = inToken == SEMI        accept(SEMI)        ret      }    }    def errorTypeTree = TypeTree().setType(ErrorType).setPos((inCurrentPos))    def errorTermTree = Literal(Constant(null)).setPos((inCurrentPos))    def errorPatternTree = Ident(nme.WILDCARD).setPos((inCurrentPos))/////// TOKEN CLASSES //////////////////////////////////////////////////////    def isModifier: Boolean = inToken match {      case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE | IMPLICIT | LAZY => true      case _ => false    }    def isLocalModifier: Boolean = inToken match {      case ABSTRACT | FINAL | SEALED | IMPLICIT | LAZY => true      case _ => false    }    def isDefIntro: Boolean = inToken match {      case VAL | VAR | DEF | TYPE | OBJECT |           CASEOBJECT | CLASS | CASECLASS | TRAIT => true      case _ => false    }    def isDclIntro: Boolean = inToken match {      case VAL | VAR | DEF | TYPE => true      case _ => false    }    def isIdent = inToken == IDENTIFIER || inToken == BACKQUOTED_IDENT    def isExprIntroToken(token: Int): Boolean = token match {      case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |           STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER | BACKQUOTED_IDENT |           THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |           DO | RETURN | THROW | LPAREN | LBRACE | XMLSTART => true      case _ => false    }    def isExprIntro: Boolean = isExprIntroToken(inToken)    def isTypeIntroToken(token: Int): Boolean = token match {      case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER | USCORE | LPAREN | AT => true      case _ => false    }    def isTypeIntro: Boolean = isTypeIntroToken(inToken)    def isStatSep(token: Int): Boolean =       token == NEWLINE || token == NEWLINES || token == SEMI        def isStatSep: Boolean = isStatSep(inToken)/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////    /** Join the comment associated with a definition    */    def joinComment(trees: => List[Tree]): List[Tree] = {      val buf = in.flushDoc      if ((buf ne null) && buf.length > 0) trees map (t => DocDef(buf, t) setPos t.pos)      else trees    }/////// TREE CONSTRUCTION ////////////////////////////////////////////////////    /** Convert tree to formal parameter list    */    def convertToParams(tree: Tree): List[ValDef] = tree match {      case Parens(ts) =>        ts map convertToParam      case _ =>        List(convertToParam(tree))

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?