Parsing 基于令牌的内容在解析器级别进行分支
我正在为一个小项目开发一个简单的解析器/词法分析器示例,但遇到了一个问题 我将按照以下思路分析内容:Parsing 基于令牌的内容在解析器级别进行分支,parsing,ocaml,grammar,ocamllex,menhir,Parsing,Ocaml,Grammar,Ocamllex,Menhir,我正在为一个小项目开发一个简单的解析器/词法分析器示例,但遇到了一个问题 我将按照以下思路分析内容: Name SEP Gender SEP Birthday Name SEP Gender SEP Birthday …其中SEP是任意一个,但不是多个!属于|、、或空白 现在,我不想将字段顺序锁定在lexer顺序中,所以我尝试用一组非常简单的令牌来lex它: %token <string> SEP %token <string> VAL %token NL %toke
Name SEP Gender SEP Birthday
Name SEP Gender SEP Birthday
…其中SEP是任意一个,但不是多个!属于|、、或空白
现在,我不想将字段顺序锁定在lexer顺序中,所以我尝试用一组非常简单的令牌来lex它:
%token <string> SEP
%token <string> VAL
%token NL
%token EOF
是的,没有骰子。显然,我尝试的非结构化词法已经很糟糕了
解析这样的东西的惯用方法是什么?解析器,如Menhir和OCamlYacc,对标记而不是字符串或字符进行操作。从字符到标记的转换是在lexer级别进行的。这就是为什么不能在产生式规则中指定字符串 当然,您可以在语义操作中执行任何检查并引发异常,例如
record:
last_name = name_field; SEP; first_name = name_field; SEP;
gender_val = VAL; SEP; favourite_colour = colour_field; SEP;
birthday = date_field
{
let gender = match gender_val with
| "male" -> Person.Male
| "female" -> Person.Female
| "neither" -> Person.Neither
| "unspecified" -> Person.Unspecified
| _ -> failwith "Parser error: invalid value in the gender field" in
{last_name; first_name; gender; favourite_colour; birthday}
}
您还可以标记可能的性别,或者在lexer级别使用正则表达式来防止无效字段,例如
rule token = parser
| "male" | "female" | "neither" | "unspecified" as -> {GENDER s}
...
然而,这是不推荐的,因为它实际上会把男性、女性等变成关键词,所以它们在其他地方的出现会破坏你的语法 我不是解析器专家,但我会将接受的值标记化,因为它们具有语法值,然后将性别_字段定义为这些标记的并集。也许你应该添加问题中使用的Person.Male等构造函数。此外,在词法分析时处理性别也不是那么理想,这些话可能会出现在其他地方,并打破东西。是的,这是一个很好的观点。它基本上会生成指定的genders关键字。因此,从一开始就不应该是解析器错误。
rule token = parser
| "male" | "female" | "neither" | "unspecified" as -> {GENDER s}
...