跳转至

Mini Bash Parser

从 4436 行的 src/utils/bash/bashParser.ts 提炼到 ~250 行的递归下降 parser。 支持 简单命令 / pipe / &&/|| / if-else / while / for-in / 函数定义 / 变量赋值 / 重定向

文件

mini-bash-parser/
├── src/
│   ├── types.ts       AST 节点类型
│   ├── lexer.ts       Lexer(~110 行)
│   ├── parser.ts      递归下降 parser(~180 行)
│   └── cli.ts         CLI 入口
└── README.md

npm install && npm start
# 或传参数
node dist/cli.js "cat foo | grep bar | wc -l"
node dist/cli.js "if [ -f x ]; then echo yes; else echo no; fi"
node dist/cli.js "for x in a b c; do echo \$x; done"
node dist/cli.js "foo() { echo hi; }"

真实代码对照

Demo 真实文件 简化
src/lexer.ts bashParser.ts:200 Tokenizer (~295 行) 不处理 heredoc / ANSI-C quoting / locale
src/parser.ts bashParser.ts:300 parseProgram (~2000 行) 不处理 array / subshell / process substitution / brace expansion
src/types.ts bashParser.ts:TsNode (~400 行) 简化 AST 节点(去掉 span / metadata)

优先级(从低到高)

program      ← parseProgram()
├─ andOr     ← parseAndOr()  → ; 是语句分隔
│  ├─ pipe   ← parsePipeline()  → | 是管道
│  │  └─ command  ← parseCommand() / parseIf / parseWhile / parseFor / parseFunction
│  └─ (&&/||)
└─ (next andOr)

核心 4 件套

1️⃣ Lexer 状态机

按字符类型分发:; | & ( ) { } > < → 单字符 token;' " → 字符串;其他 → 单词。

2️⃣ 关键字 vs 单词

if then fi 等 13 个关键字独立 token type,parser 走 expect("keyword", "if") 强校验。

3️⃣ 递归下降 = 函数即规则

每个语法规则对应一个 parseXxx() 函数,函数互相调用,优先级靠调用顺序(先调 = 优先级低)。

4️⃣ Token lookahead = 1

peek() 一个 token;遇到分叉用 check() 判断后 advance()。真实 bashParser 支持 k=2~3 lookahead。

支持的语法

  • ls -la /tmp (command + args + redirect)
  • cat foo | grep bar | wc -l (pipeline)
  • cmd1 && cmd2 || cmd3 (logical op)
  • a; b; c (sequence)
  • if [ -f x ]; then cmd; else cmd; fi (if/else)
  • while [ -n "$x" ]; do ...; done (while)
  • for x in a b c; do ...; done (for-in)
  • foo() { echo hi; } (function)
  • VAR=value command (assignment,简化版)
  • ❌ heredoc / array / subshell / glob expansion

进阶练习

  1. case 语句case $x in a) ... ;; esac
  2. [[ ]] test 表达式(带 && || 短路)
  3. (( )) 算术(C 风格表达式)
  4. 加 arrayarr=(1 2 3) / ${arr[0]}
  5. 加 span 位置(每个 AST 节点带 start / end 位置,便于报错定位)

相关阅读