ANTLR4 Токенизация огромного набора ключевых слов

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

Можно ли поместить мои ключевые слова в отдельный файл? Одна из возможностей, о которой я думаю, - это поместить ключевые слова в класс java, который будет подклассифицирован сгенерированным классом лексера. В этом случае семантический предикат моего лексера может просто вызвать метод в пользовательском суперклассе лексера, чтобы проверить, соответствует ли входной токен моему длинному списку имен. И мой длинный список может быть помещен в этот код src суперкласса.

Однако в книге ANTLR4 говорится, что параметры грамматики «суперкласс» для комбинированной грамматики устанавливают только суперкласс парсера. Как я могу установить суперкласс моего лексера, если я все еще хочу использовать комбинированную грамматику. Или есть другой лучший способ поместить мой длинный список ключевых слов в отдельный «файл ключевых слов».


person JavaMan    schedule 07.05.2013    source источник


Ответы (1)


Если вы хотите, чтобы у каждого ключевого слова был свой тип токена, вы можете сделать следующее:

  1. Добавьте в грамматику блок tokens{}, чтобы создать токены для каждого ключевого слова. Это гарантирует создание уникальных типов токенов для каждого из ваших ключевых слов.

    tokens {
        Keyword1,
        Keyword2,
        ...
    }
    
  2. Создайте отдельный класс MyLanguageKeywords, подобный следующему:

    private static final Map<String, Integer> KEYWORDS =
        new HashMap<String, Integer>();
    static {
        KEYWORDS.put("keyword1", MyLanguageParser.Keyword1);
        KEYWORDS.put("keyword2", MyLanguageParser.Keyword2);
        ...
    }
    
    public static int getKeywordOrIdentifierType(String text) {
         Integer type = KEYWORDS.get(text);
         if (type == null) {
             return MyLanguageParser.Identifier;
         }
    
         return type;
    }
    
  3. Добавьте в свою грамматику правило лексера Identifier, которое обрабатывает ключевые слова и идентификаторы.

    Identifier
        :   [a-zA-Z_] [a-zA-Z0-9_]*
            {_type = MyLanguageKeywords.getKeywordOrIdentifierType(getText());}
        ;
    
person Sam Harwell    schedule 07.05.2013