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 + -
显示快捷键?