0

在我的声明中,lexer.mll我声明EOS如下:

let line_feed = '\n' (* %x200A *)
let carriage_return = '\r' (* %x200D *)
let line_terminator = line_feed | carriage_return | carriage_return line_feed 
(* KO: %x2028 | %x2029 *)
let LINE_END = line_terminator

let tab_character = '\x09' (* CHARACTER TABULATION *)
let eom_character = '\x19' (* END OF MEDIUM *)
let space_character = '\x20' (* SPACE *)
let underscore = '\x5F' (* LOW LINE or SPACING UNDERSCORE *)

let WSC = tab_character | eom_character | space_character 
let line_continuation = WSC* underscore WSC* line_terminator
let WS = (WSC | line_continuation)+
let EOL = WS? LINE_END
let EOS = EOL*

rule token = parse
  | WS       { token lexbuf }
  | LINE_END { newline lexbuf; token lexbuf }
  | EOS      { EOS }

在我的parser.mly,我有这样的事情:

%token EOS
...
%%
nonterminal :
    statement EOS 
    statement { semantic-action }

我如下编辑我test_KO.txtEmacs,它在解析时引发错误:

a_statement
b_statement

但是,如果我在后面添加一个spacea_statement它会通过解析:

a_statement(space)
b_statement

我想原因是line_terminator无法识别,test_KO.txt但不在同一行;如果它们之间有一个,则可以识别。a_statemntb_statementline_terminatorspace

您认为添加x2028x2029line_terminator解决问题吗?由于ocamllex可能不支持很好的 unicode,所以测试它会很复杂......

否则,有没有其他解决方案?

4

1 回答 1

2

问题是您的 WS、LINE_END 和 EOS 规则都可以尝试匹配相同的字符串,请参阅OCamllex 手册以了解用于选择哪个正则表达式实际匹配的“最长匹配”规则。

当语句之间只有一个行终止符时,“LINE_END”和“EOS”规则都只匹配 1 个字符,但“LINE_END”规则出现得更早,因此被选中。没有发出 EOS 令牌,并且您的语法出现错误。

当您同时有空格和行终止符时,“WS”的规则将匹配 1 个字符,而 EOS 的规则将匹配两个字符(空格和换行符),因此选择 EOS 的规则。现在发出一个 EOS 令牌,您的语法按预期工作。

最简单的可能是从您的词法分析器和语法中删除 EOS 令牌。

于 2013-04-21T12:31:17.327 回答