快速上手 gocc10 分钟创建你的第一个 BNF 语法文件并生成解析器【免费下载链接】goccParser / Scanner Generator项目地址: https://gitcode.com/gh_mirrors/go/goccgocc 是一款用 Go 语言编写的解析器生成器Parser / Scanner Generator。你只需写好一份 BNF 语法文件gocc 就能自动生成词法分析器lexer和 LR(1) 语法分析器parser再也不用手写一堆繁琐的解析代码。本文将从零开始带你用 10 分钟完成 gocc 安装、编写 BNF 语法文件、生成解析器并跑通测试新手也能快速掌握这门用语法换代码的高效技能。gocc 是什么新手为什么要学解析器生成器gocc 本质是一个编译器生成器Compiler Compiler你把语法规则写进 BNF 语法文件它帮你把词法分析器和语法分析器全部生成出来。它生成的词法分析器是能识别正则语言的 DFA支持 UTF-8 输入语法分析器是识别 LR(1) 语言的 PDA并且可以自动解决 shift/reduce 和 reduce/reduce 冲突。很多知名 Go 项目都在用它处理复杂文本格式例如 Graphviz DOT 语言解析、LLVM IR 解析等。学会 gocc意味着任何自定义语言、配置文件、DSL你都能自己快速实现。gocc 快速安装一条命令编译出命令行工具首先确保本机已安装 Go建议 1.20然后把 gocc 源码克隆到本地并编译安装git clone https://gitcode.com/gh_mirrors/go/gocc cd gocc go install安装完成后把$(go env GOPATH)/bin加入 PATH 环境变量执行gocc -h看到用法说明即代表安装成功。后续我们只需调用gocc xxx.bnf一个命令即可。编写 BNF 语法文件从一个计算器语法开始BNF 语法文件是整个流程的核心输入。以项目自带的计算器为例文件内容位于example/calc/calc.bnf分为词法部分和语法部分/* Lexical part */ _digit : 0-9 ; int64 : 1-9 {_digit} ; !whitespace : | \t | \n | \r ; /* Syntax part */ Calc : Expr; Expr : Expr Term $0.(int64) $2.(int64), nil | Term ; Term : Term * Factor $0.(int64) * $2.(int64), nil | Factor ; Factor : ( Expr ) $1, nil | int64 util.IntValue($0.(*token.Token).Lit) ;要点速记词法部分用引号字面量、a-z字符区间和{}重复来定义记号以!开头的规则会被忽略如空白符语法部分用:定义产生式|表示多个候选分支 ... 是语义动作SDT 规则$0、$1代表对应位置的语法符号值你可以在这里直接拼接出结果。完整的 BNF 语法规范见spec/gocc2.ebnf更多写法可参考example/bools/example.bnf。用 gocc 生成解析器一条命令自动产出五个包在存放calc.bnf的目录下执行gocc calc.bnfgocc 会自动生成lexer、parser、token、util、errors等 Go 包对应项目示例example/calc/下的目录结构。生成完毕直接go build ./...即可编译通过无需任何手工改动。如果你只需要语法分析、不需要词法分析例如输入已经由别的工具切分好可以加-no_lexer参数参考example/nolexer/。在 Go 代码中调用 gocc 生成的解析器生成之后调用方式非常简单——先创建 lexer再喂给 parser 解析。参考example/calc/calc_test.go的写法p : parser.NewParser() s : lexer.NewLexer([]byte(1 2 * 3)) sum, err : p.Parse(s)p.Parse返回的sum就是你 BNF 中语义动作算出的结果这里是7。如果语法错误会返回包含行列号的错误信息错误处理包在errors/目录中。运行测试验证你的解析结果在项目目录下执行go test -v ./...gocc 项目自带大量可运行示例每个示例都有测试文件。建议你逐个运行example/下的make regenerate重新生成解析器和go test跑测试亲眼看看 BNF 与生成代码之间的对应关系。gocc 常用命令行参数速查表参数作用-a自动解决 LR(1) 冲突-o 目录指定输出目录-p 包名指定生成的 Go 包名-no_lexer不生成词法分析器-debug_parser开启解析器调试日志-v输出详细过程含 LR(1) 项集-u允许存在不可达的产生式-zip压缩 action 表与 goto 表参数定义可查看源码internal/config/config.go。进阶玩法语义动作、AST 与更多内置示例构建 AST复杂项目建议用语义动作构造抽象语法树参考example/astx/、example/bools/ast/ast.go错误恢复想让解析器在出错后继续解析参考example/errorrecovery/自定义上下文通过$Context在解析时传递上下文数据如符号表参考example/usercontext/及其README.md冲突处理gocc 生成的 LR(1) 冲突报告与自动解决可对比example/sr/shift/reduce与example/rr/reduce/reduce两个示例调试利器加-v参数会输出LR1_sets.txt、first.txt、terminals.txt等中间文件帮你看清分析表的每一步。详细的原理与语法说明可阅读官方文档doc/gocc_user_guide.pdf源码为doc/gocc_user_guide.tex。总结gocc 让写一个自己的解析器从数周的苦工变成 10 分钟的小任务写好 BNF 语法文件 → 执行gocc→ 调用生成的解析器三步即可完成。无论你是想解析配置格式、做一个小型 DSL还是学习编译原理gocc 都是绝佳的起点。现在就打开example/calc/calc.bnf动手改一个属于自己的语法吧【免费下载链接】goccParser / Scanner Generator项目地址: https://gitcode.com/gh_mirrors/go/gocc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考