2013-12-15 5 views
0

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

display <<"hello">> (number1) (number2) (number3) { 
    a = 1; 
    b = 2; 
    ... 
} 

Примечание это только пример, хотя и уродливой, например, но все же, это всего лишь преувеличения можно о том, что я хотел бы сделать. number1, number2, number3 - цифры, а отображение будет своего рода оператором, за которым следует блок между {}, содержащим назначение переменной, и это будет печатать все это особым образом. Как сказано, просто пример.

Мой вопрос об этом ... скажем, этот синтаксис, форма display <<str>>()()() {} используется только с ключевым словом «display» и никогда не используется после. И, допустим, < < и >> обычно являются операторами. Интересно ... как можно сказать bison/flex, что в этом случае < < и >> не используются в качестве операторов, а только разделители, принадлежащие синтаксису «display»? И, как вы могли бы правильно извлекать данные между < < и >>, номерами между() и затем синтаксическим разборами всего блока с использованием ДИФФЕРЕННОГО, СПЕЦИФИЧЕСКОГО синтаксиса для блока между {}?

Например, если у меня было:

display <<"hello">> (1) (5) (8) { 
    a = 1; 
    b = 8 * 273 + 40; 
} 

Я тогда хотел бы сделать вызов, как это:

handle_display_operator(szStr, num1, num2, num3) 

// here szStr contains "hello", num1 = 1, num2 = 5, num3 = 8 

После этого вызова функции, я должен был бы разобрать в блок.

Может ли кто-нибудь объяснить мне, как бы я справился с этим должным образом?

Благодаря

ответ

1

Вы можете написать это как бизон правило, как:

statement: DISPLAY LSHIFT string RSHIFT '(' expr ')' '(' expr ')' '(' expr ')' 
       { handle_display_operator($3, $6, $9, $12); } 
      block 
     ; 

где лексер распознает display как для ключевого слова, и << и >> как LShift жетоны и RShift. В других контекстах (например, выражение) вы будете использовать LSHIFT и RSHIFT в качестве операторов сдвига.

Это разрешает ЛЮБОЕ выражение в круглой скобке (которое вы можете оценить целочисленным в своих правилах expr) и может разрешать строковые выражения, если вы обрабатываете их в правиле.

Альтернативный подход, если вы действительно хотите, необработанный текст между <</>> (а не строки), заключается в использовании гибкого эксклюзивное положение для после display ключевого слова. Тогда вам придется сгибать правила, как:

%x display, raw_text 
%{ 
    /* use a dynamic buffer if you don't have an upper limit on the length */ 
    static char raw_text_buffer[MAX_LENGTH], *raw_text_end; 
%} 

%% 

"display"  { BEGIN(display); return DISPLAY; } 
<display>"<<" { BEGIN(raw_text); raw_text_end = raw_text_buffer; } 
<raw_text>. { *raw_text_end++ = *yytext; /* DANGER -- may overflow */ } 
<raw_text>\n { error?? or just put it in the buffer... } 
<raw_text>">>" { *raw_text_end = 0; 
       yylval.string = strdup(raw_text_buffer); 
       BEGIN(INITIAL); 
       return RAW_TEXT; } 

Теперь ваше правило будет выглядеть следующим образом:

statement: DISPLAY RAW_TEXT '(' expr ')' '(' expr ')' '(' expr ')' 
       { handle_display_operator($2, $4, $7, $10); } 
      block 

Это позволяет входы как display << %" ,> >> (1)(2)(3) и передаст вашу функцию ручки строку %" ,> (в том числе ведущие/конечные пробелы котировки и все.

конечно, вы должны добавить проверку на переполнение буфера с соответствующим сообщением об ошибке.

+0

Спасибо за comprehe и быстрый ответ Крису.Я все равно хотел бы извлечь выгоду из вашего опыта в отношении точки. В блоке, обработанном дисплеем, скажем, я хотел бы иметь уникальный синтаксис внутри него. Скажем, у меня есть второй оператор, называемый, например, 'struct', который бы принял также блок, такой как struct {block}, и что блок внутри синтаксиса struct также имеет уникальный синтаксис внутри него. Опять же я удивляюсь этому примеру, но я хотел бы четко понять концепцию. Должен ли я сделать другой yyparse() (префикс), или я могу сделать это в одном парсере? Благодаря! – Yannick

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