Цикл парсинга FOR с использованием анализатора PLSQL на основе ANTLR

Я изменил парсер PLSQL, предоставленный [Porcelli] ( https://github.com/porcelli/plsql-parser). Я использую этот парсер для разбора файлов PlSql. Я сталкиваюсь с проблемой разбора операторов цикла FOR, например

for i in 1..l_line_tbl.count
LOOP
l_line_tbl(i).schedule_ship_date := l_max_ship_date;
l_line_tbl(i).ship_set_id := x_ship_set_id;
END LOOP;

Вышеупомянутое утверждение не разбирает, а его выдает EarlyExitException.

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

for i in 1 ..l_line_tbl.count
LOOP
l_line_tbl(i).schedule_ship_date := l_max_ship_date;
l_line_tbl(i).ship_set_id := x_ship_set_id;
END LOOP;

Грамматика парсера:

loop_statement
@init    {    int mode = 0;    } 
:    label_name?
    (while_key condition {mode = 1;} | for_key cursor_loop_param {mode = 2;})?
    loop_key
    seq_of_statements
    end_key loop_key label_name?
    -> {mode == 1}? ^(WHILE_LOOP[$while_key.start] label_name* 
    ^(LOGIC_EXPR condition) seq_of_statements)
    -> {mode == 2}? ^(FOR_LOOP[$for_key.start] label_name* cursor_loop_param seq_of_statements)
    -> ^(loop_key label_name* seq_of_statements)
;

// $<Loop - Specific Clause

cursor_loop_param
@init    {    int mode = 0;    }
:    (index_name in_key reverse_key? lower_bound DOUBLE_PERIOD)=> 
        index_name in_key reverse_key? lower_bound DOUBLE_PERIOD upper_bound
    -> ^(INDEXED_FOR index_name reverse_key? ^(SIMPLE_BOUND lower_bound upper_bound))
|     record_name in_key ( cursor_name expression_list? {mode = 1;} | LEFT_PAREN 
select_statement RIGHT_PAREN)
    ->{mode == 1}? ^(CURSOR_BASED_FOR record_name cursor_name expression_list?)
    -> ^(SELECT_BASED_FOR record_name select_statement)
;

// $>

Грамматика лексера:

FOR_NOTATION
:    UNSIGNED_INTEGER
    {state.type = UNSIGNED_INTEGER; emit(); advanceInput();}
    '..'
    {state.type = DOUBLE_PERIOD; emit(); advanceInput();}
    UNSIGNED_INTEGER
    {state.type = UNSIGNED_INTEGER; emit(); advanceInput(); $channel=HIDDEN;}
;

fragment
UNSIGNED_INTEGER
:    ('0'..'9')+ 
;

0 ответов

Другие вопросы по тегам