2015-07-16 3 views
1

Недавно я начал использовать ANTLR для создания простого синтаксического анализа для интерполированных строк. Некоторые примеры входной строки следуют (по одному в каждой строке):Как сделать правило ANTLR «жадным»?

Hello {User.Name}!
Welcome on Planet {GetPlanetName(" A stupid string param :-} ")}
Plain String without an interpolated expression
String with escaped {{ brackets }}

грамматику, чтобы решить, следует ли что-то строка (plainString) или выражение (expressionString) выглядит следующим образом :

grammar T; 

patternString:     (plainString | expressionString)+ 
           ; 

plainString:     (CBO_ESCAPESEQUENCE | CBC_ESCAPESEQUENCE | PLAINSTRINGLITERAL)+ 
           ; 

expressionString:    CBO expression CBC | CURLYBRACKETS_EMPTY 
           ; 

expression:      expressionSegment+ 
           ; 

expressionSegment:    ~('"' | '\'' | '{' | '(' | '[' | '}' | ')' | ']' | CBO_ESCAPESEQUENCE | CBC_ESCAPESEQUENCE)+ 
           | '(' expressionSegment+ ')' | '(' WS ')' | '()' 
           | '[' expressionSegment+ ']' | '[' WS ']' | '[]' 
           | '{' expressionSegment+ '}' | CURLYBRACKETS_EMPTY 
           | stringLiteral 
           | charLiteral 
           ; 

stringLiteral:     '"' (~('"') | '\\"')+ '"' 
           | '""' 
           ; 

charLiteral:     '\'' (~('\'') | '\\\'')+ '\'' 
           ; 

fragment WS:     (' ' | '\r' | '\n' | '\t')+; 

PLAINSTRINGLITERAL:    ~('{' | '}'); 
CURLYBRACKETS_EMPTY:   (CBO WS CBC | CBO CBC); 
CBO:       '{'; 
CBC:       '}'; 

fragment CBO_ESCAPESEQUENCE: '{{'; 
fragment CBC_ESCAPESEQUENCE: '}}'; 

Это работает очень хорошо для некоторых строк, как за исключением следующего:

{{{новый [] {1, 2, 3, 4}}}}

Который дает мне следующее AST

PatternString         => '{{{new[]{1, 2, 3, 4}}}}' 
    ExpressionString       => '{{{new[]{1, 2, 3, 4}}}}' 
     Expression       => '{{new[]{1, 2, 3, 4}}}' 
      ExpressionSegment     => '{{new[]{1, 2, 3, 4}}}' 
       ExpressionSegment    => '{new[]{1, 2, 3, 4}}' 
        ExpressionSegment   => 'new[]' 
        ExpressionSegment   => '{1, 2, 3, 4}' 
         ExpressionSegment  => '1, 2, 3, 4' 

в то время как я хотел бы ожидать (и хотят) следующий AST:

PatternString         => '{{{new[]{1, 2, 3, 4}}}}' 
    PlainString        => '{{' 
    ExpressionString       => '{new[]{1, 2, 3, 4}}' 
     Expression       => 'new[]{1, 2, 3, 4}' 
      ExpressionSegment     => 'new[]' 
      ExpressionSegment     => '{1, 2, 3, 4}' 
       ExpressionSegment    => '1, 2, 3, 4' 
    PlainString        => '}}' 

Значение, plainString должны быть более жадным и взять столько побег d скобки. Как я могу исправить это в вышеупомянутой грамматике?

ответ

3

Я думаю, что ваши проблемы объясняются явным определением правила для открытых и закрывающих фигурных скобок, но затем ссылаются на них в некоторых правилах анализатора как строковый литерал. Модифицируя правило сегмента выражения только для ссылок на правила лексера, проблема, похоже, решена. Пожалуйста, попробуйте эту грамматику и посмотреть, если ваш вопрос фиксировано

expressionString:    CBO expression CBC | CURLYBRACKETS_EMPTY 
           ; 

expression:      expressionSegment+ 
           ; 

expressionSegment: 
            L_PAREN expressionSegment+ R_PAREN 
           | L_BRACKET expressionSegment+ R_BRACKET 
           | CBO expressionSegment+ CBC 
           | L_PAREN WS R_PAREN 
           | L_BRACKET WS R_BRACKET 
           | L_PAREN R_PAREN 
           | L_BRACKET R_BRACKET 
           | CURLYBRACKETS_EMPTY 
           | stringLiteral 
           | charLiteral 
           | ~(DOUBLE_QUOTE | SINGLE_QUOTE | CBC | CBO | L_PAREN | L_BRACKET | R_PAREN | R_BRACKET)+ 
           ; 

stringLiteral:     '"' (~('"') | '\\"')+ '"' 
           | '""' 
           ; 

charLiteral:     '\'' (~('\'') | '\\\'')+ '\'' 
           ; 

WS:     (' ' | '\r' | '\n' | '\t')+; 

PLAINSTRINGLITERAL:    ~('{' | '}'); 
CURLYBRACKETS_EMPTY:   (CBO WS CBC | CBO CBC); 
CBO:       '{'; 
CBC:       '}'; 
L_PAREN: '('; 
R_PAREN: ')'; 
L_BRACKET: '['; 
R_BRACKET: ']'; 
SINGLE_QUOTE: '\''; 
DOUBLE_QUOTE: '"'; 

Как вы можете видеть, дерево синтаксического анализа, кажется, отражает то, что вы ищете

enter image description here

+0

После быстрой проверки его кажется, работает отлично! Завтра мои юниты проведут тесты и дадут вам знать результаты! – Markus

+1

Прекрасно работает! Большое спасибо! – Markus

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