views:

217

answers:

2

I've got the above odd error message that I don't understand "value Parsers is not a member of package scala.util.parsing.combinator".

I'm trying to learn Parser combinators by writing a C parser step by step. I started at token, so I have the classes:

import util.parsing.combinator.JavaTokenParsers
object CeeParser extends JavaTokenParsers {
    def token: Parser[CeeExpr] = ident ^^ (x => Token(x))
}

abstract class CeeExpr 
case class Token(name: String) extends CeeExpr

This is as simple as I could make it.

The code below works fine, but if I uncomment the commented line I get the error message given above:

object Play {
  def main(args: Array[String]) {
    //val parser: _root_.scala.util.parsing.combinator.Parsers.Parser[CeeExpr] CeeParser.token
    val x = CeeParser.token
    print(x)
  }
}

In case it is a problem with my setup, I'm using scala 2.7.6 via the scala-plugin for intellij. Can anyone shed any light on this? The message is wrong, Parsers is a member of scala.util.parsing.combinator.

--- Follow-up

This person http://www.scala-lang.org/node/5475 seems to have the same problem, but I don't understand the answer he was given. Can anyone explain it?

+1  A: 

The issue is that Parsers is not a package or class, is is a trait, so its members can't be imported. You need to import from the specific class extending the trait.

In this case the specific class is CeeParser so the type of val should be CeeParser.Parser[CeeExpr]:

val parser : CeeParser.Parser[CeeExpr]
Nick Fortescue
It's also possible to refer to the nested class using the syntax `scala.util.parsing.combinator.Parsers#Parser[CeeExpr]`. Nested types in scala are *path dependent* (meaning that the nested type is different for each *instance* of the outer type). The `#` syntax gets around this.
Ben Lings
This has nothing to do with the traitness of it. It would give the same problem if it were a class.
Daniel
@Daniel is this true? I should try it. I thought if Parser was a class, then surely CeeParser.Parser would be an instanceof Parsers.Parser, so the import would work.
Nick Fortescue
@Nick An import of `CeeParser` works, an import of `Parsers` doesn't. A class is not a package nor an object. You _cannot_ import things from it, only from instances of it. It's not that your solution isn't correct, is just that class/trait doesn't have anything to do with it.
Daniel
+2  A: 

The problem is that Parser is a subclass of Parsers, so the proper way to refer to it is from an instance of Parser. That is, CeeParser.Parser is different from any other x.Parser.

The correct way to refer to the type of CeeParser.token is CeeParser.Parser.

Daniel