Ohm语法参考手册:解析表达式文法详解
引言
Ohm是一个基于解析表达式文法(PEG)的解析工具库,它提供了一种声明式的语法定义语言。本文将全面介绍Ohm语法系统的核心概念和语法结构,帮助开发者掌握如何编写高效的语法规则。
基础概念
语法规则基础
Ohm语法由一系列规则组成,每个规则定义了一种语法结构。规则分为两种类型:
- 语法规则(Syntactic Rules):名称以大写字母开头,会自动跳过空白字符
- 词法规则(Lexical Rules):名称以小写字母开头,不自动处理空白
Arithmetic {
Expr = "1 + 1" // 语法规则
number = digit+ // 词法规则
}
与PEG的关系
Ohm基于PEG但有以下重要区别:
- 严格区分大小写的规则命名
- 语法与语义动作分离
- 支持带名称的备选分支
- 支持参数化规则
- 支持面向对象的语法扩展
解析表达式详解
基本匹配单元
-
字面量匹配:使用双引号
"function" // 精确匹配"function"
-
转义字符:支持标准转义序列
"\"" // 匹配引号 "\n" // 匹配换行 "\u{1F600}" // 匹配😀表情
-
字符范围:
"a".."z" // 匹配任意小写字母 "0".."9" // 匹配数字
组合表达式
-
序列:按顺序匹配
"function" letter+ // 匹配"function"后跟字母
-
选择:尝试多个可能
"true" | "false" // 匹配true或false
-
重复:
digit+ // 1个或多个数字 letter* // 0个或多个字母
高级操作符
-
正向预查:匹配但不消耗输入
&"var" letter+ // 匹配以var开头的标识符
-
负向预查:
~"\n" any // 匹配非换行字符
-
词法化:在语法规则中禁用空白跳过
#(letter+) // 严格匹配连续字母
内置规则
Ohm提供了一系列常用规则:
any
:匹配任意Unicode字符letter
:匹配字母digit
:匹配数字(0-9)space
:匹配空白字符end
:匹配输入结束
参数化规则:
ListOf<digit, ","> // 匹配逗号分隔的数字列表
caseInsensitive<"ohm"> // 匹配不区分大小写的"ohm"
语法组织
规则定义方式
-
新建规则:
FunctionDecl = "function" ident "()"
-
覆盖规则:
ident := letter+ // 覆盖父语法中的ident规则
-
扩展规则:
keyword += "let" // 在原有关键字基础上添加let
参数化规则
Repeat<x> = x x x
Triple = Repeat<letter> // 等价于letter letter letter
语法继承
ExtendedGrammar <: BaseGrammar {
// 扩展或覆盖规则
}
语法与词法规则详解
空白处理机制
语法规则自动处理空白:
- 规则开始前跳过空白
- 序列元素间跳过空白
- 重复操作每次迭代前跳过空白
// 语法规则会自动处理空白
Array = "[" Elements "]" // 可以匹配"[ elements ]"
// 等效的词法规则需要显式处理
array = spaces "[" spaces elements spaces "]"
词法化操作
使用#
在语法规则中创建词法上下文:
// 要求冒号两边不能有空白
KeyValue = #ident ":" #value
最佳实践
-
命名规范:
- 语法规则使用PascalCase
- 词法规则使用camelCase
-
错误处理:
number (a numeric value) = digit+ // 提供描述便于错误提示
-
复杂结构:
FunctionDecl = "function" ident "(" ParamList? ")" ParamList = ident ("," ident)* -- multi | ident -- single
-
注释使用:
/* * 多行注释说明复杂规则 */ Expr = AddExpr | MulExpr // 注意运算优先级
总结
Ohm提供了一套强大而灵活的语法定义系统,通过区分语法和词法规则、支持参数化和继承等特性,使得语法定义更加模块化和可维护。掌握这些语法元素后,开发者可以构建复杂的语言解析器,同时保持语法的清晰和可扩展性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考