java - 如何为嵌套的 "if"指令定义使用多个破折号的语法?

标签 java syntax grammar cup

我正在尝试用 Java 创建一个可以识别这段代码的语法分析器(使用 CUP):

if ¿b? then
~ a = 2;
~ if ¿b && c? then
~ ~ a = 3;
else
~ a = 4;

“if”语句使用的产品如下:

Instr ::= ...
       | IF CONOP Exp:e CONCL THEN CondInstrList:l
       ...
       ;
...
CondInstrList ::= CondInstrList CondInstr
       | /*empty*/
       ;
...
CondInstr ::= CONTROLD Instr
       | CONTROLD CondInstr
       ;

其中 Instr 代表指令/语句,CondInstrList 代表条件指令列表,CONTROLD 代表控制破折号 (~)。 (CONOP 和 CONCL 表示条件打开/关闭)

问题在于使用该语法,生成的 AST 如下:

if
|-condition b
|-condInstrListT
  |---asig a = 2
  |---if
      |---condition b and c
      |---condInstrListT 
      |   |---asig a = 2
      |---condInstrListF
          |---asig a = 4

因此,“else”部分与内部“if”相关联。

我只是不知道如何编写符合我希望我的语言的方式的语法。

感谢任何帮助。

如果需要,我可以提供更多细节。

最佳答案

我不认为单靠语法就可以做到你想做的事。但是使用稍微不同的语法和词法分析器的一些帮助是可能的。

这里是要做的:与其将 ~ 标记视为单独的语法符号,不如让词法分析器将行首的 ~ 序列转换为 INDENT 和 OUTDENT 标记,它们在语法中的工作方式与 { 和在 Java 中工作。您跟踪从零开始的“当前缩进级别”。在每一行的开头,计算 ~ 字符。对于超过当前缩进级别的每个 ~,生成一个 INDENT 标记并增加当前缩进级别;对于每个小于当前缩进级别的 ~,生成一个 OUTDENT 标记并降低当前缩进级别。

因此您的示例文本为

if ¿b? then
~ a = 2;
~ if ¿b && c? then
~ ~ a = 3;
else
~ a = 4;

将被标记为:

// Indent level = 0 and no ~, so no INDENT here
[IF] [CONOP] [ID b] [CONCL] [THEN]
// Indent level = 0, one ~, so one INDENT
[INDENT]
    // Indent level = 1
    [ID a] [OP =] [CONST 2] [SEMICOLON]
    // Indent level = 1, one ~, so no INDENT here
    [IF] [CONOP] [ID b] [OP &&] [ID c] [CONCL] [THEN]
    // Indent level = 1, two ~, so one INDENT
    [INDENT]
        // Indent level = 2
        [ID a] [ASSIGN] [CONST 3] [SEMICOLON]
        // Indent level = 2, lines starts with no ~, two OUTDENTs
    [OUTDENT]
    // Indent level = 1
[OUTDENT]
//Indent level = 0
[ELSE] // No ~ at start of this line, so no INDENT
// Indent level = 0; one ~, so one INDENT
[INDENT] 
    // Indent level = 1
    [ID a] [ASSIGN] [CONST 4] [SEMICOLON]
// End-of-input.  Indent level = 1, so 1 OUTDENT
[OUTDENT]
// Done; indent level = 0;

INDENT 和 OUTDENT 标记在您的语法中的作用类似于 Java 中的左右大括号,因此您的语法可能类似于:

Instr ::= ...
       | IF CONOP Exp:e CONCL THEN INDENT CondInstrList:l OUTDENT
       ...
       ;
...
CondInstrList ::= CondInstrList Instr
       | /*empty*/
       ;
...

Python 语言做同样的事情,但只是使用空格而不是 ~。可以下载Python源码here如果你有兴趣。查找文件 Grammar\GrammarParser\tokenizer.c

关于java - 如何为嵌套的 "if"指令定义使用多个破折号的语法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44014564/

相关文章:

java - 在cucumber cli main方法后执行代码生成报告

java - 在String java中获取图标包路径

html - 如何选择具有特定类别的元素?

jquery - iOS $(document).on() 在模态中工作, $ ('' ).click(function() 仅在网站内工作

java - 如何解析这个语法?

java - ANTLR - 连接 token 以输出

java - 如何在java中使用drawline绘制楼梯线?

c++ - 了解 C++ 结构体语法

parsing - LL1首先并遵循设置规则

java - 如何在捕获异常后保持代码运行(Java)