2015-03-27 3 views
1

У меня есть грамматика ниже (упрощенная для демонстрации), и у меня возникла проблема в конкретном случае, связанном с логическими операторами.ANTLR C# 4 Грамматика - Приоритет

Все, что я тестировал, кроме случая, когда логический оператор находится в моем цитированном идентификаторе. Например, это работает:

@m = "ABC12345"

Но это не делает:

@m = "ABC12OR345"

Что происходит, ИЛИ внутри строки дает приводит к следующему ошибка

посторонний вход 'ИЛИ' ожидает { "", LOWCHAR < HIGHCAR, DIGIT}

Я в недоумении относительно того, как Ге t приоритет правильный.

Благодаря

  grammar PRDL; 

      options 
      { 
        language=CSharp; 
      } 

      statement 
       : expression (logicalOperator expression)* 
       ; 

      logicalOperator 
       : logicalOR | logicalAND 
       ; 

      logicalOR 
       : OR 
       ; 

      logicalAND 
       : AND 
       ; 

      expression 
       : mVar 
       | nVar 
       | parenStatement 
       | notExpression 
       ; 

      parenStatement 
       : LPAREN statement RPAREN 
       ; 

      notExpression 
       : NOT expression 
       ; 

      mVar 
       : M equalityOperator quotedIdentifier 
       ; 

      nVar 
       : N equalityOperator quotedIdentifier 
       ; 

      equalityOperator 
        : EQUAL 
        ; 

      quotedIdentifier 
       : '"' identifier '"' 
       ; 

      identifier 
       : (HIGHCHAR | LOWCHAR | DIGIT)+ 
       ; 


      // ============ Lexer Defintions ======================== 

      // OPERATORS 

      NOT_ALLOWED : '*' | '/' | '+' | '-' | '#' | '$' | '%' | '^'; 

      EQUAL  : '='; 

      COMMA  : ','; 

      LPAREN  : '('; 

      RPAREN  : ')'; 

      LPARENSQ : '['; 

      RPARENSQ : ']'; 

      OR   : ('OR' | 'or' | '||'); 

      AND   : ('AND' | 'and' | '&&'); 

      NOT   : ('NOT' | 'not' | '!') ; 

      M    : '@M'; 

      N    : '@N'; 

      LOWCHAR  : 'a'..'z'; 

      HIGHCHAR : 'A'..'Z'; 

      DIGIT  : '0'..'9'; 


      // Whitespace -- ignored 
      WS   : [ \n\t\r\f]+ -> skip; 

ответ

1

Ставит полосу между лексером и анализатором в неправильном месте ...

quotedIdentifier 
    : '"' identifier '"' 
    ; 

identifier 
    : (HIGHCHAR | LOWCHAR | DIGIT)+ 
    ; 

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

Эти два правила синтаксического анализа должны быть на самом деле лексера правила:

QUOTED_IDENTIFIER 
    : '"' (HIGHCHAR | LOWCHAR | DIGIT)+ '"' 
    ; 

IDENTIFIER 
    : (HIGHCHAR | LOWCHAR | DIGIT)+ 
    ; 

И HIGHCHAR, LOWCHAR и DIGIT должны быть фрагменты, чтобы предотвратить получение другой тип маркера на одиночные символы:

fragment LOWCHAR  : 'a'..'z'; 
fragment HIGHCHAR : 'A'..'Z'; 
fragment DIGIT  : '0'..'9'; 

С такими lexer, вы получите один токен за идентификатор, что намного лучше для синтаксического анализа.

Кроме того, правила, как это в значительной степени бесполезны:

equalityOperator 
     : EQUAL 
     ; 

Как это просто альясинга правило лексического анализатора с правилом синтаксического анализатора.

+0

Привет, Лукас, спасибо за ответ. Я попробовал пару вариантов, учитывая вашу информацию, но все еще имел проблемы. –

+0

Извините, нажмите enter, а затем не успели вернуться. Одна из вещей, о которых я не упоминал, это то, что я использую прослушиватель, поэтому у меня больше правил в парсере (например, public override void ExitQuotedIdentifier ...). Во время разбора я создаю внутренний список, который позже могу применить к переменным значения реальных значений и оценить истинное/ложное условие. Похоже, мне нужно больше читать, чтобы лучше понять эту версию antlr - несколько иначе, чем версия, которую я использовал 8 или 10 лет назад. –

+0

Хорошо, я понял. Изменяя это: идентификатор \t: (HIGHCHAR | LOWCHAR | DIGIT) + \t; Для этого: идентификатор \t: ИДЕНТИФИКАТОР + \t; , а затем положить IDENTIFIER в лексер следующим образом: IDENTIFIER \t: (HIGHCHAR | LOWCHAR | DIGIT) +; Я смог заставить все работать. Спасибо, –

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