Scala Parser在<init> </init>上失败

时间:2011-03-22 19:44:04

标签: parsing scala

修改:我可以通过在MessageParser类中将val更改为lazy val来解决此问题。我忘记了我之前使用def而不是val.对其进行了测试。有人能说清楚为什么这个更改会修复它吗?

所以,我目前正在编写一个IRC服务器。我决定使用Scala的Combinator Parser库来帮助我解析消息。我已经能够通过测试程序正确地解析消息了,但是当我尝试将我的解析器合并到我已经写过的echo服务器时,我在连接到服务器时收到以下错误消息:

Connected to the target VM, address: '127.0.0.1:55567', transport: 'socket'
Exception in thread "main" java.lang.ExceptionInInitializerError
    at IRCServer.main(IRCServer.scala)
Caused by: java.lang.NullPointerException
    at messages.MessageParser.<init>(MessageParser.scala:11)
    at net.Connection.<init>(Connection.scala:14)
    at net.Server.start(Server.scala:14)
    at IRCServer$.<init>(IRCServer.scala:12)
    at IRCServer$.<clinit>(IRCServer.scala)
    ... 1 more
Disconnected from the target VM, address: '127.0.0.1:55567', transport: 'socket'

Connection类处理从ServerSocket

创建的侦听器Socket
class Connection(socket: Socket) extends Thread {
    private val out = new PrintStream(socket.getOutputStream)
    private val in  = new BufferedReader(new InputStreamReader(socket.getInputStream))
    private val parser = new MessageParser
    override def run(): Unit = {
        var line = ""
        while({(line = in.readLine); line != null}) {
            Console.println("received: " + line)
            parser.parseLine(line.trim)
            out.println("out: " + line)
        }
    }

}

以下是我的MessageParser:

class MessageParser extends JavaTokenParsers {
    def parseLine(line :CharSequence) = {
        parseAll(message, line)
    }

    val message: Parser[Any] = opt(":"~prefix)~command~opt(params) ^^ (x=> {println("message: "+x)})
    val prefix: Parser[Any] = nick~"!"~user~"@"~host | servername ^^ (x=> {println("prefix: " +x)})
    val nick: Parser[Any] = letter~rep(letter | wholeNumber | special) ^^ (x=> {println("nick: " +x)})
    val special: Parser[Any] = "-" | "[" | "]" | "\\" | "`" | "^" | "{" | "}" ^^ (x=> {println("special: " +x)})
    val user: Parser[Any] = """[^\s@]+""".r ^^ (x=> {println("user: " +x)})
    val host: Parser[Any] = """[\w\.]+\w+""".r ^^ (x=> {println("host: " +x)})
    val servername: Parser[Any] = host ^^ (x=> {println("servername: " +x)})
    val command: Parser[Any] = """([A-Za-z]+)|([0-9]{3})""".r ^^ (x=> {println("command: " +x)})
    val params: Parser[Any] = rep(param)~opt(":"~tail) ^^ (x=> {println("params: " +x)})
    val param: Parser[Any] = """[^:][\S]*""".r
    val tail: Parser[Any] = """.*$""".r ^^ (x=> {println("tail: " +x)})
    val letter: Parser[Any] = """[A-Za-z]""".r ^^ (x=> {println("letter: " +x)})
}

我不太确定是什么原因引起的。希望我只是对一些小事视而不见。

2 个答案:

答案 0 :(得分:3)

根据需要填充

lazy val个值; val值将按您指定的顺序填充。使用解析器,较早的条目引用后来尚不存在的条目。所以他们最好是lazy valdef(哪一个取决于解析器; packrat解析器喜欢lazy val,而其他人通常假设def,但我是不确定他们是否需要它。)

答案 1 :(得分:0)

使用以下代码捕获异常:

try {
    //your code here
} catch {
    case err: ExceptionInInitializerError => err.getCause.printStackTrace
}

这将帮助您找到异常的原因。