Я создаю DSL и использую библиотеку-комбайнер Scala для анализа DSL. DSL следует за простым, похожим на Ruby синтаксисом. Исходный файл может содержать ряд блоков, которые выглядят следующим образом:
create_model do
at 0,0,0
end
Окончания строк значительны для DSL, так как они эффективно используются в качестве терминаторов операторов.
Я написал парсер Scala, который выглядит так:
class ML3D extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
def model: Parser[Any] = commandList
def commandList: Parser[Any] = rep(commandBlock)
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"
def eol: Parser[Any] = """(\r?\n)+""".r
def command: Parser[Any] = commandName~opt(commandLabel)
def commandName: Parser[Any] = ident
def commandLabel: Parser[Any] = stringLiteral
def statementList: Parser[Any] = rep(statement)
def statement: Parser[Any] = functionName~argumentList~eol
def functionName: Parser[Any] = ident
def argumentList: Parser[Any] = repsep(argument, ",")
def argument: Parser[Any] = stringLiteral | constant
def constant: Parser[Any] = wholeNumber | floatingPointNumber
}
В связи с кончиками строк, я перевернул whiteSpace так, чтобы он обрабатывал пробелы и вкладки как пробельные символы (вместо того, чтобы обрабатывать новые строки как пробелы и, таким образом, игнорировать их).
Это работает, за исключением оператора "end" для commandBlock. Поскольку мой исходный файл содержит завершающую новую строку, синтаксический анализатор жалуется, что он ожидал только end, но получил новую строку после ключевого слова end.
Итак, я изменил определение commandBlock на следующее:
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"~opt(eol)
(То есть, я добавил дополнительную строку после "end" ).
Но теперь, когда синтаксический анализ исходного файла, я получаю следующую ошибку:
[4.1] failure: `end' expected but `' found
Я думаю, что это связано с тем, что после того, как он сосет его в завершающей новой строке, синтаксический анализатор встречает пустую строку, которая, по ее мнению, является недопустимой, но я не уверен, почему она это делает.
Любые советы о том, как это исправить? Я мог бы пропустить неправильный синтаксический анализатор из Scala библиотеки комбинаторов парсеров, поэтому любые предложения о том, как создать определение языка со значительными новыми символами строки, также приветствуются.