Использование ANTLR для разбора комментариев JavaDoc - PullRequest
2 голосов
/ 01 октября 2010

Я пытаюсь проанализировать один конкретный (доморощенный) тег JavaDoc в моем файле JavaScript, и я пытаюсь понять, как мне этого добиться. Antlr жалуется, как указано ниже:

jsDocComment 
    : '/**' (importJsDocCommand | ~('*/'))* '*/' <== See note 1
    ;

importJsDocCommand
    : '@import' gav
    ;

gav
    :  gavGroup ':' gavArtifact
    -> ^(IMPORT gavGroup gavArtifact)
    ;

gavGroup 
    : gavIdentifier
    ;

gavArtifact
    : gavIdentifier
    ;

gavIdentifier 
    : ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-'|'.')* <== See note 2
    ;
  • Примечание 1: Следующие альтернативы никогда не могут быть сопоставлены: 1

  • Примечание 2: Решение может соответствовать входным данным, таким как "'_' .. '." ", Используя несколько альтернатив: 1, 2 В результате альтернатива (ы) 2 были отключены для этого входа

Вот что я пытаюсь разобрать:

/** a */
/** @something */
/** @import com.jquery:jquery */

Все строки должны анализироваться нормально, только оператор @import (вместе с его группой Maven: значение артефакта) создается в элементе дерева AST с именем «IMPORT».

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 01 октября 2010

Кристофер Хант написал:

  • Примечание 1: Следующие альтернативы никогда не могут быть сопоставлены: 1

~('*/') неверно: в правилах лексера можно отрицать только отдельные символы (!).В своем фрагменте вы пытаетесь отрицать что-то в правиле парсера.В правилах синтаксического анализа вы не отрицаете символы, но токены.Например:

parse : ~A;
foo   : .;
A     : 'A';
B     : 'B';
C     : 'C';

правило parse будет не соответствовать любому символу, кроме 'A', но соответствует 'B' или 'C'foo не соответствует ни одному символу, но соответствует любому токену (или правилу лексера).

Кристофер Хант писал:

  • Примечание 2: Решение может соответствовать входным данным, таким как "_" .. '.' ", Используя несколько альтернатив: 1, 2 В результате альтернатива (ы) 2 были отключены для этого ввода

Два вопроса:

  1. Вы опубликовали всю грамматику?
  2. Вы пытаетесь проанализировать весь файл JS или вы просто «фильтруете» файлы JS ивытащить комментарии JavaDoc?

Если это последнее, есть гораздо более простой способ сделать это с помощью ANTLR (и может дать объяснение, если это так).

РЕДАКТИРОВАТЬ

Проще всего просто добавить новое DocComment правило лексера и поместить его чуть выше (существующего) Comment правила:

DocComment
  :  '/**' (options {greedy=false;} : .)* '*/'
  ;

Comment
  :  '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;}
  ;
0 голосов
/ 06 октября 2010

Мое решение этой проблемы состояло в том, чтобы использовать Lexer ANTLR без анализатора и отфильтровывать вещи, которые мне не интересны. Вот что я придумал (он также ищет глобально определенные переменные и импорт):

lexer grammar ECMAScriptLexer;

options {filter=true;}

@lexer::header {
    package com.classactionpl.mojo.javascript;
}

@members {
    int scopeLevel = 0;
}

IMPORTDOC
    :   '/**' .* IMPORT .* (IMPORT)* '*/'
    ;

fragment 
IMPORT
    :   '@import' WS groupId=GAVID ':' artifactId=GAVID
        {System.out.println("found import: " + $groupId.text + ":" + $artifactId.text);}
    ;

fragment
GAVID  
    :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'_'|'-'|'0'..'9'|'.')*
    ;

COMMENT
    :   '/*' .* '*/'
    ;

SL_COMMENT
    :   '//' .* '\n' 
    ;

ENTER_SCOPE
    :   '{' {++scopeLevel;}
    ;

EXIT_SCOPE
    :   '}' {--scopeLevel;}
    ;

WINDOW_VAR
    :   'window.' name=ID WS? value=(';' | '=') ~('=')
        {
            System.out.println("found window var " + $name.text + " = " + ($value == ';'));
        }
    ;

GLOBAL_VAR
    :   'var' WS name=ID WS? value=(';' | '=') ~('=')
        {
            if (scopeLevel == 0) {
                System.out.println("found global var " + $name.text + " = " + ($value == ';'));
            }
        }
    ;

fragment
ID  :   ('a'..'z'|'A'..'Z'|'$'|'_') ('a'..'z'|'A'..'Z'|'$'|'_'|'0'..'9')*
    ;

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