2014-11-13 4 views
1

В настоящее время я использую парсер JavaScript/ECMAScript 5.1 с JavaCC. Я недавно learned около LOOKAHEAD s, которые здесь удобны, поскольку грамматика не полностью LL (1).Как реализовать отрицательную проверку LOOKAHEAD для токена в JavaCC?

Одна из вещей, которые я вижу в грамматике ECMAScript «негативный контроль опережения», как в следующем ExpressionStatement производства:

ExpressionStatement : 
    [lookahead ∉ {{, function}] Expression ; 

Так что, наверное, нужно что-то вроде LOOKAHEAD(!("{" | "function")), но он не работает в этот синтаксис.

Вопрос в том, как я мог реализовать этот «отрицательный LOOKAHEAD» в JavaCC?

После прочтения LOOKAHEAD MiniTutorial я считаю, что выражение типа getToken(1).kind != FUNCTION может быть тем, что мне нужно, но я не совсем уверен в этом.

+1

Я поместил свое предложенное решение в синтаксический анализ ArrayLiteral в конце моего ответа на ваш второй вопрос, поэтому я считаю, что это не имеет значения. Но, может быть, кто-то придумает решение. – rici

+0

@rici Да, я думаю, что моя непосредственная проблема с 'ArrayLiteral' будет решена, я переписал вопрос, чтобы сосредоточиться на отрицательном' LOOKAHEAD'. – lexicore

ответ

1

Для примера, который вы предоставляете, я бы предпочел использовать синтаксический взгляд вперед, который в определенном смысле обязательно «положительный».

Производство для ExpressionStatement не является местом для решения проблемы, поскольку выбора нет.

void ExpressionStatement() : {} { Expression() ";" } 

Проблема возникнет, когда есть выбор между утверждением выражения и блоком или между утверждением выражения и объявлением функции (или оба).

E.g. в Заявлении вы найдете

void Statement() :{} { 
    ... 
| 
    Block() 
| 
    ExpressionStatement() 
| ... 
} 

дает предупреждение, потому что оба варианта могут начинаться с символа "{". У вас есть два варианта. Один из них - игнорировать предупреждение. Первый выбор будет сделан, и все будет хорошо, пока Блок станет первым. Второй вариант - подавить предупреждение с помощью спецификации. как это:

void Statement() :{} { 
    ... 
| 
    LOOKAHEAD("{") Block() 
| 
    ExpressionStatement() 
| ... 
} 

синтаксический смотреть вперед, в некотором смысле положительный - «принять эту альтернативу, если X».

Если вы действительно хотите отрицательный --i.e., «Возьмите эту альтернативу, если не X» - смотрите вперед, она должна быть семантической.

В случае заявления вы могли бы написать

void Statement() :{} { 
    ... 
| 
    LOOKAHEAD({!(getToken(1)==LBRACE)}) ExpressionStatement() 
| 
    Block() 
} 

Я убедился, что это последние две альтернативы, так как иначе вы должны были бы включать в себя более лексем в наборе лексем, которые блокируют ExpressionStatement(), например он не должен выбираться, если следующий токен является «если» или «в то время» или «для» и т. д.

В целом, вам лучше использовать синтаксический просмотр, когда сможете. Это обычно более прямолинейно и сложнее испортить.

+0

На самом деле меня больше интересует «отрицательный« LOOKAHEAD », чем при его конкретном решении для« ExpressionStatement ». – lexicore

+0

В целом, вам лучше использовать синтаксический просмотр, когда сможете. В этом случае вы можете использовать семантический просмотр. Например. 'LOOKAHEAD ({getToken (1)! = LBRACE && getToken (1)! = FUNCTION}) ExpressionStatement() | Block() 'будет работать. –

 Смежные вопросы

  • Нет связанных вопросов^_^