2014-10-09 2 views
0

Вот моя грамматика:ANTLR3 правила Eval имеет решения не-LL (*)

grammar esi_exp; 

/* This will be the entry point of our parser. */ 
eval 
    : booleanExp 
    ; 

/* Addition and subtraction have the lowest precedence. */ 
booleanExp 
    : orExp 
    ; 

orExp 
    : andExpr (OR andExpr)* 
    ; 

andExpr 
    : notExpr (AND notExpr)* 
    ; 

notExpr 
    : NOT comparisonExpr 
    | comparisonExpr 
    ; 

comparisonExpr 
    : varOrLiteral ('==' varOrLiteral)* 
    ; 

varOrLiteral 
    : functionExpr 
    | literalExpr 
    | variableExpr 
    ; 

literalExpr : QUOTE VAR_ID QUOTE ; 
variableExpr 
    : OPEN_VAR VAR_ID CLOSE_PAREN   // $(HTTP_HOST) 
    | OPEN_VAR varWithArg CLOSE_PAREN // $(QUERY_STRING{param}) 
    | OPEN_VAR varWithArgQuoted CLOSE_PAREN // $(QUERY_STRING{'param'}) 
    | OPEN_PAREN booleanExp CLOSE_PAREN 
    ; 

varWithArg : VAR_ID OPEN_ARG VAR_ID CLOSE_ARG ; 
varWithArgQuoted : VAR_ID OPEN_QUOTED_ARG VAR_ID CLOSE_QUOTED_ARG ; 

matchValue : MATCH_VALUE_REGEX ; 

functionExpr 
    : '$' FunctionName functionArgs; 


FunctionName : 
    'exists' 
    | 'is_empty' 
    ; 

functionArgs 
    : '()' 
    | OPEN_PAREN VAR_ID CLOSE_PAREN 
    | OPEN_PAREN variableExpr CLOSE_PAREN 
    ; 

EQUALS : '==' ; 
MATCH_FUNC  : 'matches' ; 
TRIPLE_QUOTE : '\'\'\'' ; 
QUOTE  : '\'' ; 
OPEN_VAR : '$(' ; 
OPEN_PAREN : '(' ; 
CLOSE_PAREN : ')' ; 
OPEN_ARG : '{' ; 
CLOSE_ARG : '}' ; 
OPEN_QUOTED_ARG : '{\'' ; 
CLOSE_QUOTED_ARG : '\'}' ; 
VAR_ID  : ('a'..'z'|'A'..'Z'|'_')+ ;  // match identifiers 

AND : '&&' | '&' ; 
OR : '|' | '||' ; 
NOT : '!' ; 

/* A number: can be an integer value */ 
Number 
    : ('0'..'9')+ 
    ; 

WS 
    : (
      ' ' 
     | '\r' 
     | '\t' 
     | '\u000C' 
     | '\n' 
     ) 
      { 
       skip(); 
      } 
    ; 

MATCH_VALUE_REGEX : TRIPLE_QUOTE ~(QUOTE)* TRIPLE_QUOTE; 

, который работает отлично подходит для теста:

$exists($(id)) && (($(pagetype) == 'roster') || ($(pagetype) == 'cheerleaders') || ($(pagetype) == 'coaches') || ($(pagetype) == 'staff')) 

Однако, я также должен иметь это быть в состоянии признать:

$(REQUEST_PATH) matches '''(matchup)/([^/]*)/([^/]*)/([^/]*)/([^/]*)''' 

правило грамматики, как:

varOrLiteral MATCH_FUNC matchValue 

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

Я читал, что включение backtracking должно помочь в этих ситуациях, однако документация, похоже, указывает на то, что в целом следует избегать обратного отслеживания.

Как добавить это без проблем с LL и/или левой рекурсией?

ответ

0

Наконец понял это и был в состоянии достичь цели просто с изменением сравнения выражений для:

: varOrLiteral (EQUALS varOrLiteral | MATCH_FUNC matchValue)* 

Достаточно хорошо сейчас.

0

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

Почему бы вам не попробовать это?

varOrLiteral 
    : 
    (QUOTE QUOTE) => matchValue 
    |(QUOTE) => literalExpr 
    | variableExpr 
    |functionExpr 
    ; 

При этом, вы говорите грамматику, что только тогда, когда только varOrLiteral начинается от QUOTE, это literalExpr. И т.д.

Вы можете предвидеть, сколько вы хотите.

Последнее правило, вариант по умолчанию.

Удачи вам!

+0

Как это помогает реализовать/интегрировать «MATCH_FUNC matchValue» в грамматику? – nflearl

+0

Просто попробовал этот рефакторинг, получив исключение FailedPredicateException. Это не приводит к регрессии по существующему рабочему делу. – nflearl

+0

Я отредактировал свой ответ. Я пытался помочь вам, но я пропустил информацию. Извините. Попробуй это. Компиляция грамматик только с умом сложна, но я не получил доступ к моему «набору разработчика» прямо сейчас: p –