使用FsLexYacc实现词法分析器时如何获取全部token?
你当前的代码仅调用了一次Lexer.tokenize方法,因此只能返回首个token。FsLexYacc的词法分析器设计为每次调用tokenize方法时,从传入的LexBuffer中消费对应长度的字符、返回当前匹配的token,同时将LexBuffer的读取指针移动到下一个token的起始位置,因此你需要循环调用该方法直到命中输入结束标记,即可拿到完整的token序列。
修改后的代码示例
#load "../.paket/load/net5.0/FsLexYacc.Runtime.fsx" #load "./Domain.fs" #load "./Parser.fs" #load "./Lexer.fs" open System open System.IO open FSharp.Text open FSharp.Text.Lexing open Scripting let allTokens (input : string) = let lexBuffer = LexBuffer<char>.FromString input // 循环生成token序列 seq { while true do match Lexer.tokenize lexBuffer with // 此处的EOF请替换为你自己项目中定义的输入结束对应的token名称 | EOF -> yield EOF yield! Seq.empty | token -> yield token } // 如果需要直接返回列表,取消下面这行的注释即可 // |> List.ofSeq // 测试输出所有token printfn "%A" <| allTokens "1 + 1"
注意事项
- 请确保你的
Lexer.fsl词法规则文件中定义了输入结束的匹配规则,示例如下:| eof { EOF } - 如果你不需要在结果中包含结束标记EOF,可以使用如下实现:
let allTokensWithoutEOF (input : string) = let lexBuffer = LexBuffer<char>.FromString input Seq.unfold (fun _ -> let token = Lexer.tokenize lexBuffer if token = EOF then None else Some (token, ()) ) ()
修改后运行你的测试用例"1 + 1",就会输出完整的token列表:[NUMBER 1; PLUS; NUMBER 1; EOF](具体token名称以你自己的定义为准)。
内容的提问来源于stack exchange,提问作者sdgfsdh
相关产品推荐
相关产品推荐

