parsers.scala

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

SCALA
1,932
字号
          placeholderParams = param :: placeholderParams          t = atPos(pos) { Ident(pname) }        case LPAREN =>          val pos = inSkipToken          val ts = if (inToken == RPAREN) List() else exprs()          accept(RPAREN)          t = Parens(ts) setPos (pos)        case LBRACE =>          t = blockExpr()          canApply = false        case NEW =>          t = atPos(inSkipToken) {            val (parents, argss, self, stats) = template(false)            makeNew(parents, self, stats, argss)          }          canApply = false        case _ =>          syntaxErrorOrIncomplete("illegal start of simple expression", true)          t = errorTermTree      }      simpleExprRest(t, canApply)    }    def simpleExprRest(t: Tree, canApply: Boolean): Tree = {      if (canApply) newLineOptWhenFollowedBy(LBRACE)      inToken match {        case DOT =>          simpleExprRest(atPos(inSkipToken) { selector(stripParens(t)) }, true)        case LBRACKET =>          val t1 = stripParens(t)          t1 match {            case Ident(_) | Select(_, _) =>              val pos = if (t1.pos == NoPosition) i2p(inCurrentPos) else t1.pos              simpleExprRest(atPos(pos) { TypeApply(t1, typeArgs(false, true)) }, true)            case _ =>              t1          }        case LPAREN | LBRACE if (canApply) =>          // again, position should be on idetifier, not (          var pos = if (t.pos == NoPosition) i2p(inCurrentPos) else t.pos          simpleExprRest(atPos(pos) { Apply(stripParens(t), argumentExprs()) }, true)        case USCORE =>          atPos(inSkipToken) { Typed(stripParens(t), Function(List(), EmptyTree)) }        case _ =>          t      }    }    /** ArgumentExprs ::= `(' [Exprs [`,']] `)'      *                 | [nl] BlockExpr     */    def argumentExprs(): List[Tree] = {      if (inToken == LBRACE) {        List(blockExpr())      } else {        val ts = surround(LPAREN,RPAREN)(if (inToken == RPAREN) List() else exprs(), List())        ts      }    }    /** BlockExpr ::= `{' (CaseClauses | Block) `}'     */    def blockExpr(): Tree = {      assert(inToken == LBRACE)      val res = atPos(accept(LBRACE)) { // no need to surround        if (inToken == CASE) Match(EmptyTree, caseClauses())        else block()      }      accept(RBRACE)      res    }        /** Block ::= BlockStatSeq     */    def block(): Tree =       makeBlock(blockStatSeq(new ListBuffer[Tree]))   /** CaseClauses ::= CaseClause {CaseClause}     */    def caseClauses(): List[CaseDef] = {      val ts = new ListBuffer[CaseDef]      do { ts += caseClause()      } while (inToken == CASE)      ts.toList    }    /** CaseClause ::= case Pattern [Guard] `=>' Block     */    def caseClause(): CaseDef =      atPos(accept(CASE)) {        val pat = pattern()        val gd = guard()        makeCaseDef(pat, gd, caseBlock())      }    // IDE HOOK (so we can memoize case blocks)    def caseBlock(): Tree =       atPos(accept(ARROW))(block())    /** Guard ::= if PostfixExpr     */    def guard(): Tree =       if (inToken == IF) { inNextToken; stripParens(postfixExpr()) }       else EmptyTree          /** Enumerators ::= Generator {semi Enumerator}     *  Enumerator  ::=  Generator     *                |  Guard     *                |  val Pattern1 `=' Expr     */    def enumerators(): List[Enumerator] = {      val newStyle = inToken != VAL // todo: deprecate old style      //if (!newStyle)      //  deprecationWarning(inCurrentPos, "for (val x <- ... ) has been deprecated; use for (x <- ... ) instead")      val enums = new ListBuffer[Enumerator]      generator(enums, false)      while (isStatSep) {        inNextToken        if (newStyle) {          if (inToken == IF) enums += Filter(guard())          else generator(enums, true)        } else {          if (inToken == VAL) generator(enums, true)           else enums += Filter(expr())        }      }      enums.toList    }    /** Generator ::= val Pattern1 `<-' Expr [Guard]     */    def generator(enums: ListBuffer[Enumerator], eqOK: Boolean) {      if (inToken == VAL) inNextToken      val pos = inCurrentPos;      val pat = pattern1(false)      val tok = inToken      if (tok == EQUALS && eqOK) inNextToken      else accept(LARROW)      enums += makeGenerator(pos, pat, tok == EQUALS, expr)      if (inToken == IF) enums += Filter(guard())    }    //def p2i(pos : ScanPosition) : Int;//////// PATTERNS ////////////////////////////////////////////////////////////    /**   Patterns ::= Pattern { `,' Pattern }       *    SeqPatterns ::= SeqPattern { `,' SeqPattern }       *       *  (also eats trailing comma if it finds one)     */    def patterns(seqOK: Boolean): List[Tree] = {      val ts = new ListBuffer[Tree] + pattern(seqOK)      while (inToken == COMMA) {        val pos = inCurrentPos        inNextToken         if (inToken == RPAREN) {          deprecationWarning(pos, "Trailing commas have been deprecated")          return ts.toList        } else {          ts += pattern(seqOK)        }      }      ts.toList    }    /**   Pattern  ::=  Pattern1 { `|' Pattern1 }     *    SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }     */    def pattern(seqOK: Boolean): Tree = {      val pos = inCurrentPos      val t = pattern1(seqOK)      if (isIdent && inName == BAR) {        val ts = new ListBuffer[Tree] + t        while (isIdent && inName == BAR) {          inNextToken; ts += pattern1(seqOK)        }        atPos(pos) { makeAlternative(ts.toList) }      } else t    }    def pattern(): Tree = pattern(false)    /**   Pattern1    ::= varid `:' TypePat     *                 |  `_' `:' TypePat     *                 |  Pattern2     *    SeqPattern1 ::= varid `:' TypePat     *                 |  `_' `:' TypePat     *                 |  [SeqPattern2]     */    def pattern1(seqOK: Boolean): Tree = {      //if (false && /*disabled, no regexp matching*/ seqOK && !isExprIntro) {        //atPos(inCurrentPos) { Sequence(List()) }      //} else {        val p = pattern2(seqOK)        p match {          case Ident(name) if (treeInfo.isVarPattern(p) && inToken == COLON) =>            atPos(inSkipToken) { Typed(p, compoundType(true)) }          case _ =>            p        }      //}    }    /*   Pattern2    ::=  varid [ @ Pattern3 ]     *                |   Pattern3     *   SeqPattern2 ::=  varid [ @ SeqPattern3 ]     *                |   SeqPattern3     */    def pattern2(seqOK: Boolean): Tree = {      val p = pattern3(seqOK)      if (inToken == AT) {        p match {          case Ident(name) =>            if (name == nme.WILDCARD) {              inNextToken; pattern3(seqOK)            } else if (treeInfo.isVarPattern(p)) {              inNextToken              atPos(p.pos) { Bind(name, pattern3(seqOK)) }            } else {              p            }          case _ =>            p        }      } else p    }    /*   Pattern3    ::= SimplePattern     *                |  SimplePattern {Id [nl] SimplePattern}      *   SeqPattern3 ::= SeqSimplePattern [ '*' | '?' | '+' ]     *                |  SeqSimplePattern {Id [nl] SeqSimplePattern}      */    def pattern3(seqOK: Boolean): Tree = {      val base = opstack      var top = simplePattern(seqOK)      if (seqOK && isIdent) {        if (inName == STAR)          return atPos(inSkipToken)(Star(top))        else if (inName == PLUS)          return atPos(inSkipToken)(makePlus(top))        else if (inName == OPT)          return atPos(inSkipToken)(makeOpt(top))      }      while (isIdent && inName != BAR) {        top = reduceStack(          false, base, top, precedence(inName), treeInfo.isLeftAssoc(inName))        val op = inName        opstack = OpInfo(top, op, inCurrentPos) :: opstack        ident()        top = simplePattern(seqOK)      }      stripParens(reduceStack(false, base, top, 0, true))    }         def xmlLiteralPattern() : Tree     /** SimplePattern    ::= varid     *                    |  `_'     *                    |  literal     *                    |  XmlPattern     *                    |  StableId  [TypeArgs] [`(' [SeqPatterns [`,']] `)']     *                    |  `(' [Patterns [`,']] `)'     *  SimpleSeqPattern ::= varid     *                    |  `_'     *                    |  literal     *                    |  XmlPattern     *                    |  `<' xLiteralPattern      *                    |  StableId [TypeArgs] [`(' [SeqPatterns [`,']] `)']     *                    |  `(' [SeqPatterns [`,']] `)'     *      * XXX: Hook for IDE     */    def simplePattern(seqOK: Boolean): Tree = inToken match {      case IDENTIFIER | BACKQUOTED_IDENT | THIS =>        var t = stableId()        inToken match {          case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>            t match {              case Ident(name) if name == nme.MINUS =>                return literal(true, true)              case _ =>            }          case _ =>        }/* not yet        if (inToken == LBRACKET)          atPos(inCurrentPos) {            val ts = typeArgs(true, false)            accept(LPAREN)            val ps = if (inToken == RPAREN) List() else patterns(true, false)            accept(RPAREN)            Apply(TypeApply(convertToTypeId(t), ts), ps)          }        else */        if (inToken == LPAREN) {          atPos(t.pos) { Apply(t, argumentPatterns()) }        } else t      case USCORE =>        atPos(inSkipToken) { Ident(nme.WILDCARD) }      case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>        literal(true, false)      case LPAREN =>        val pos = inSkipToken        val ps = if (inToken == RPAREN) List() else patterns(false)        accept(RPAREN)        Parens(ps) setPos (pos)      case XMLSTART => xmlLiteralPattern()      case _ =>        syntaxErrorOrIncomplete("illegal start of simple pattern", true)        errorPatternTree    }    def argumentPatterns(): List[Tree] = {      accept(LPAREN)      val ps = if (inToken == RPAREN) List() else patterns(true)      accept(RPAREN)      ps    }////////// MODIFIERS and ANNOTATIONS /////////////////////////////////////////////////    private def normalize(mods: Modifiers): Modifiers =       if ((mods hasFlag Flags.PRIVATE) && mods.privateWithin != nme.EMPTY.toTypeName)        mods &~ Flags.PRIVATE      else if ((mods hasFlag Flags.ABSTRACT) && (mods hasFlag Flags.OVERRIDE))        mods &~ (Flags.ABSTRACT | Flags.OVERRIDE) | Flags.ABSOVERRIDE      else        mods    private def addMod(mods: Modifiers, mod: Long): Modifiers = {      if (mods hasFlag mod) syntaxError(inCurrentPos, "repeated modifier", false)      inNextToken      mods | mod    }    /** AccessQualifier ::= "[" (Id | this) "]"     */    def accessQualifierOpt(mods: Modifiers) = {      var result = mods      if (inToken == LBRACKET) {        inNextToken        if (mods.privateWithin != nme.EMPTY.toTypeName)          syntaxError("duplicate private/protected qualifier", false)        result = if (inToken == THIS) { inNextToken; mods | Flags.LOCAL }                 else Modifiers(mods.flags, ident().toTypeName)        accept(RBRACKET)      }      result    }    /** AccessModifier ::= (private | protected) [AccessQualifier]     */    def accessModifierOpt(): Modifiers = normalize {      inToken match {        case PRIVATE => inNextToken; accessQualifierOpt(Modifiers(Flags.PRIVATE))        case PROTECTED => inNextToken; accessQualifierOpt(Modifiers(Flags.PROTECTED))        case _ => NoMods      }    }    /** Modifiers ::= {Modifier}     *  Modifier  ::= LocalModifier      *             |  AccessModifier     *             |  override     */    def modifiers(): Modifiers = normalize {      def loop(mods: Modifiers): Modifiers = inToken match {        case ABSTRACT =>          loop(addMod(mods, Flags.ABSTRACT))        case FINAL =>          loop(addMod(mods, Flags.FINAL))        case SEALED =>          loop(addMod(mods, Flags.SEALED))        case PRIVATE =>          loop(accessQualifierOpt(addMod(mods, Flags.PRIVATE)))        case PROTECTED =>          loop(accessQualifierOpt(addMod(mods, Flags.PROTECTED)))        case OVERRIDE =>          loop(addMod(mods, Flags.OVERRIDE))        case IMPLICIT =>          loop(addMod(mods, Flags.IMPLICIT))        case LAZY =>          loop(addMod(mods, Flags.LAZY))        case _ =>          mods      }      loop(NoMods)    }

⌨️ 快捷键说明

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