parsers.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,932 行 · 第 1/5 页
SCALA
1,932 行
} /** Convert tree to formal parameter */ def convertToParam(tree: Tree): ValDef = atPos(tree.pos) { tree match { case Ident(name) => ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree) case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident! ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree).setPos(tree.pos) case _ => syntaxError(tree.pos, "not a legal formal parameter", false) ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree) } } /** Convert (qual)ident to type identifier */ def convertToTypeId(tree: Tree): Tree = tree match { case Ident(name) => Ident(name.toTypeName).setPos(tree.pos) case Select(qual, name) => Select(qual, name.toTypeName).setPos(tree.pos) case _ => syntaxError(tree.pos, "identifier expected", false) errorTypeTree } /** make closure from tree staring with a `.' */ def makeDotClosure(tree: Tree): Tree = { val pname = freshName(tree.pos, "x$") def insertParam(tree: Tree): Tree = atPos(tree.pos) { tree match { case Ident(name) => Select(Ident(pname), name) case Select(qual, name) => Select(insertParam(qual), name) case Apply(fn, args) => Apply(insertParam(fn), args) case TypeApply(fn, args) => TypeApply(insertParam(fn), args) case _ => syntaxError(tree.pos, "cannot convert to closure", false) errorTermTree } } Function(List(makeSyntheticParam(pname)), insertParam(tree)) }/////// OPERAND/OPERATOR STACK ///////////////////////////////////////////////// var opstack: List[OpInfo] = Nil def precedence(operator: Name): Int = if (operator eq nme.ERROR) -1 else { val firstCh = operator(0) if (((firstCh >= 'A') && (firstCh <= 'Z')) || ((firstCh >= 'a') && (firstCh <= 'z'))) 1 else firstCh match { case '|' => 2 case '^' => 3 case '&' => 4 case '=' | '!' => 5 case '<' | '>' => 6 case ':' => 7 case '+' | '-' => 8 case '*' | '/' | '%' => 9 case _ => 10 } } def checkSize(kind: String, size: Int, max: Int) { if (size > max) syntaxError("too many "+kind+", maximum = "+max, false) } def checkAssoc(pos: Int, op: Name, leftAssoc: Boolean) = if (treeInfo.isLeftAssoc(op) != leftAssoc) syntaxError( pos, "left- and right-associative operators with same precedence may not be mixed", false) def reduceStack(isExpr: Boolean, base: List[OpInfo], top0: Tree, prec: Int, leftAssoc: Boolean): Tree = { var top = top0 if (opstack != base && precedence(opstack.head.operator) == prec) checkAssoc(opstack.head.pos, opstack.head.operator, leftAssoc) while (opstack != base && (prec < precedence(opstack.head.operator) || (leftAssoc && prec == precedence(opstack.head.operator)))) { top = atPos(opstack.head.pos) { makeBinop(isExpr, opstack.head.operand, opstack.head.operator, top) } opstack = opstack.tail } top }/////// IDENTIFIERS AND LITERALS //////////////////////////////////////////////////////////// def ident(): Name = if (inToken == IDENTIFIER || inToken == BACKQUOTED_IDENT) { val name = inName.encode inNextToken name } else { accept(IDENTIFIER) nme.ERROR } def selector(t: Tree) = atPos(inCurrentPos)(Select(t, ident())) /** Path ::= StableId * | [Ident `.'] this * AnnotType ::= Path [`.' type] */ def path(thisOK: Boolean, typeOK: Boolean): Tree = { var t: Tree = null if (inToken == THIS) { t = atPos(inSkipToken) { This(nme.EMPTY.toTypeName) } if (!thisOK || inToken == DOT) { t = selectors(t, typeOK, accept(DOT)) } } else if (inToken == SUPER) { // val pos = inCurrentPos val pos = inSkipToken val (mix,usePos) = mixinQualifierOpt(pos) t = atPos(usePos) { Super(nme.EMPTY.toTypeName, mix) } t = atPos(accept(DOT)) { selector(t) } if (inToken == DOT) t = selectors(t, typeOK, inSkipToken) } else { val i = atPos(inCurrentPos) { if (inToken == BACKQUOTED_IDENT) new BackQuotedIdent(ident()) else Ident(ident()) } t = i if (inToken == DOT) { val pos = inSkipToken if (inToken == THIS) { inNextToken t = atPos(i.pos) { This(i.name.toTypeName) } if (!thisOK || inToken == DOT) t = selectors(t, typeOK, accept(DOT)) } else if (inToken == SUPER) { inNextToken val (mix,pos) = mixinQualifierOpt(i.pos) t = atPos(pos) { Super(i.name.toTypeName, mix) } t = atPos(accept(DOT)) {selector(t)} if (inToken == DOT) t = selectors(t, typeOK, inSkipToken) } else { t = selectors(t, typeOK, pos) } } } t } def selectors(t: Tree, typeOK: Boolean, pos : Int): Tree = if (typeOK && inToken == TYPE) { inNextToken atPos(pos) { SingletonTypeTree(t) } } else { val t1 = atPos(pos) { selector(t); } if (inToken == DOT) { selectors(t1, typeOK, inSkipToken) } else t1 } /** MixinQualifier ::= `[' Id `]' */ def mixinQualifierOpt(pos : Position): (Name,Position) = if (inToken == LBRACKET) { inNextToken val pos = inCurrentPos val name = ident().toTypeName accept(RBRACKET) (name,pos) } else { (nme.EMPTY.toTypeName,pos) } /** StableId ::= Id * | Path `.' Id * | [id '.'] super [`[' id `]']`.' id */ def stableId(): Tree = path(false, false) /** QualId ::= Id {`.' Id} */ def qualId(): Tree = { val id = atPos(inCurrentPos) { Ident(ident()) } if (inToken == DOT) { selectors(id, false, inSkipToken) } else id } /** SimpleExpr ::= literal * | symbol * | null */ def literal(isPattern: Boolean, isNegated: Boolean): Tree = { def litToTree() = atPos(inCurrentPos) { Literal( inToken match { case CHARLIT => Constant(charVal) case INTLIT => Constant(intVal(isNegated)) case LONGLIT => Constant(longVal(isNegated)) case FLOATLIT =>Constant(floatVal(isNegated)) case DOUBLELIT => Constant(doubleVal(isNegated)) case STRINGLIT | SYMBOLLIT => Constant(stringVal) case TRUE => Constant(true) case FALSE => Constant(false) case NULL => Constant(null) case _ => syntaxErrorOrIncomplete("illegal literal", true) null }) } val isSymLit = inToken == SYMBOLLIT val t = litToTree() val pos = inSkipToken if (isSymLit) { atPos(pos) { var symid = scalaDot(nme.Symbol) Apply(symid, List(t)) } } else { t } } def newLineOpt() { if (inToken == NEWLINE) inNextToken } def newLinesOpt() { if (inToken == NEWLINE || inToken == NEWLINES) inNextToken } def newLineOptWhenFollowedBy(token: Int) { // note: next is defined here because current == NEWLINE if (inToken == NEWLINE && inNextTokenCode == token) newLineOpt() } def newLineOptWhenFollowing(p: Int => Boolean) { // note: next is defined here because current == NEWLINE if (inToken == NEWLINE && p(inNextTokenCode)) newLineOpt() }//////// TYPES /////////////////////////////////////////////////////////////// /** TypedOpt ::= [`:' Type] */ def typedOpt(): Tree = if (inToken == COLON) { inNextToken; typ() } else TypeTree() /** RequiresTypedOpt ::= [requires AnnotType] */ def requiresTypeOpt(): Tree = if (inToken == REQUIRES) { deprecationWarning(in.currentPos, "`requires T' has been deprecated; use `{ self: T => ...' instead") inNextToken; annotType(false) } else TypeTree() /** Types ::= Type {`,' Type} * (also eats trailing comma if it finds one) */ def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] = { val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply, isFuncArg) while (inToken == COMMA) { val pos = inCurrentPos inNextToken if (inToken == RPAREN) { deprecationWarning(pos, "Trailing commas have been deprecated") return ts.toList } else { ts += argType(isPattern, isTypeApply, isFuncArg) } } ts.toList } /** modes for infix types */ object InfixMode extends Enumeration { val FirstOp, LeftOp, RightOp = Value } /** Type ::= InfixType `=>' Type * | `(' [`=>' Type] `)' `=>' Type * | InfixType [ExistentialClause] * ExistentialClause ::= forSome `{' ExistentialDcl {semi ExistentialDcl}} `}' * ExistentialDcl ::= type TypeDcl | val ValDcl */ def typ(): Tree = typ(false) def typ(isPattern: Boolean): Tree = placeholderTypeBoundary { val t = if (inToken == LPAREN) { val pos = inSkipToken if (inToken == RPAREN) { inNextToken atPos(accept(ARROW)) { makeFunctionTypeTree(List(), typ(isPattern)) } /* Not more used } else if (inToken == ARROW) { inNextToken val t0 = typ(isPattern) accept(RPAREN) atPos(accept(ARROW)) { makeByNameFunctionTypeTree(t0, typ(isPattern)) } */ } else { val ts = types(isPattern, false, true) accept(RPAREN) if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(ts, typ(isPattern)) } else { for (t <- ts) t match { case AppliedTypeTree(Select(_, n), _) if (n == nme.BYNAME_PARAM_CLASS_NAME.toTypeName) => syntaxError(t.pos, "no by-name parameter type allowed here", false) case _ => } infixTypeRest(pos, annotTypeRest(pos, isPattern, makeTupleType(ts, true)), false, InfixMode.FirstOp) } } } else { infixType(isPattern, InfixMode.FirstOp) } if (inToken == ARROW) atPos(inSkipToken) { makeFunctionTypeTree(List(t), typ(isPattern)) } else if (inToken == FORSOME) atPos(inSkipToken) { val whereClauses = refinement() for (wc <- whereClauses) { wc match { case TypeDef(_, _, _, TypeBoundsTree(_, _)) | ValDef(_, _, _, EmptyTree) | EmptyTree => ; case _ => syntaxError(wc.pos, "not a legal where clause", false) } } ExistentialTypeTree(t, whereClauses) } else t } /** InfixType ::= CompoundType {id [nl] CompoundType} */ def infixType(isPattern: Boolean, mode: InfixMode.Value): Tree = placeholderTypeBoundary { infixTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern, mode) } def infixTypeFirst(isPattern: Boolean) = if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern) def infixTypeRest(pos: Int, t0: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = { val t = compoundTypeRest(pos, t0, isPattern) if (isIdent && inName != nme.STAR) { val opPos = inCurrentPos val leftAssoc = treeInfo.isLeftAssoc(inName) if (mode == InfixMode.LeftOp) checkAssoc(opPos, inName, true) else if (mode == InfixMode.RightOp) checkAssoc(opPos, inName, false) val op = ident() newLineOptWhenFollowing(isTypeIntroToken) def mkOp(t1: Tree) = atPos(opPos) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) } if (leftAssoc) infixTypeRest(inCurrentPos, mkOp(compoundType(isPattern)), isPattern, InfixMode.LeftOp) else mkOp(infixType(isPattern, InfixMode.RightOp)) } else t } /** CompoundType ::= AnnotType {with AnnotType} [Refinement] * | Refinement */ def compoundType(isPattern: Boolean): Tree =
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?