Идентификаторы FParsec и ключевые слова - PullRequest
3 голосов
/ 19 марта 2012

Для языков с ключевыми словами должен быть какой-то особый трюк, чтобы не допустить, например, «если» интерпретироваться как идентификатор, а «ifSomeVariableName» стать ключевым словом «если», за которым следует идентификатор «SomeVariableName» в потоке токенов.

Для рекурсивного спуска и Lex / Yacc я просто воспользовался подходом (согласно полезной инструкции) преобразования потока токенов между лексером и анализатором.

Однако FParsec на самом деле некажется, сделайте отдельный шаг лексера, поэтому мне интересно, как лучше всего с этим справиться.Говоря о том, что, похоже, Parsec Haskell поддерживает слой лексера, а FParsec нет?

Ответы [ 2 ]

5 голосов
/ 19 декабря 2012

Я думаю, эта проблема очень проста.Ответ таков:

  1. Разбор всего слова ([a-z]+), только нижний регистр;
  2. Проверьте, принадлежит ли оно словарю;если это так, верните keyword;в противном случае синтаксический анализатор отступит;
  3. Разбор identifier отдельно;

Например (просто гипотетический код, не проверенный):

let keyWordSet =
    System.Collections.Generic.HashSet<_>(
        [|"while"; "begin"; "end"; "do"; "if"; "then"; "else"; "print"|]
    )
let pKeyword =
   (many1Satisfy isLower .>> nonAlphaNumeric) // [a-z]+
   >>= (fun s -> if keyWordSet.Contains(s) then (preturn x) else fail "not a keyword")

let pContent =
    pLineComment <|> pOperator <|> pNumeral <|> pKeyword <|> pIdentifier

Приведенный выше код проанализирует ключевое слово или идентификатор дважды.Чтобы исправить это, вы также можете:

  1. Разобрать все слово ([a-z][A-Z]+[a-z][A-Z][0-9]+), например, все буквы и цифры;
  2. Проверить, является ли это ключевое слово или идентификатор (нижний регистр)и принадлежность к словарю) и либо
    1. вернуть ключевое слово
    2. вернуть идентификатор

PS Не забудьте заказать "дешевле"сначала парсеры, если это не разрушает логику.

0 голосов
/ 11 апреля 2012

Вы можете определить синтаксический анализатор для пробела и проверить, следует ли за ним ключевое слово или идентификатор.Например, некоторый универсальный анализатор пробелов будет выглядеть как

let pWhiteSpace = pLineComment <|> pMultilineComment <|> pSpaces

, для этого потребуется как минимум один пробел

let ws1 = skipMany1 pWhiteSpace

, тогда если он будет выглядеть как

let pIf = pstring "if" .>> ws1
...