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}
...