parsers.scala

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

SCALA
1,932
字号
      compoundTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern)    def compoundTypeRest(pos: Int, t: Tree, isPattern: Boolean): Tree = {      var ts = new ListBuffer[Tree] + t      while (inToken == WITH) {        inNextToken; ts += annotType(isPattern)      }      newLineOptWhenFollowedBy(LBRACE)      atPos(pos) {        if (inToken == LBRACE)           CompoundTypeTree(Template(ts.toList, emptyValDef, refinement()))        else           makeIntersectionTypeTree(ts.toList)      }    }    /** AnnotType        ::=  SimpleType {Annotation}     *  SimpleType       ::=  SimpleType TypeArgs      *                     |  SimpleType `#' Id     *                     |  StableId     *                     |  Path `.' type     *                     |  `(' Types [`,'] `)'     *                     |  WildcardType     */    def annotType(isPattern: Boolean): Tree = placeholderTypeBoundary {      val pos = inCurrentPos            val t: Tree = annotTypeRest(pos, isPattern,        if (inToken == LPAREN) {          inNextToken          val ts = types(isPattern, false, false)          accept(RPAREN)          atPos(pos) { makeTupleType(ts, true) }        } else if (inToken == USCORE) {          wildcardType(in.skipToken)        } else {          val r = path(false, true)          r match {            case SingletonTypeTree(_) => r            case _ => convertToTypeId(r)          }        })      (t /: annotations(false)) (makeAnnotated)    }    def annotTypeRest(pos: Int, isPattern: Boolean, t: Tree): Tree =      if (inToken == HASH) {        inSkipToken        val posId = inCurrentPos        val id = ident        annotTypeRest(pos, isPattern, atPos(posId) { SelectFromTypeTree(t, id.toTypeName) })      } else if (inToken == LBRACKET) {        val usePos = if (t.pos != NoPosition) t.pos else i2p(pos)        annotTypeRest(pos, isPattern, atPos(usePos) { AppliedTypeTree(t, typeArgs(isPattern, false)) })      }      else        t    /** WildcardType ::= `_' TypeBounds     */    def wildcardType(pos: Int) = {      val pname = freshName(pos, "_$").toTypeName      val param = atPos(pos) { makeSyntheticTypeParam(pname, typeBounds()) }      placeholderTypes = param :: placeholderTypes      Ident(pname) setPos pos    }    /** TypeArgs    ::= `[' ArgType {`,' ArgType} `]'     */    def typeArgs(isPattern: Boolean, isTypeApply: Boolean): List[Tree] = {      accept(LBRACKET)      val ts = types(isPattern, isTypeApply, false)      accept(RBRACKET)      ts    }           /** ArgType       ::=  Type     */     def argType(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): Tree =      if (isPattern) {        if (inToken == USCORE)          if (inToken == SUBTYPE || inToken == SUPERTYPE) wildcardType(inSkipToken)          else atPos(inSkipToken) { Bind(nme.WILDCARD.toTypeName, EmptyTree) }        else if (inToken == IDENTIFIER && treeInfo.isVariableName(inName.toTypeName))          atPos(inCurrentPos) {             Bind(ident().toTypeName, EmptyTree)           }        else {          typ(true)         }      } else if (isFuncArg) {        // copy-paste (with change) from def paramType        if (inToken == ARROW)          atPos(inSkipToken) {            AppliedTypeTree(                scalaDot(nme.BYNAME_PARAM_CLASS_NAME.toTypeName), List(typ()))          }        else {          val t = typ()          if (isIdent && inName == STAR) {            inNextToken            atPos(t.pos) {               AppliedTypeTree(                scalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))            }          } else t        }      } else if (isTypeApply) {        typ()      } else {        typ()      }    //////// EXPRESSIONS ////////////////////////////////////////////////////////    /** EqualsExpr ::= `=' Expr     */    def equalsExpr(): Tree = {      accept(EQUALS)      expr()    }    /** Exprs ::= Expr {`,' Expr}      *       *  (also eats trailing comma if it finds one)     */    def exprs(): List[Tree] = {          val ts = new ListBuffer[Tree] + expr()           while (inToken == COMMA) {        val pos = in.currentPos        inNextToken        if (inToken == RPAREN) {          deprecationWarning(pos, "Trailing commas have been deprecated")          return ts.toList        } else {          ts += expr()        }      }      ts.toList    }    /** Expr       ::= (Bindings | Id)  `=>' Expr     *               | Expr1     *  ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block     *               | Expr1     *  Expr1      ::= if `(' Expr `)' {nl} Expr [[semi] else Expr]     *               | try `{' Block `}' [catch `{' CaseClauses `}'] [finally Expr]     *               | while `(' Expr `)' {nl} Expr     *               | do Expr [semi] while `(' Expr `)'     *               | for (`(' Enumerators `)' | '{' Enumerators '}') {nl} [yield] Expr     *               | throw Expr     *               | return [Expr]     *               | [SimpleExpr `.'] Id `=' Expr     *               | SimpleExpr1 ArgumentExprs `=' Expr     *               | PostfixExpr Ascription     *               | PostfixExpr match `{' CaseClauses `}'     *  Bindings   ::= `(' [Binding {`,' Binding}] `)'     *  Binding    ::= Id [`:' Type]     *  Ascription ::= `:' CompoundType     *               | `:' Annotation {Annotation}      *               | `:' `_' `*'     */    def expr(): Tree = expr(Local)    /* hook for IDE, unlike expression can be stubbed     * don't use for any tree that can be inspected in the parser!     */    def statement(location: Int): Tree = expr(location)    def expr(location: Int): Tree = {      def isWildcard(t: Tree): Boolean = t match {        case Ident(name1) if !placeholderParams.isEmpty && name1 == placeholderParams.head.name => true        case Typed(t1, _) => isWildcard(t1)        case Annotated(t1, _) => isWildcard(t1)        case _ => false      }      var savedPlaceholderParams = placeholderParams      placeholderParams = List()      var res = inToken match {        case IF =>          val pos = inSkipToken                    val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))          newLinesOpt()          val thenp = expr()          val elsep =            if (inToken == ELSE) { inNextToken; expr() }            else EmptyTree          atPos(pos) { If(cond, thenp, elsep) }        case TRY =>          atPos(inSkipToken) {            val body = surround(LBRACE,RBRACE)(block(), Literal(()))            val catches =               if (inToken == CATCH) {                 inNextToken                val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)                cases              } else List()            val finalizer =               if (inToken == FINALLY) { inNextToken; expr() }              else EmptyTree            Try(body, catches, finalizer)          }        case WHILE =>          val pos = inSkipToken          val lname: Name = freshName(pos, "while$")          val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))          newLinesOpt()          val body = expr()          atPos(pos) { makeWhile(lname, cond, body) }        case DO =>          val pos = inSkipToken          val lname: Name = freshName(pos, "doWhile$")          val body = expr()          if (isStatSep) inNextToken          accept(WHILE)          val cond = surround(LPAREN,RPAREN)(expr(), Literal(true))          atPos(pos) { makeDoWhile(lname, body, cond) }        case FOR =>          atPos(inSkipToken) {            val startToken = inToken            val (open,close) = if (startToken == LBRACE) (LBRACE,RBRACE) else (LPAREN,RPAREN)            val enums = surround(open,close)(enumerators(), Nil)            newLinesOpt()            if (inToken == YIELD) {              inNextToken; makeForYield(enums, expr())            } else makeFor(enums, expr())          }        case RETURN =>          atPos(inSkipToken) {            Return(if (isExprIntro) expr() else Literal(()))          }        case THROW =>          atPos(inSkipToken) {             Throw(expr())           }        case DOT =>          deprecationWarning(in.currentPos, "`.f' has been deprecated; use `_.f'  instead")          atPos(inSkipToken) {            if (isIdent) {              makeDotClosure(stripParens(simpleExpr()))            } else {              syntaxErrorOrIncomplete("identifier expected", true)              errorTermTree             }          }        case _ =>          var t = postfixExpr()          if (inToken == EQUALS) {            t match {              case Ident(_) | Select(_, _) | Apply(_, _) =>                t = atPos(inSkipToken) { makeAssign(t, expr()) }              case _ =>             }          } else if (inToken == COLON) {            t = stripParens(t)            val pos = inSkipToken            if (inToken == USCORE) {              //todo: need to handle case where USCORE is a wildcard in a type              val pos1 = inSkipToken              if (isIdent && inName == nme.STAR) {                inNextToken                t = atPos(pos) {                  Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })                }              } else {                syntaxErrorOrIncomplete("`*' expected", true)              }            } else if (in.token == AT) {              t = (t /: annotations(false)) (makeAnnotated)            } else {              t = atPos(pos) {                 val tpt = if (location != Local) compoundType(false) else typ()                if (isWildcard(t))                  (placeholderParams: @unchecked) match {                    case (vd @ ValDef(mods, name, _, _)) :: rest =>                       placeholderParams = copy.ValDef(vd, mods, name, tpt.duplicate, EmptyTree) :: rest                  }                // this does not correspond to syntax, but is necessary to                 // accept closures. We might restrict closures to be between {...} only!                Typed(t, tpt)              }            }          } else if (inToken == MATCH) {            t = atPos(inSkipToken) {              val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)              Match(stripParens(t), cases)            }          }          if (inToken == ARROW && location != InTemplate) {            t = atPos(inSkipToken) {              Function(convertToParams(t), if (location == Local) expr() else block())            }          }          stripParens(t)      }      if (!placeholderParams.isEmpty && !isWildcard(res)) {        res = atPos(res.pos){ Function(placeholderParams.reverse, res) }        placeholderParams = List()      }      placeholderParams = placeholderParams ::: savedPlaceholderParams      res    }    /** PostfixExpr   ::= InfixExpr [Id [nl]]     *  InfixExpr     ::= PrefixExpr     *                  | InfixExpr Id [nl] InfixExpr     */    def postfixExpr(): Tree = {      val base = opstack      var top = prefixExpr()      while (isIdent) {        top = reduceStack(          true, base, top, precedence(inName), treeInfo.isLeftAssoc(inName))        val op = inName        opstack = OpInfo(top, op, inCurrentPos) :: opstack        ident()        newLineOptWhenFollowing(isExprIntroToken)        if (isExprIntro) {          top = prefixExpr()        } else {          val topinfo = opstack.head          opstack = opstack.tail          return Select(            stripParens(reduceStack(true, base, topinfo.operand, 0, true)),            topinfo.operator.encode).setPos(topinfo.pos)        }      }      reduceStack(true, base, top, 0, true)    }    /** PrefixExpr   ::= [`-' | `+' | `~' | `!' | `&'] SimpleExpr     */    def prefixExpr(): Tree = {      def unaryOp(): Name = "unary_" + ident()      if (isIdent && inName == MINUS) {        val name = unaryOp()        inToken match {          case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)          case _ => atPos(inCurrentPos) { Select(stripParens(simpleExpr()), name) }        }      } else if (isIdent && (inName == PLUS || inName == TILDE || inName == BANG)) {        val pos = inCurrentPos        val name = unaryOp()        atPos(pos) { Select(stripParens(simpleExpr()), name) }      } else if (isIdent && inName == AMP) {        deprecationWarning(in.currentPos, "`&f' has been deprecated; use `f _' instead")        val pos = inCurrentPos        val name = ident()        atPos(pos) { Typed(stripParens(simpleExpr()), Function(List(), EmptyTree)) }/* XX-LIFTING      } else if (settings.Xexperimental.value && isIdent && inName == SLASH) {        val pos = inSkipToken        val name = freshName()        liftedGenerators += ValFrom(pos, Bind(name, Ident(nme.WILDCARD)), simpleExpr())        Ident(name) setPos pos*/      } else {        simpleExpr()      }    }    def xmlLiteral(): Tree        /* SimpleExpr    ::= new (ClassTemplate | TemplateBody)     *                |  BlockExpr     *                |  SimpleExpr1 [`_']     * SimpleExpr1   ::= literal     *                |  xLiteral     *                |  Path     *                |  `(' [Exprs [`,']] `)'     *                |  SimpleExpr `.' Id      *                |  SimpleExpr TypeArgs     *                |  SimpleExpr1 ArgumentExprs     */    def simpleExpr(): Tree = {      var t: Tree = null      var canApply = true      inToken match {        case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |              SYMBOLLIT | TRUE | FALSE | NULL =>          t = literal(false, false)        case XMLSTART => t = xmlLiteral()        case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>          t = path(true, false)        case USCORE =>          val pos = inSkipToken          val pname = freshName(pos, "x$")          val param = atPos(pos){ makeSyntheticParam(pname) }

⌨️ 快捷键说明

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