ANTRL 3 грамматика опущена часть входного исходного кода

Я использую эту грамматику ANTLR 3 и ANTLRWorks для тестирования этой грамматики.

Но я не могу понять, почему некоторые части моего входного текста опущены.

Я хотел бы переписать эту грамматику и отобразить каждый элемент (lparen, ключевые слова, точку с запятой,..) исходного файла (ввода) в AST / CST.

Я перепробовал все, но безуспешно. Может ли кто-нибудь, кто имеет опыт работы с ANTLR, помочь мне?

введите описание изображения здесь

Разобрать дерево:

разбирать дерево

1 ответ

Решение

Мне удалось сузить его до semic правило:

/*
This rule handles semicolons reported by the lexer and situations where the ECMA 3 specification states there should be semicolons automaticly inserted.
The auto semicolons are not actually inserted but this rule behaves as if they were.

In the following situations an ECMA 3 parser should auto insert absent but grammaticly required semicolons:
- the current token is a right brace
- the current token is the end of file (EOF) token
- there is at least one end of line (EOL) token between the current token and the previous token.

The RBRACE is handled by matching it but not consuming it.
The EOF needs no further handling because it is not consumed by default.
The EOL situation is handled by promoting the EOL or MultiLineComment with an EOL present from off channel to on channel
and thus making it parseable instead of handling it as white space. This promoting is done in the action promoteEOL.
*/
semic
@init
{
    // Mark current position so we can unconsume a RBRACE.
    int marker = input.mark();
    // Promote EOL if appropriate   
    promoteEOL(retval);
}
    : SEMIC
    | EOF
    | RBRACE { input.rewind(marker); }
    | EOL | MultiLineComment // (with EOL in it)
    ;

Итак, вставка точки с запятой снова начинается!

Я не совсем уверен, но я думаю, что эти mark / rewind звонки не синхронизированы. @init Блок выполняется, когда введено правило для выбора ветви и фактического соответствия. Это на самом деле создает много отметок, но не убирает их. Но я не знаю, почему это так портит дерево разбора.

Во всяком случае, вот рабочая версия того же правила:

semic
@init
{
    // Promote EOL if appropriate   
    promoteEOL(retval);
}
    : SEMIC
    | EOF
    | { int pos = input.index(); } RBRACE { input.seek(pos); }
    | EOL | MultiLineComment // (with EOL in it)
    ;

Это намного проще и не использует mark/rewind механизм.

Но есть подвох: semic Правило в дереве разбора будет иметь дочерний узел } в случае вставки точки с запятой перед закрывающей скобкой. Попробуйте убрать точку с запятой после i-- и увидим результат. Вы должны будете обнаружить это и обработать это в своем коде. semic должен содержать ; токен или содержать EOL (это означает, что точка с запятой была вставлена ​​в этот момент без вывода сообщений).

Другие вопросы по тегам