Проблемы синтаксического анализатора Scala

самый простой путем является анонимный метод, переданный в Label.Invoke :

// Running on the worker thread
string newText = "abc";
form.Label.Invoke((MethodInvoker)delegate {
    // Running on the UI thread
    form.Label.Text = newText;
});
// Back on the worker thread

Уведомление, что Invoke выполнение блоков, пока это не завершается - это - синхронный код. Вопрос не спрашивает об асинхронном коде, но существует много из содержание на Переполнении стека о написании асинхронного кода, когда Вы хотите узнать об этом.

5
задан ShaunL 28 August 2009 в 16:30
поделиться

2 ответа

Вы на правильном пути. В вашем парсере есть несколько проблем. Я отправлю исправленный код и объясню изменения.

import scala.util.parsing.combinator._
import scala.util.parsing.combinator.syntactical._

case class Book (name: String, isbn: String) {
  def niceName = name + " : " + isbn
}


object BookParser extends StandardTokenParsers {
  lexical.reserved += ("book","has","isbn")

  def bookSpec: Parser[Book]  = "book" ~ ident ~ "has" ~ "isbn" ~ ident ^^ {
            case "book" ~ name ~ "has" ~ "isbn" ~ isbn => new Book(name, isbn) }

  def parse (s: String) = {
    val tokens = new lexical.Scanner(s)
    phrase(bookSpec)(tokens)
  }

  def test (exprString : String) = {
     parse (exprString) match {
       case Success(book, _) => println("Book: " + book.niceName)
       case Failure(msg, _) => println("Failure: " + msg)
       case Error(msg, _) => println("Error: " + msg)
     }
  }

  def main (args: Array[String]) = {
     test ("book ABC has isbn DEF")
  }   
}

1. Возвращаемое значение анализатора

Чтобы вернуть книгу из синтаксического анализатора, вам нужно оказать некоторую помощь модулю вывода типов. Я изменил определение функции bookSpec на явное: она возвращает Parser [Book]. То есть он возвращает объект, который является парсером для книг.

2. stringLit

Используемая вами функция stringLit взята из трейта StdTokenParsers. stringLit - это функция, которая возвращает Parser [String], но соответствующий ей шаблон включает двойные кавычки, которые большинство языков используют для ограничения строкового литерала. Если вам нравятся слова в двойных кавычках в вашем DSL, то stringLit - это то, что вам нужно. В интересах простоты я заменил stringLit на идент. Идентификатор ищет идентификатор языка Java. Это не совсем подходящий формат для номеров ISBN, но он прошел ваш тестовый пример. : -)

Чтобы правильно сопоставить ISBN, я думаю, вам нужно будет использовать выражение регулярного выражения вместо идентификаторов.

3. Ignore-left sequence

Ваш сопоставитель использовал строку ~> объединителей. Это функция, которая принимает два объекта Parser [_] и возвращает Parser, который распознает их последовательно, а затем возвращает результат в правой части. Используя целую цепочку из них, чтобы привести к вашему последнему stringLit, ваш синтаксический анализатор проигнорирует все, кроме последнего слова в предложении. Это означает, что имя книги также будет удалено.

Кроме того, когда вы используете ~> или <~, игнорируемые токены не должны появляться в вашем сопоставлении с образцом.

Для простоты, Я изменил их все на простые функции последовательности и оставил дополнительные токены в сопоставлении с образцом.

4. Сопоставление результатов

Метод тестирования должен сопоставить все возможные результаты функции parse (). Итак, я добавил случаи Failure () и Error (). Кроме того, даже Success включает как возвращаемое значение, так и объект Reader. Нас не заботит читатель, поэтому я просто использовал "_", чтобы игнорировать его при сопоставлении с образцом.

Надеюсь, это поможет!

15
ответ дан 18 December 2019 в 07:30
поделиться

Когда вы используете ~> или <~ , вы отбрасываете элемент, от которого исходит стрелка. Например:

"book" ~> stringLit // discards "book"
"book" ~> stringLit ~> "has" // discards "book" and then stringLit
"book" ~> stringLit ~> "has" ~> "isbn" // discards everything except "isbn"
"book" ~> stringLit ~> "has" ~> "isbn" ~> stringLit // discards everything but the last stringLit

Вы можете написать это так:

def bookSpec: Parser[Book] = ("book" ~> stringLit <~ "has" <~ "isbn") ~ stringLit ^^ {
  case name ~ isbn => new Book(name,isbn) 
}
6
ответ дан 18 December 2019 в 07:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: