самый простой путем является анонимный метод, переданный в 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
выполнение блоков, пока это не завершается - это - синхронный код. Вопрос не спрашивает об асинхронном коде, но существует много из содержание на Переполнении стека о написании асинхронного кода, когда Вы хотите узнать об этом.
Вы на правильном пути. В вашем парсере есть несколько проблем. Я отправлю исправленный код и объясню изменения.
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. Нас не заботит читатель, поэтому я просто использовал "_", чтобы игнорировать его при сопоставлении с образцом.
Надеюсь, это поможет!
Когда вы используете ~>
или <~
, вы отбрасываете элемент, от которого исходит стрелка. Например:
"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)
}