0

我正在为一个小项目开发一个简单的示例解析器/词法分析器,但我遇到了一个问题。

我正在按照以下方式解析内容:

Name SEP Gender SEP Birthday
Name SEP Gender SEP Birthday

... 、 或空格中的任何SEP一个(但不是多个!)在哪里。|,

现在,我不想将字段顺序锁定在词法分析器顺序中,因此我尝试使用一组非常简单的标记来对此进行词法分析:

%token <string> SEP
%token <string> VAL
%token NL

%token EOF

现在,如果gender字段不包含一小组预先确定的值,例如{male,female,neither,unspecified}. 我可以包装解析器并处理这个问题,但我真的很想将此要求编码到自动机中以供将来扩展。

我的第一次尝试,看起来像这样,可怕地失败了:

doc:
   | EOF              { [] }
   | it = rev_records { it }
   ;

rev_records:
           | (* base-case: empty *) { [] }
           | rest = rev_records; record; NL  { record :: rest }
           | rest = rev_records; record; EOF { record :: rest }
           ;

record:
   last_name = name_field; SEP; first_name = name_field; SEP;
   gender = gender_field; SEP; favourite_colour = colour_field; SEP;
   birthday = date_field
   { {last_name; first_name; gender; favourite_colour; birthday} }

name_field: str = VAL { str }

gender_field:
            | VAL "male" { Person.Male }
            | VAL "female" { Person.Female }
            | VAL "neither" { Person.Neither }
            | VAL "unspecified" { Person.Unspecified }
            ;

是的,没有骰子。显然,我对非结构化词法分析的尝试已经很糟糕了。

解析这样的东西的惯用方法是什么?

4

1 回答 1

1

解析器,例如 Menhir 和 OCamlYacc,对标记进行操作,而不是对字符串或字符进行操作。从字符到标记的转换是在词法分析器级别进行的。这就是为什么您不能在生产规则中指定字符串的原因。

当然,您可以在语义操作中执行任何检查并引发异常,例如,

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

您还可以标记可能的性别,或者您可以在词法分析器级别使用正则表达式来防止无效字段,例如,

rule token = parser
| "male" | "female" | "neither" | "unspecified" as -> {GENDER s}
...

但是,不建议这样做,因为它实际上会将male,female等变成关键字,因此它们在其他地方的出现会破坏您的语法。

于 2018-07-19T12:08:49.320 回答