Что такое "семантический предикат" в ANTLR?


Что это семантический предикат в ANTLR?

2 94

2 ответа:

ANTLR 4

для предикатов в ANTLR 4, проверьте эти стекпереполнения Q&это:


ANTLR 3

A семантический предикат это способ применения дополнительных (семантических) правил грамматики действия, используя простые код.

существует 3 типа семантических предикатов:

  • проверка семантические предикаты;
  • закрытого типа семантические предикаты;
  • устранение неоднозначностей семантические предикаты.

пример грамматики

Допустим, у вас есть блок текста, состоящий только из цифр, разделенных запятая, игнорируя любые свободное пространство. Вы хотели бы проанализировать этот ввод решений убедитесь, что цифры не более 3 цифр "длинные" (не более 999). Следующий грамматика (Numbers.g) сделал бы такую вещь:

grammar Numbers;

// entry point of this parser: it parses an input string consisting of at least 
// one number, optionally followed by zero or more comma's and numbers
parse
  :  number (',' number)* EOF
  ;

// matches a number that is between 1 and 3 digits long
number
  :  Digit Digit Digit
  |  Digit Digit
  |  Digit
  ;

// matches a single digit
Digit
  :  '0'..'9'
  ;

// ignore spaces
WhiteSpace
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

тестирование

грамматика может быть проверена с помощью следующего класса:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("123, 456, 7   , 89");
        NumbersLexer lexer = new NumbersLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        NumbersParser parser = new NumbersParser(tokens);
        parser.parse();
    }
}

проверьте его, создав лексер и парсер, компилируя все .java файлы и под управлением Main класс:

java -cp antlr-3.2.jar org.antlr.Tool Numbers.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar Main

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

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7   , 89");

в:

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7777   , 89");

и сделайте тест еще раз: вы увидите ошибку, появляющуюся на консоли сразу после строки 777.


Семантические Предикаты

это подводит нас к семантическому предикату. Допустим, вы хотите разобрать числа от 1 до 10 цифр. Правило вроде:

number
  :  Digit Digit Digit Digit Digit Digit Digit Digit Digit Digit
  |  Digit Digit Digit Digit Digit Digit Digit Digit Digit
     /* ... */
  |  Digit Digit Digit
  |  Digit Digit
  |  Digit
  ;

станет громоздким. Семантический предикаты могут помочь упростить этот тип правила.


1. Проверка Семантических Предикатов

A проверка семантического предиката ничего больше, чем блок кода, за которым следует вопросительный знак:

RULE { /* a boolean expression in here */ }?

чтобы решить проблему, с помощью проверка семантический предикат, измените number правило в грамматике в:

number
@init { int N = 0; }
  :  (Digit { N++; } )+ { N <= 10 }?
  ;

запчасти { int N = 0; } и { N++; } простые Операторы Java, которые первый инициализируется, когда парсер "вводит"number правило. Действительность сказуемое-это: { N <= 10 }?, что приводит к тому, что парсер бросает a FailedPredicateException всякий раз, когда количество больше, чем 10 цифр.

проверьте его с помощью следующих ANTLRStringStream:

// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890"); 

который не создает исключения, в то время как следующее делает thow исключение:

// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");

2. Стробированные Семантические Предикаты

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

синтаксис a закрытый семантический предикат - это:

{ /* a boolean expression in here */ }?=> RULE

вместо того, чтобы решить вышеуказанную проблему с помощью закрытого типа предикаты для сопоставления чисел длиной до 10 цифр вы бы написали:

number
@init { int N = 1; }
  :  ( { N <= 10 }?=> Digit { N++; } )+
  ;

Я всегда использовал краткую ссылку на ANTLR предикаты ВКЛ wincent.com как мой проводник.