尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

从零构建Calculator解析器:syntax从词法到语法的4步实战

从零构建Calculator解析器:syntax从词法到语法的4步实战 从零构建Calculator解析器syntax从词法到语法的4步实战【免费下载链接】syntaxSyntactic analysis toolkit, language-agnostic parser generator.项目地址: https://gitcode.com/gh_mirrors/sy/syntaxsyntax 是一个语言无关的解析器生成器Syntactic analysis toolkit它实现了 LR 与 LL 两套经典语法分析算法能把你手写的词法规则和 BNF 语法定义一键编译成 JavaScript、Python、PHP、Ruby、C#、Rust、Java、Julia 等 8 种语言的解析器模块。这篇文章以一个 Calculator计算器为例带你走完从词法分析到语法解析的 4 步实战全程只需几行配置就能让解析器正确算出2 2 * 2 6✅ 先认识一下 syntax 能做什么两种解析模式LRLR0/SLR1/LALR1/CLR1与 LL(1)解析算法核心代码在src/lr/与src/ll/目录下多语言代码生成解析表计算与代码生成解耦每种目标语言由一个插件负责见src/plugins/内置词法器基于正则的词法规则自动生成 tokenizer并自动捕获行号、列号等位置信息冲突检测--validate选项能自动报出移进-归约冲突并给出解决建议️ 第 1 步一键安装准备开发环境最简单的方式是通过 npm 安装 CLI 工具npm install -g syntax-cli syntax-cli --help也可以从源码构建适合贡献代码或二次开发git clone https://gitcode.com/gh_mirrors/sy/syntax cd syntax npm install npm run build构建完成后即可执行./bin/syntax --help看到帮助信息说明环境就绪。 第 2 步编写词法语法 —— 教解析器认识每个词词法语法lex负责把原始文本切分成 token。每条规则就是一个正则表达式 返回的 token 类型官方示例 examples/calc-eval.g 中的核心部分如下lex: { rules: [ [\\s, /*skip whitespace*/], [[0-9], return NUMBER], [\\, return ], [\\*, return *], [\\(, return (], [\\), return )] ] }几个关键要点空白符规则不 return表示跳过yytext变量可访问匹配到的原文如把123转成数字生成后的 tokenizer 还会自动记录每个 token 的startLine、startColumn等位置信息方便后续做错误提示。写完词法规则后可以先单独验证切分效果./bin/syntax --lex my.lex --tokenize -p 2 5你会看到一段 JSON2被识别为NUMBER被识别为加号 token——词法这一关就通过了 第 3 步编写语法 —— BNF 规则 算符优先级词法之后是语法语法bnf用 BNF 描述表达式的结构。同一个示例里的语法规则是bnf: { e: [ [e e, $$ $1 $3], [e * e, $$ $1 * $3], [( e ), $$ $2], [NUMBER, $$ Number(yytext)] ] }$$是该规则的归约结果$1、$3是右侧各符号的值——这就是典型的语法导向翻译SDT解析的同时直接完成计算。⚠️ 新手最常踩的坑2 2 2会产生移进-归约冲突。解决方法是为算符声明优先级与结合性%left、%right、%nonassocoperators: [ [left, ], [left, *], ]声明顺序即优先级*写在后面所以2 2 * 2会正确解析为2 (2 * 2) 6。如果拿不准用--validate让 syntax 帮你检查冲突并给出修复建议。⚙️ 第 4 步生成解析器 —— 一条命令多语言输出解析器的目标语言由输出文件后缀自动决定这是 syntax 语言无关设计的精髓# 生成 JavaScript 解析器 ./bin/syntax -g examples/calc-eval.g -m lalr1 -o calc-parser.js # 同样一份语法换后缀就是其他语言 ./bin/syntax -g examples/calc.py.g -m lalr1 -o calcparser.py生成的模块可以直接 require/import 使用const CalcParser require(./calc-parser); CalcParser.parse(2 2 * 2); // 6每种语言的实现由src/plugins/下对应的插件模板驱动比如 Python 模板位于src/plugins/python/templates/Rust 插件说明见src/plugins/rust/README.md。如果只是想快速验证语法而不生成文件还能直接干跑一次解析./bin/syntax -g examples/calc-eval.g -m lalr1 -p 2 2 * 2 # 输出6想对比不同模式的效果可以看看项目自带的三份计算器语法LR 左递归版examples/calc.slr1、直接求值版examples/calc-eval.g、LL(1) 左因子化版examples/calc.ll1对照着读一遍收获很大。 实战小结步骤做什么关键命令/配置1. 环境安装工具链npm install -g syntax-cli2. 词法定义 lex 正则规则--tokenize验证切分3. 语法写 BNF 声明优先级--validate检查冲突4. 生成输出多语言解析器-m lalr1 -o 文件名新手建议优先使用最实用的--mode lalr1遇到冲突先声明优先级而不是改解析模式写词法规则时善用yytext和位置信息能让错误提示更友好。更多细节可以阅读项目根目录的README.md以及语法格式说明所在的src/grammar/grammar.js。四步走完你已经拥有了一个能嵌入自己项目的迷你编译器前端完全可以用同样的方法去构建配置语言、表达式引擎或 DSL 解析器 【免费下载链接】syntaxSyntactic analysis toolkit, language-agnostic parser generator.项目地址: https://gitcode.com/gh_mirrors/sy/syntax创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表