FParsec标识符与关键字

Han*_*ans 4 f# parser-combinators fparsec

对于具有关键字的语言,需要一些特殊的技巧来防止例如"if"被解释为标识符,并且"ifSomeVariableName"变为关键字"if",后跟标识符流中的标识符"SomeVariableName".

对于递归下降和Lex/Yacc,我简单地采用了在词法分析器和解析器之间转换令牌流的方法(根据有用的指令).

然而,FParsec似乎并没有真正做一个单独的词法分析步骤,所以我想知道处理这个问题的最佳方法是什么.说到,似乎Haskell的Parsec支持lexer层,但FParsec不支持?

byt*_*ter 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
Run Code Online (Sandbox Code Playgroud)

上面的代码将解析关键字或标识符两次.或者,要修复它,您可以:

  1. 解析整个单词([a-z][A-Z]+[a-z][A-Z][0-9]+),例如所有字母数字;
  2. 检查它是否是关键字或标识符(小写并且属于字典)和其中之一
    1. 返回关键字
    2. 返回一个标识符

PS如果不破坏逻辑,不要忘记首先订购"更便宜"的解析器.