summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-12-08 18:13:31 +0000
committerMartin Odersky <odersky@gmail.com>2006-12-08 18:13:31 +0000
commitcb3adcfb6d0023da523c6a9f04dc8b7b5555e85c (patch)
tree00660c17ed4fad01ab8ecf1fcb32bd0a0e342105 /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parent4b8520e5ef660ba5089f0e12c34a7b2f3dd61497 (diff)
downloadscala-cb3adcfb6d0023da523c6a9f04dc8b7b5555e85c.tar.gz
scala-cb3adcfb6d0023da523c6a9f04dc8b7b5555e85c.tar.bz2
scala-cb3adcfb6d0023da523c6a9f04dc8b7b5555e85c.zip
implemented infix type operators
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala79
1 files changed, 56 insertions, 23 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index d0ca47ed0f..f47ced301d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -3,6 +3,8 @@
* @author Martin Odersky
*/
// $Id$
+//todo: allow infix type patterns
+
package scala.tools.nsc.ast.parser
@@ -190,6 +192,11 @@ trait Parsers requires SyntaxAnalyzer {
def isExprIntro: boolean = isExprIntroToken(in.token)
+ def isTypeIntroToken(token: int): boolean = token match {
+ case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER | USCORE | LPAREN => true
+ case _ => false
+ }
+
/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////
/** Join the comment associated with a definition
@@ -293,16 +300,15 @@ trait Parsers requires SyntaxAnalyzer {
}
}
+ 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 &&
- treeInfo.isLeftAssoc(opstack.head.operator) != leftAssoc) {
- syntaxError(
- opstack.head.pos,
- "left- and right-associative operators with same precedence may not be mixed",
- false)
- }
+ 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)))) {
@@ -517,10 +523,14 @@ trait Parsers requires SyntaxAnalyzer {
ts.toList
}
- /** Type ::= Type1 `=>' Type
- * | `(' `=>' Type `)' `=>' Type
- * | `(' [Types] `)' `=>' Type
- * | Type1
+ /** modes for infix types */
+ final val FirstOp = 0 // first operand
+ final val LeftOp = 1 // left associative
+ final val RightOp = 2 // right associative
+
+ /** Type ::= InfixType `=>' Type
+ * | `(' [Types | `=>' Type] `)' `=>' Type
+ * | InfixType
*/
def typ(): Tree = {
val t =
@@ -544,24 +554,47 @@ trait Parsers requires SyntaxAnalyzer {
atPos (accept(ARROW)) { makeFunctionTypeTree(ts.toList, typ()) }
} else {
accept(RPAREN)
- type1rest(pos, t0, false)
+ infixTypeRest(pos, t0, false, FirstOp)
}
}
} else {
- type1(false)
+ infixType(false, FirstOp)
}
if (in.token == ARROW) atPos(in.skipToken()) {
makeFunctionTypeTree(List(t), typ()) }
else t
}
- /** Type1 ::= SimpleType {with SimpleType} [Refinement]
- * TypePattern ::= SimpleTypePattern {with SimpleTypePattern}
+ /** InfixType ::= CompoundType {id [NewLine] CompoundType}
+ * TypePattern ::= CompoundTypePattern {id [NewLine] CompoundTypePattern
+ */
+ def infixType(isPattern: boolean, mode: int): Tree =
+ infixTypeRest(in.currentPos, simpleType(isPattern), isPattern, mode)
+
+ def infixTypeRest(pos: int, t0: Tree, isPattern: boolean, mode: int): Tree = {
+ val t = compoundTypeRest(pos, t0, isPattern)
+ if (isIdent && in.name != nme.STAR) {
+ val opPos = in.pos
+ val leftAssoc = treeInfo.isLeftAssoc(in.name)
+ if (mode == LeftOp) checkAssoc(opPos, in.name, true)
+ else if (mode == RightOp) checkAssoc(opPos, in.name, false)
+ val op = ident()
+ newLineOptWhenFollowing(isTypeIntroToken)
+ def mkOp(t1: Tree) = atPos(opPos) { AppliedTypeTree(Ident(op.toTypeName), List(t, t1)) }
+ if (leftAssoc)
+ infixTypeRest(in.pos, mkOp(compoundType(isPattern)), isPattern, LeftOp)
+ else
+ mkOp(infixType(isPattern, RightOp))
+ } else t
+ }
+
+ /** CompoundType ::= SimpleType {with SimpleType} [Refinement]
+ * CompoundTypePattern ::= SimpleTypePattern {with SimpleTypePattern}
*/
- def type1(isPattern: boolean): Tree =
- type1rest(in.currentPos, simpleType(isPattern), isPattern)
+ def compoundType(isPattern: boolean): Tree =
+ compoundTypeRest(in.currentPos, simpleType(isPattern), isPattern)
- def type1rest(pos: int, t: Tree, isPattern: boolean): Tree = {
+ def compoundTypeRest(pos: int, t: Tree, isPattern: boolean): Tree = {
var ts = new ListBuffer[Tree] + t
while (in.token == WITH) {
in.nextToken(); ts += simpleType(isPattern)
@@ -706,7 +739,7 @@ trait Parsers requires SyntaxAnalyzer {
/** Expr ::= (Bindings | Id) `=>' Expr
* | Expr1
- * ResultExpr ::= (Bindings | Id `:' Type1) `=>' Block
+ * ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block
* | Expr1
* Expr1 ::= if (' Expr `)' [NewLine] Expr [[`;'] else Expr]
* | try `{' block `}' [catch `{' caseClauses `}'] [finally Expr]
@@ -718,7 +751,7 @@ trait Parsers requires SyntaxAnalyzer {
* | [SimpleExpr `.'] Id `=' Expr
* | SimpleExpr ArgumentExprs `=' Expr
* | `.' SimpleExpr
- * | PostfixExpr [`:' Type1]
+ * | PostfixExpr [`:' CompoundType]
* | PostfixExpr match `{' CaseClauses `}'
* | MethodClosure
* Bindings ::= `(' [Binding {`,' Binding}] `)'
@@ -840,7 +873,7 @@ trait Parsers requires SyntaxAnalyzer {
syntaxError(in.currentPos, "`*' expected", true)
}
} else {
- t = atPos(pos) { Typed(t, if ((mode & IsInBlock) != 0) type1(false) else typ()) }
+ t = atPos(pos) { Typed(t, if ((mode & IsInBlock) != 0) compoundType(false) else typ()) }
if ((mode & IsInBlock) != 0 && in.token == COMMA) {
val vdefs = new ListBuffer[ValDef]
while (in.token == COMMA) {
@@ -1134,7 +1167,7 @@ trait Parsers requires SyntaxAnalyzer {
val p = pattern2(seqOK)
p match {
case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) =>
- atPos(in.skipToken()) { Typed(p, type1(true)) }
+ atPos(in.skipToken()) { Typed(p, compoundType(true)) }
case _ =>
p
}