python Lark教程 1)简介与安装
1.1 为什么需要 Lark?
在编程世界里,解析(parsing)是一个基础而又关键的主题。无论是编译器、解释器、配置文件解析器,还是数据格式转换工具,都离不开“将文本转化为结构化数据”的过程。
传统上,我们可能会使用正则表达式来完成解析任务。但随着需求复杂化,正则表达式逐渐力不从心。例如:
- 当需要解析嵌套结构(如 JSON、XML、HTML)时,正则难以应对。
- 当语法规则具有递归特性(例如括号匹配、函数调用嵌套)时,正则表达式显得笨拙。
- 当需要进行语义分析(如表达式求值、编程语言的编译)时,正则更无法胜任。
于是,专门的解析工具和库应运而生。Python 生态里有不少选择,比如 PLY、pyparsing、ANTLR 的 Python 接口等。而 Lark 则是近年来备受欢迎的一款解析库。
Lark 的优势:
- 简洁:语法定义接近 EBNF 标准,易读易写。
- 强大:支持 Earley、LALR 等算法,能处理几乎所有上下文无关语法。
- 灵活:能输出解析树(Parse Tree),并可通过 Transformer 转换为语义树(AST)。
- 现代:支持 Python 3.x,性能优化合理,API 友好。
- 跨场景:可用来编写 DSL、编译器前端、数据解析器、甚至聊天机器人语言解释器。
换句话说,如果你需要在 Python 里写一个语法解析器,Lark 是极佳的选择。
1.2 Lark 能做什么?
举几个典型的应用场景,让你快速感受 Lark 的能力:
-
算术表达式解析与求值
- 输入:
1 + 2 * (3 + 4) - 输出:解析树 → AST → 结果
15
- 输入:
-
配置文件解析
-
输入:
[database] host = localhost port = 3306 -
Lark 可以轻松定义一个语法来读取并转化为 Python 字典。
-
-
DSL(领域专用语言)
-
例如编写一个简化版的 SQL 子集解析器:
SELECT name, age FROM users WHERE age > 18 -
经过 Lark 解析后,可以直接生成查询语法树,供后端执行。
-
-
自定义编程语言
- 许多学习编译原理的同学,会使用 Lark 来构建自己的“小语言”。
💡 小贴士:
如果你曾经在大学里学过《编译原理》,可能对“词法分析器”“语法分析器”这些术语印象深刻。Lark 就是一个帮你把“语法分析器”写出来的工具,而无需你手写复杂的递归下降代码。
1.3 Lark 的解析算法
Lark 内置了多种解析算法,最常用的有两种:
-
Earley 算法
- 功能最强大,能处理所有上下文无关语法(包括有二义性的语法)。
- 适合写通用解析器,如自然语言或复杂的 DSL。
- 但性能相对一般。
-
LALR(1) 算法
- 功能稍弱,但能覆盖绝大多数编程语言语法。
- 速度快,适合高性能需求。
在使用 Lark 时,可以通过参数指定解析算法,例如:
from lark import Lark
grammar = """
start: "hello" NAME
NAME: /[a-zA-Z_][a-zA-Z0-9_]*/
"""
parser = Lark(grammar, parser="earley")
print(parser.parse("hello world"))
1.4 安装 Lark
安装 Lark 非常简单,可以直接使用 pip:
pip install lark
如果你想使用最新的开发版本,可以从 GitHub 安装:
pip install git+https://github.com/lark-parser/lark
安装完成后,你可以在 Python 中尝试:
import lark
print(lark.__version__)
如果能正常输出版本号,说明安装成功。
1.5 第一个 Lark 程序
我们来写一个最简单的 Lark 示例:解析算术表达式。
语法定义
from lark import Lark
grammar = """
start: expr
?expr: expr "+" term -> add
| expr "-" term -> sub
| term
?term: term "*" factor -> mul
| term "/" factor -> div
| factor
?factor: NUMBER
| "(" expr ")"
%import common.NUMBER
%import common.WS
%ignore WS
"""
parser = Lark(grammar, parser="lalr")
在这个语法中:
start是入口规则。expr定义了加减法。term定义了乘除法。factor定义了数字和括号。%import表示引入内置的通用规则。%ignore WS表示忽略空格。
解析与输出
tree = parser.parse("1 + 2 * (3 + 4)")
print(tree.pretty())
输出结果为:
add
NUMBER 1
mul
NUMBER 2
add
NUMBER 3
NUMBER 4
这就是一个标准的 解析树。
1.6 从解析树到计算结果
解析树只是结构信息,如果我们想计算结果,需要定义一个 Transformer。
from lark import Transformer
class CalculateTree(Transformer):
def add(self, items):
return items[0] + items[1]
def sub(self, items):
return items[0] - items[1]
def mul(self, items):
return items[0] * items[1]
def div(self, items):
return items[0] / items[1]
def NUMBER(self, items):
return float(items)
calc = CalculateTree()
result = calc.transform(tree)
print(result)
运行结果:
15.0
至此,我们就用 Lark 实现了一个 迷你计算器。
💡 小贴士:
这里的Transformer相当于“语义分析”的过程,把纯粹的结构树转化为有意义的操作。你也可以用它来生成字节码、SQL 语句、甚至机器学习模型的中间表示。
1.7 Lark 与正则的比较
很多初学者会问:我用正则表达式不也能做解析吗?为什么要用 Lark?
我们来对比一下。
用正则解析算术表达式
假设要匹配 1 + 2 * (3 + 4),正则的复杂度非常高,而且要处理括号嵌套基本不可能。
用 Lark
只需要清晰的语法规则,就能自然地解析括号嵌套。
换句话说:
- 正则适合小任务:匹配 Email、URL、简单格式化。
- Lark 适合大任务:编程语言、DSL、复杂文件格式。
1.8 Lark 的内置工具
Lark 提供了不少便利的内置工具:
-
通用 Token
NUMBER、WORD、WS等常见正则模式直接可用。
-
调试工具
tree.pretty():输出可视化的解析树。parser.parse_interactive():逐步解析,方便调试复杂语法。
-
Error Handling
- 可以捕获
UnexpectedInput异常,提供语法错误提示。
- 可以捕获
1.9 小结
在本章中,我们学习了:
- Lark 的基本概念与优势。
- 如何安装并验证 Lark。
- 使用 Lark 定义最简单的语法。
- 如何将文本解析为解析树,并进一步转化为有意义的结果。
- Lark 与正则的区别与优势。
更多推荐


所有评论(0)