ключевые слова и идентификаторы конфликтуют написание лексера?(Скала Либс) - PullRequest
0 голосов
/ 31 декабря 2018

Я пробовал fastparse, parboiled2 и scala-комбинаторы.Все они имеют эту проблему при определении LEXER:

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

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

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

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

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

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

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

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

0 голосов
/ 31 декабря 2018

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

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
}
...