ANTLR3: нет жизнеспособной альтернативы у персонажа - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть эта грамматика ANTLR3:

grammar wft;

@header {
    package com.mycompany.wftdiff.parser;

    import com.mycompany.wftdiff.model.*;
}
@lexer::header {
    package com.mycompany.wftdiff.parser;
}
@members {
    private final WftFile wftFile = new WftFile();

    public WftFile getParsingResult() {
        return wftFile;
    }
}
wftFile:
    {
        System.out.println("Heyo!");
    }
    (CommentLine | assignment | NewLine)*
    itemTypeDefinition
    EOF
    ;

/**
 * ItemTypeDefinition
 * DEFINE ITEM_TYPE
 * END ITEM_TYPE
 */
itemTypeDefinition:
    'DEFINE ITEM_TYPE' NewLine
    (KeyName|TransStmt|BaseStmt|NewLine)+
        WhiteSpace* 'DEFINE ITEM_ATTRIBUTE' NewLine
        (KeyName|TransStmt|BaseStmt)*
        WhiteSpace* 'END ITEM_ATTRIBUTE' NewLine
    'END ITEM_TYPE'
    ;

/**
 * KeyName
 * KEY NAME VARCHAR2(8)
 */
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';

/**
 * TransStmt
 * TRANS DISPLAY_NAME VARCHAR2(80)
 */
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';

/**
 * BaseStmt
 BASE PROTECT_LEVEL NUMBER
 */
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';

/**
 * Assignment
 */
assignment returns [Assignment assignment]:
    {
        System.out.println("Assignment found!");
    }
    target=AssignmentTarget
    WhiteSpace '=' WhiteSpace
    value=String {
        assignment = new Assignment(target.getText(), value.getText());
        wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
    }
    NewLine;

AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;

/**
 * Comment
 */
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';

// Lexer rules

fragment D: '0'..'9';
fragment A: 'A'..'Z'
    | 'a'..'z';
StringLength: D+;
NewLine   : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';

Затем я создаю парсер для него, используя

java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g

... и называю это так:

val lexer = wftLexer(ANTLRFileStream(fileName))
val parser = wftParser(CommonTokenStream(lexer))
parser.wftFile()
System.out.println("Test")

fileName указывает на текстовый файл со следующим содержимым:

# Oracle Workflow Process Definition
# $Header$

VERSION_MAJOR = "2"
VERSION_MINOR = "6"
LANGUAGE = "GERMAN"

ACCESS_LEVEL = "100"

DEFINE ITEM_TYPE
  KEY NAME VARCHAR2(8)
  TRANS DISPLAY_NAME VARCHAR2(80)
  TRANS DESCRIPTION VARCHAR2(240)
  BASE PROTECT_LEVEL NUMBER
  BASE CUSTOM_LEVEL NUMBER
  BASE WF_SELECTOR VARCHAR2(240)
  BASE READ_ROLE REFERENCES ROLE
  BASE WRITE_ROLE REFERENCES ROLE
  BASE EXECUTE_ROLE REFERENCES ROLE
  BASE PERSISTENCE_TYPE VARCHAR2(8)
  BASE PERSISTENCE_DAYS NUMBER

  DEFINE ITEM_ATTRIBUTE
    KEY NAME VARCHAR2(30)
    TRANS DISPLAY_NAME VARCHAR2(80)
    TRANS DESCRIPTION VARCHAR2(240)
    BASE PROTECT_LEVEL NUMBER
    BASE CUSTOM_LEVEL NUMBER
    BASE TYPE VARCHAR2(8)
    BASE FORMAT VARCHAR2(240)
    BASE VALUE_TYPE VARCHAR2(8)
    BASE DEFAULT VARCHAR2(4000)
  END ITEM_ATTRIBUTE
END ITEM_TYPE

Я получаю следующий вывод:

Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 35:2 no viable alternative at character 'E'
Test

Как мне изменитьмоя грамматика для того, чтобы избавиться от ошибки no viable alternative at character 'D'?

Обратите внимание, что мне не нужно анализировать этот раздел файла (меня не интересует эта конкретная информация; она появится позже вфайл).

Обновление 1: Пытался игнорировать все это, как предлагалось здесь (используя skip()), но это не помогло.

Новый файл грамматики:

grammar wft;

@header {
    package com.mycompany.wftdiff.parser;

    import com.mycompany.wftdiff.model.*;
}
@lexer::header {
    package com.mycompany.wftdiff.parser;
}
@members {
    private final WftFile wftFile = new WftFile();

    public WftFile getParsingResult() {
        return wftFile;
    }
}
wftFile:
    {
        System.out.println("Heyo!");
    }
    (CommentLine | assignment | NewLine)*
    itemTypeDefinition
    EOF
    ;

/**
 * ItemTypeDefinition
 * DEFINE ITEM_TYPE
 * END ITEM_TYPE
 */
itemTypeDefinition:
    'DEFINE ITEM_TYPE' NewLine
    (KeyName|TransStmt|BaseStmt|NewLine)+
        WhiteSpace*
        NewLine
        DefineItemAttribute
        WhiteSpace*
    'END ITEM_TYPE'
    ;

