Я создаю 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 библиотеки комбинаторов парсеров, поэтому любые предложения о том, как создать определение языка со значительными новыми символами строки, также приветствуются.