2015-05-12 2 views
0

Я создаю компилятор для школьного проекта. Все работает отлично, но у меня возникают трудности с определением грамматики для функций. Я должен определить, есть ли ноль или более параметров, и если эта функция является прототипом или определением. Я продолжаю получать/уменьшать и/или уменьшать/уменьшать ошибки. Я пробовал много вариантов безрезультатно. Вот что я имею, только ищущие указатели в другом направлении или идеи о том, как это исправить.Создание грамматики для прототипов функций и объявления bison

function : parameters ';' {free_ast($2); $$ = $1;} 
      | parameters block {$$ = adopt1($1, $2)} 
      ; 

parameters : paramlist ')' {free_ast($2); $$ = $1;} 
      | '(' identdecl ')' {free_ast($3); $$ = adopt_func2($1, $2);} 
      ; 

paramlist : paramlist ',' identdecl {free_ast($2); 
             $$ = adopt1($1, $2);} 
      | '(' identdecl   {$$ = adopt_func2($1, $2);} 

identdecl : basetype TOK_ARRAY TOK_IDENT {$$ = adopt2($1, $2, 
              change_symbol(
              $3, TOK_DECLID));} 
      | basetype TOK_IDENT   {$$ = adopt1($1, 
              change_symbol(
              $2, TOK_DECLID));} 
      ; 

block  : stateseq '}'  {free_ast($2); $$ = $1;} 
      | ';'    {free_ast($1);} 
      ; 

принимает_func2 принимает определение, поэтому частью моей проблемы будет место для принятия_прото. Спасибо за ваше время.

+1

В чем разница между прототипом и декларацией? Что такое грамматика? Как это относится к C++? – Potatoswatter

+0

Мне жаль добавить C++, я использую C++ для написания всего остального. Уже поздно, и я некоторое время работаю над этим. Прототип не имеет блока, и определение имеет значение, как и C++. поэтому int foo(); // proto и int foo() {...} для определения. Также есть точка с запятой. –

+0

Прототипом в C++ является объявление. A * definition * - это то, что включает тело функции. – Potatoswatter

ответ

1

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

parameters : paramlist ')' 
      | '(' identdecl ')' 
      ; 

paramlist : paramlist ',' identdecl 
      | '(' identdecl 
      ; 

Так (type id) можно уменьшить, используя либо первую продукцию для parameters, где paramlist уменьшается с его второй производство, или его можно уменьшить напрямую, используя второе производство для parameters. Я не вижу никакой очевидной потребности в втором производстве для parameters, поэтому я бы предложил просто удалить его.

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

parameters : '(' paramlist ')' 
      | '(' ')' 

paramlist : identdecl 
      | paramlist ',' identdecl 

который, я думаю, намного яснее.

+0

Я думаю, что это исходит из какой-то другой части, но когда я разбираю файл сейчас, я получаю синтаксическую ошибку от моего анализатора, говорящего «неожиданно» («, ожидая») или «,». Это может быть какая-то другая грамматика, которую я имею, но проблема с переключением/уменьшением или уменьшением/уменьшением не существует. Хотя проблема с уменьшением/уменьшением с точки с запятой зависит от функции и блока. –

+0

@corn_flakes: вы разрешаете 'block' быть единственным'; ', что означает, что определение может выглядеть точно так же, как объявление. Вы действительно должны исправить эту двусмысленность. Я также рекомендовал бы переписать правило 'block' так же, как и« параметры », так что' {'и'} 'находятся в одном и том же произведении. (Как показано, никакая продукция не включает '{', так что это определенно не сработает. – rici

+0

Да, извините за это. Продолжением для блока является stateeq: stateseq statement {$$ = принятие1 ($ 1, $ 2);} | '{' {$$ = change_symbol ($ 1, TOK_BLOCK);} ; –

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