DefineItemAttribute: 'DEFINE ITEM_ATTRIBUTE' .* 'END ITEM_ATTRIBUTE' {skip();};

/**
 * KeyName
 * KEY NAME VARCHAR2(8)
 */
KeyName: WhiteSpace* KeyNameStart .* {$channel = HIDDEN;} NewLine;
fragment KeyNameStart: 'KEY NAME VARCHAR2(';

/**
 * TransStmt
 * TRANS DISPLAY_NAME VARCHAR2(80)
 */
TransStmt: WhiteSpace* TransStmtStart .* {$channel = HIDDEN;} NewLine;
fragment TransStmtStart: 'TRANS';

/**
 * BaseStmt
 BASE PROTECT_LEVEL NUMBER
 */
BaseStmt: WhiteSpace* BaseStmtStart .* {$channel = HIDDEN;} NewLine;
fragment BaseStmtStart: 'BASE';

/**
 * Assignment
 */
assignment returns [Assignment assignment]:
    {
        System.out.println("Assignment found!");
    }
    target=AssignmentTarget
    WhiteSpace '=' WhiteSpace
    value=String {
        assignment = new Assignment(target.getText(), value.getText());
        wftFile.addAssignment(new Assignment(target.getText(), value.getText()));
    }
    NewLine;

AssignmentTarget: A (A|D|'_')*;
String: '"' ~'"'* '"'
;

/**
 * Comment
 */
CommentLine: CommentStart .* {$channel = HIDDEN;} NewLine;
fragment CommentStart: '#';

// Lexer rules

fragment D: '0'..'9';
fragment A: 'A'..'Z'
    | 'a'..'z';
StringLength: D+;
NewLine   : '\r' '\n' | '\n' | '\r';
WhiteSpace: ' ';

Результат разбора:

Heyo!
Assignment found!
Assignment found!
Assignment found!
Assignment found!
test-data/partialSample01.wft line 25:2 no viable alternative at character 'D'
test-data/partialSample01.wft line 36:0 missing DefineItemAttribute at 'END ITEM_TYPE'
Test

Условия вознаграждения

Я назначу вознаграждение человекукоторый совершает следующие героические поступки:

  1. Создает парсер, способный распознавать все части этого файла , которые помечены как соответствующие в комментариях, чтоt

1.1.все внутри тегов BEGIN ACTIVITY и END ACTIVITY, 1.2.все внутри BEGIN ACTIVITY_TRANSITION и END ACTIVITY_TRANSITION, 1.3.все внутри тегов BEGIN PROCESS_ACTIVITY и BEGIN PROCESS_ACTIVITY.

Под "распознавать все" я подразумеваю, что должен быть код ANTLR 3, который позволяет мне помещать операторы Java, которые будут обрабатывать данные, извлеченные из файла, как вassignment правило в оригинальном посте.Вам не нужно писать там какой-либо Java-код, но я должен иметь возможность добавить этот код позже.

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

Ваша грамматика должна быть совместима с ANTLR 3, Java 8 и Windows 7.

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

Парсер должен иметь возможность генерироваться с использованием java -cp "D:\wftdiff\lib\antlr-3.5.2\antlr-3.5.2-complete.jar" org.antlr.Tool -o src/com/mycompany/wftdiff/parser/ grammar-src/wft.g, или, если вы используете какие-либо специальные настройки, вынужно указать их в своем ответе.Суть в том, что мне нужно иметь возможность воспроизвести ваш результат.

Когда я передаю файл образца в анализатор, он должен потреблять его без жалоб (безпечать любых сообщений об ошибках ANTLR, без сбоев и без создания технических исключений, таких как NullPointerException).

1 Ответ

0 голосов
/ 08 февраля 2019

Вот грамматика.Он распознает все части, вы можете добавлять действия Java в любое удобное для вас место.

Скомпилировано и протестировано с использованием jdk1.8, antlr 3.5.2 и предоставленного примера ввода.

grammar wft;

@header {
    package com.mycompany.wftdiff.parser;
}

@lexer::header {
    package com.mycompany.wftdiff.parser;
}

@members {
}

wftFile :   (COMMENT|assignment|definition|flow)*
    ;

assignment
    :   ID EQ STRING
    ;

definition
    :   'DEFINE' ID
        (COMMENT | (dclass ID type) | definition)* 
        'END' ID
    ;


dclass  :   'KEY' | 'BASE' | 'TRANS'
    ;

type    :   tnum | tvarchar | tref | tdate
    ;

tnum    :   'NUMBER'
    ;

tvarchar:   'VARCHAR2' '(' INT ')'
    ;

tref    :   'REFERENCES' ID
    ;

tdate   :   'DATE'
    ;

flow    :   'BEGIN' ID (STRING)+
        (COMMENT|assignment|flow)+
        'END' ID
    ;

EQ  :   '='
    ;

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


NL  :   '\r'? '\n' {$channel=HIDDEN;}
    ;

COMMENT
    :   '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    ;

WS  :   ( ' '
        | '\t'
        ) {$channel=HIDDEN;}
    ;

STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;

INT :   '0'..'9'+
    ;
...