Грамматика ANTLR - Разбор меток и инструкций - PullRequest
2 голосов
/ 13 февраля 2012

Я пишу интерпретатор, который использует код списка команд. У меня возникают некоторые проблемы, когда я пытаюсь написать грамматику для инструкций с метками.

Я бы хотел проанализировать этот блок кода:

LD 4
ST A
LD A
EQ 4
ST _AUX_1
(* IF *)
LDN _AUX_1
JMPC _label_2 
(* THEN *)
LD B
EQ 3
ST _AUX_2
_label_2: (* ELSE *)
_label_1: (* END IF*)
LD TRUE

Как вы можете видеть, эти метки находятся в одной строке без инструкций, но язык, который я использую для синтаксического анализа, позволяет "метка + инструкция" в строке. Итак, существует три разных вида комбинаций инструкции и метки:

  1. Инструкция
  2. Метка:
  3. Метка: Инструкция

Я могу разобрать 1 и 2, но не могу разобрать все различные комбинации.

Это фрагмент моей грамматики ANTLR:

program_il : instruction* ;

instruction 
        : ID':' // label
        | ID_INST operand
        ;

operando
    : ID
    | CTE_INT
    | CTE_BOOL
    ;

Я пытался изменить грамматику на:

instruction : (ID':')? instruction? ;

Но у меня следующая ошибка:

As a result, alternative(s) 2 were disabled for that input
[14:43:49] error(201): Analizador.g:131:29: The following alternatives can never be matched: 2

Может ли кто-нибудь помочь мне с этой проблемой? Заранее спасибо.

1 Ответ

1 голос
/ 13 февраля 2012

Поскольку вы теперь принимаете Label: Instruction, грамматика неоднозначна.Синтаксический анализатор не может различить:

lbl:
LD 4

и

lbl: LD 4

Другими словами, вы должны позволить вашим instruction разделяться каким-либо разделителем.Разрыв строки будет работать, как показано в следующей демонстрации:

grammar T;

program_il
 : NL* instruction (NL+ instruction)* NL* EOF
 ;

instruction 
 : ID ':' (ID_INST operand)?
 | ID_INST operand
 ;

operand
 : ID
 | CTE_INT
 | CTE_BOOL
 ;

CTE_BOOL
 : 'TRUE'
 | 'FALSE'
 ;

ID_INST
 : 'LD'
 | 'ST'
 | 'EQ'
 | 'LDN'
 | 'JMPC'
 ;

ID
 : ('_' | 'a'..'z' | 'A'..'Z') ('_' | 'a'..'z' | 'A'..'Z' | '0'..'9')*
 ;

CTE_INT
 : ('0'..'9')+
 ;

NL
 : '\r'? '\n'
 | '\r'
 ;

COMMENT
 : '(*' .* '*)' {skip();}
 ;

SPACE
 : (' ' | '\t')+ {skip();}
 ;

Теперь при синтаксическом анализе ввода:

(* IF *)
JMPC _label_2 
(* THEN *)
LD B
ST _AUX_2
_label_2: LDN _AUX_1 (* ELSE *)
_label_1: (* END IF*)
LD TRUE

приведет к следующему дереву:

enter image description here

...