我有一个语法应该解析下面的代码片段(例如):
vmthread programm_start
{
CALL main
}
subcall main
{
// Declarations
DATAF i
CALL i
// Statements
MOVEF_F 3 i
}
问题是CALL语句之间存在歧义。此操作代码在vmthread部分(仅限CALL!)中有效,但也在这些子部分中有效。如果我使用所有操作码和一个额外的OC_CALL令牌定义OP_CODES令牌,那么词法分析器就无法处理这种情况(显然)。
以下列表是我的语法片段(第一个词法分析器,第二个解析器):
VMTHREAD
: 'vmthread'
;
SUBCALL
: 'subcall'
;
CURLY_OPEN
: '{'
;
CURLY_CLOSE
: '}'
;
OP_CODES
: 'DATA8'
| 'DATAF'
| 'MOVE8_8'
| 'MOVEF_F'
| 'CALL'
;
OC_CALL
: 'CALL'
;
lms
: vmthread subcalls+
;
vmthread
: VMTHREAD name = ID CURLY_OPEN vmthreadCall CURLY_CLOSE
;
vmthreadCall
: oc = OC_CALL name = ID
;
subcalls
: SUBCALL name = ID CURLY_OPEN ins = instruction* CURLY_CLOSE
;
//instruction+
instruction
: oc = OP_CODES args = argumentList
;
argumentList
: arguments+
;
arguments
: INTEGER
| NUMBER
| TEXT
| ID
;
要继续工作,我已使用OP_CODES标记切换vmthreadCall解析器规则中的OC_CALL标记。这解决了现在的问题,因为代码是自动生成的。但是,用户可以输入此代码,这样可能会出错。
是否有解决方案,或者我应该将验证移到解析器中。在那里,我可以轻松确定vmthread部分中的语句是否仅包含调用语句。
澄清:在vmthread中只允许使用CALL。在子查询中(可能不止一个)允许每个操作码(CALL +定义的每个其他操作码)。我不想区分那些不同的CALL语句。我知道在上下文无关语法中是不可能的。我将在解析器中处理此问题。我只想将vmthread限制为一个CALL语句并允许子语句中的所有语句(所有操作代码)。希望这更清楚。
答案 0 :(得分:1)
更改您的词法规则如下:
OP_CODES
: 'DATA8'
| 'DATAF'
| 'MOVE8_8'
| 'MOVEF_F'
| OP_CALL
;
OC_CALL
: 'CALL'
;
或者替代地:
OP_CODES
: 'DATA8'
| 'DATAF'
| 'MOVE8_8'
| 'MOVEF_F'
| CALL
;
OC_CALL
: CALL
;
fragment CALL: 'CALL';
顺便说一下,我建议您为文字创建明确的词法分析器规则(比如CALL片段),这将使以后的处理更容易。 ANTLR将通用名称分配给隐式创建的文字,这使得很难找出哪个标记属于哪个文字。