如何定义对嵌套 "if" 指令使用多个破折号的语法?
How to define a syntax that uses multiple dashes for nested "if" instructions?
我正在尝试在 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 代表 instruction/statement,CondInstrList 代表条件指令列表,CONTROLD 代表控制破折号 (~)。 (CONOP 和 CONCL 表示条件 Open/Close)
问题在于使用该语法,生成的 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 中工作。您跟踪从零开始的 "current indent level"。在每一行的开头,计算 ~ 字符。对于超过当前缩进级别的每个 ~,生成一个 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 做同样的事情,但只有白色 space 而不是 ~。如果您有兴趣,可以下载 Python 来源 here。查找文件 Grammar\Grammar
和 Parser\tokenizer.c
.
我正在尝试在 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 代表 instruction/statement,CondInstrList 代表条件指令列表,CONTROLD 代表控制破折号 (~)。 (CONOP 和 CONCL 表示条件 Open/Close)
问题在于使用该语法,生成的 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 中工作。您跟踪从零开始的 "current indent level"。在每一行的开头,计算 ~ 字符。对于超过当前缩进级别的每个 ~,生成一个 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 做同样的事情,但只有白色 space 而不是 ~。如果您有兴趣,可以下载 Python 来源 here。查找文件 Grammar\Grammar
和 Parser\tokenizer.c
.