5

キーワードを含む言語の場合、たとえば「if」が識別子として解釈されないようにし、「ifSomeVariableName」がトークンストリームでキーワード「if」の後に識別子「SomeVariableName」になるのを防ぐために、特別なトリックが必要です。

再帰下降とLex/Yaccについては、レクサーとパーサーの間でトークンストリームを変換するというアプローチを(役立つ指示に従って)単純に採用しました。

ただし、FParsecは実際には別のレクサーステップを実行していないように見えるので、これに対処するための最良の方法は何であるか疑問に思います。と言えば、HaskellのParsecはレクサーレイヤーをサポートしているようですが、FParsecはサポートしていませんか?

4

2 に答える 2

6

この問題は非常に単純だと思います。答えはあなたがしなければならないということです:

  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

上記のコードは、キーワードまたは識別子を2回解析します。または、修正するには、次のようにします。

  1. 単語全体([a-z][A-Z]+[a-z][A-Z][0-9]+)を解析します。たとえば、すべて英数字です。
  2. それがキーワードまたは識別子(小文字で辞書に属している)であるかどうかを確認し、
    1. キーワードを返す
    2. 識別子を返す

PSロジックを台無しにしない場合は、最初に「安価な」パーサーを注文することを忘れないでください。

于 2012-12-19T11:48:08.890 に答える
0

空白のパーサーを定義し、キーワードまたは識別子の後にそれが続くかどうかを確認できます。たとえば、いくつかの一般的な空白パーサーは次のようになります

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

これには少なくとも1つの空白が必要です

let ws1 = skipMany1 pWhiteSpace

その後、次のようになります

let pIf = pstring "if" .>> ws1
于 2012-04-11T05:09:53.943 に答える