2013-10-14 3 views
0

Я написал parser_sub.mly и lexer_sub.mll которые могут разобрать subroutine. A subroutine является блоком выписки, заключенным в Sub и End Sub.Разбор списка подпрограмм

На самом деле, необработанный файл, с которым я хотел бы иметь дело, содержит список подпрограмм и некоторые бесполезные тексты. Вот пример:

' a example file 
Sub f1() 
    ... 
End Sub 
haha 
' hehe 
Sub f2() 
    ... 
End Sub 

Так что мне нужно написать parser.mly и lexer.mll, которые могут разобрать этот файл, игнорируя все комментарии (например, haha, ' hehe и т.д.) и вызов parser_sub.main и возвращает список подпрограмм.

  1. Может кто-нибудь сказать мне, как позволить парсер игнорировать все бесполезные предложения (предложения за пределами Sub и End Sub)?

    Вот часть parser.mly я пытался написать:

    %{ 
        open Syntax 
    %} 
    %start main 
    %type <Syntax.ev> main 
    %% 
    main: 
        subroutine_declaration* { $1 }; 
    
    subroutine_declaration: 
        SUB name = subroutine_name LPAREN RPAREN EOS 
        body = procedure_body? 
        END SUB 
        { { subroutine_name = name; 
         procedure_body_EOS_opt = body; } } 
    
  2. правил и разбора для procedure_body сложны и фактически определены в parser_sub.mly и lexer_sub.mll, так как я мог позволить parser.mly и lexer.mll не повторите определение, и просто позвоните parser_sub.main?

ответ

0

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

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

Наконец-то у вас возникла проблема в том, что ваш конечный маркер - это два символа, END SUB. Вы должны обрабатывать случай, когда вы видите END, за которым не следует SUB. Это даже сложнее, потому что SUB также является вашим начальным маркером. Опять же, одним из способов упростить это было бы взломать ваш лексер, чтобы он рассматривал END SUB как единственный токен. (Обычно это сложнее, чем вы ожидали, скажем, если вы хотите разрешить комментарии между END и SUB.)

1

Может быть, мы можем установить некоторый флаг, когда мы находимся внутри подпрограммы:

sub_starts: 
    SUB { inside:=true }; 
sub_ends: 
    ENDSUB { inside:=false };  
subroutine_declaration: 
    sub_starts name body sub_ends { ... } 

И когда этот флаг не установлен просто пропустить любой входной сигнал?

Смежные вопросы