Scala Parser не работает на <init> - PullRequest
0 голосов
/ 22 марта 2011

Редактировать: Мне удалось исправить это, изменив val на lazy val в классе MessageParser.Я забыл, что ранее я тестировал его, используя def вместо val. Может кто-нибудь прояснить, почему это изменение исправляет это?

Итак, я сейчас пишу IRC-сервер.Я решил использовать библиотеку Scala Combinator Parser, чтобы помочь мне разобрать сообщения.Мне удалось правильно проанализировать сообщение с помощью тестовой программы, но когда я попытался встроить свой синтаксический анализатор в эхо-сервер, который я уже написал, я получаю следующее сообщение об ошибке при установлении соединения с моим сервером:

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

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 ]

3 голосов
/ 22 марта 2011

lazy val значения заполняются по мере необходимости; val значения заполняются в указанном вами порядке. С парсером более ранние записи относятся к более поздним, которые еще не существуют. Так что лучше бы они были lazy val или def (что зависит от синтаксического анализатора; синтаксический анализатор packrat любит lazy val, в то время как другие обычно принимают def, но я не уверен, что они этого требуют).

0 голосов
/ 22 марта 2011

Перехватите исключение с помощью следующего кода:

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

Это поможет вам найти причину исключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...