尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

RTK 命令词法分析器设计:discover 模块 lexer 是怎么写的(完整解析)

RTK 命令词法分析器设计:discover 模块 lexer 是怎么写的(完整解析) RTK 命令词法分析器设计discover 模块 lexer 是怎么写的完整解析【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtkRTK 是一个用单个 Rust 二进制实现的 CLI 代理能把常见开发命令的 LLM Token 消耗降低 60-90%。它的安全核心之一就是 src/discover/lexer.rs 里那个不到 300 行的命令词法分析器lexer——本文带你拆解它的设计思路。为什么要为命令写一个词法分析器RTK 的工作方式AI Agent 每执行一条命令hook 都会先经过rtk rewrite判断要不要改写。而 Agent 发来的常常不是简单命令而是复合命令cargo fmt --all cargo test 21 | tail -20如果简单地用空格或字符串切割就会翻车——比如这条提交信息里就藏着git commit -m fix update字符串级切割会把一条命令错误地劈成两段。所以 RTK 选择了一个朴素但可靠的方案单遍扫描的状态机词法分析器一次遍历把命令拆成带类型、带位置的 Token 流。核心设计5 种 Token 字节偏移量整个分析器只有 5 种 Token 类型src/discover/lexer.rs#L10-L23Token 类型含义例子Arg普通参数含引号内容git、fix updateOperator连接符、||、;Pipe管道区分\|和\|cat \| grepRedirect重定向含文件描述符21、、Shellism需 Shell 才能解释的构造$()、反引号、*、()每个 Token 还记录一个关键字段——offset字节偏移。这个设计看似不起眼却是下游所有按 Token 切割原命令功能的基础不需要重新解析直接用偏移量就能从原始字符串里切出每一段。一次 tokenization 的完整效果cargo test 21 git status → [Arg(cargo), Arg(test), Redirect(21), Operator(), Arg(git), Arg(status)]状态机怎么转引号、转义与特殊字符主循环在 tokenize_inner 中用三个小状态撑起整个识别逻辑escaped转义态遇到\且不在单引号内下一个字符原样并入当前参数——所以hello\ world是一个词而单引号里的\n保持字面量quote引号态进入或后所有、|、空格都变成普通字符直到遇到配对引号关闭。这正是fix update不被误切的原因current攒词缓冲普通字符不断拼入缓冲遇到空白/操作符时由 flush_arg 一次性提交为一个Arg。⚠️ 最容易翻车的两个歧义点RTK 都做了专门处理|一个字符三种命运紧跟|是逻辑或紧跟是 stderr 管道|否则才是普通管道|lexer.rs#L124-L152同理是连接符是重定向单独才标记为后台运行Shellism。重定向把多字符原子当一个 Token21必须在词法层面就是一个原子否则后面剥离重定向、改写命令、再拼回去的策略见 src/discover/README.md根本无法实现。词法分析器为此做了细节处理出现时会回看缓冲区——如果前面紧贴的是纯数字2、1就把文件描述符和合并成2再往后贪婪吞掉、、数字最终产出21、、这类完整 Token。21和/dev/null这类无文件写入的重定向还会被豁免出安全检查见下文。从 Token 到分段两种切分策略Token 流是原料真正干活的是两个切分函数split_on_operators服务命令改写split_on_operators 只在Operator和Pipe处切段并支持stop_at_pipe参数——只保留第一个管道左侧的段。原因很简单管道右侧是消费上游输出的改写它会破坏语义所以 RTK 的改写引擎只动管道左边的命令。split_for_permissions服务安全审查split_for_permissions 更严格除了、||、;还会在换行、后台、子 shell(...)处切分并在每段的第一个重定向处截断。配合tokenize_with_newlines引号外的换行输出为 Operator Token可以安全地按行处理多行命令。安全层哪些命令不可证明词法分析器还兼任第一道安全防线contains_unattestable_construct 借助 Token 流识别权限门无法拆解的构造——命令替换.../$(...)、进程替换(...)以及真正写文件的重定向 /tmp/x、 ~/.bashrc。它同样尊重引号语义单引号里的$(rm -rf ~)是字面量不会误报而双引号里的命令替换在 bash 中会执行所以照样拦截。这些行为都被文件末尾 800 多行的测试用例lexer.rs#L496逐一锁定包括-关闭描述符、/dev/null与后台的区分等边缘场景。它被谁调用调用方用途命令改写引擎按Operator/Pipe切分复合命令逐段改写热路径每条 Agent 命令都经过rtk discover复用同一套 Token 化逻辑分析历史会话找出本可改写却没改写的命令权限检查src/hooks/split_for_permissions逐段审查 contains_unattestable_construct拦截危险构造hook 入口更轻量的 shell_split 做带引号感知的简单切词分类规则本身与词法分析解耦匹配用的 60 条正则规则独立放在 src/discover/rules.rs新增改写规则时只改这一处词法层无需任何改动。总结这套设计的三个可取之处不造轮子也不引依赖——300 行手写状态机覆盖引号、转义、重定向、管道的核心语义足够支撑上层所有需求Token 带 offset——一次扫描、处处复用下游切段全靠偏移量切片零二次解析保守优先的安全边界——拿不准的构造Shellism宁可整段放行不自动批准也不做激进猜测。对新手来说这个文件也是学习词法分析器的好样例状态极少、职责单一且每个决策都有对应测试用例兜底。想深入全链路推荐阅读 src/discover/README.md 与 docs/contributing/TECHNICAL.md。【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表