ключевые слова и идентификаторы конфликтуют при написании лексера? (скала-библиотеки)

Я пробовал fastparse, parboiled2 и scala-combinators. У них всех есть эта проблема при определении LEXER:

LET_KEYWORD ::= "let"
IDENTIFIER  ::= "[a-zA-Z]+".r

Когда я запускаю их на входе "leto", они производят [LET_KEYWORD,IDENTIFIER(o)].

Я ожидаю, что некоторые из этих библиотек дадут мне такое поведение:

если ввод равен "let", то двусмысленность устраняется путем выбора первого определенного правила, потому что оно более актуально. если на входе "leto", то двусмысленности нет и выдается только IDENTIFIER(leto). Это поведение описано здесь, в ANTLR


person Alejandro Navas    schedule 31.12.2018    source источник


Ответы (2)


Вот фрагмент моего кода

val identifierOrKeyword = letter ~ rep(letter | digit | '_') ^^ {
  case x ~ xs =>
    val ident = x :: xs mkString ""
    keyword.getOrElse(ident.toLowerCase, IDENTIFIER(ident))
}

keyword — это сопоставление строки с токеном.

Используемые определения:

sealed trait SqlToken
object SqlToken {
  case class IDENTIFIER(value: String) extends SqlToken
  case object LET extends SqlToken
}

val keyword = Map(
    "let" -> LET
}
person talex    schedule 31.12.2018

Ваша ситуация не сравнима с ситуацией ANTLR, в которой лексер ставится перед парсером. В этой ситуации вы видите, что самое длинное правило сопоставления лексера имеет приоритет просто потому, что оно выполняется первым, создавая единственный токен, который затем может использовать синтаксический анализатор.

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

Я предполагаю, что порядок правил в исходном коде не имеет отношения к этим технологиям, вам придется где-то использовать декларативный упорядоченный выбор (не |) или переписать грамматику, чтобы она больше не была двусмысленной.

person Jurgen Vinju    schedule 31.12.2018
comment
На самом деле я ставлю лексер перед парсером. Разрешить ему производить последовательность токенов, независимо от их порядка. Но если я получу leto, я хочу, чтобы он производил только один токен Identifier. - person Alejandro Navas; 31.12.2018
comment
Тогда вы могли бы заставить самый длинный матч, максимальный жевать. поведение от лексера? С Новым годом кстати - person Jurgen Vinju; 01.01.2019
comment
Некоторые лексеры всегда предпочитают литералы ключевых слов идентификаторам, некоторые принимают порядок правил как объявление приоритета. - person Jurgen Vinju; 01.01.2019