Parsing JavaScript regex com ANTLR

9

Eu tenho uma gramática ANTLR JavaScript (obtida da Internet), que parece suportar tudo, exceto os literais de expressão regular.

O problema com um literal de expressão regular é que você tem duas regras, essencialmente:

multiplicativeExpression
    : unaryExpression (LT!* ('*' | '/' | '%')^ LT!* unaryExpression)*

e

regexLiteral
    : '/' RegexLiteralChar* '/'

em que a regra RegexLiteralChar usa regras lexer diferentes de uma expressão normal (por exemplo, uma aspa dupla não a encerra).

Isso significa que eu preciso, de alguma forma, alterar algum tipo de estado lexer do meu analisador. Como posso fazer isso? É mesmo possível?

    
por erikkallen 31.08.2012 в 10:59
fonte

1 resposta

5

Olhando para a gramática mencionada no comentário de Bart Kiers aqui , você pode ver este comentário,

  

Os principais desafios enfrentados na definição dessa gramática foram:

     

-1- Ambiguidade em torno do sinal DIV em relação à expressão multiplicativa e ao literal da expressão regular. Isto é   resolvido com alguma magia dirigida por lexer: um predicado semântico fechado   ativa ou desativa o reconhecimento de expressões regulares, com base na   valor da propriedade RegularExpressionsEnabled. Quando regular   expressões são habilitadas elas têm precedência sobre a divisão   expressões. A decisão sobre se as expressões regulares estão ativadas é   com base nas heurísticas que o token anterior pode ser considerado como   último token de um operando do lado esquerdo de uma divisão.

     

...

A função areRegularExpressionsEnabled () é definida como

private final boolean areRegularExpressionsEnabled()
{
    if (last == null)
    {
        return true;
    }
    switch (last.getType())
    {
    // identifier
        case Identifier:
    // literals
        case NULL:
        case TRUE:
        case FALSE:
        case THIS:
        case OctalIntegerLiteral:
        case DecimalLiteral:
        case HexIntegerLiteral:
        case StringLiteral:
    // member access ending 
        case RBRACK:
    // function call or nested expression ending
        case RPAREN:
            return false;
    // otherwise OK
        default:
            return true;
    }
}

E a função é usada na expressão RegularExpressionLiteral,

RegularExpressionLiteral
    : { areRegularExpressionsEnabled() }?=> DIV RegularExpressionFirstChar RegularExpressionChar* DIV IdentifierPart*
    ;
    
por sbridges 03.09.2012 / 07:28
fonte