2014-09-20 3 views
0

Я хочу научить flex & bison для определения макроопределений в чистом C. На самом деле я добавлю эту функцию к существующей форме синтаксического анализатора here. Сам анализатор хорош, но ему не хватает функциональности макросов. Таким образом, я сделал добавить успешно обнаружение #include и pragma макросов, но с макросами выбора у меня есть проблемы, это код в парсер:Flex and Bison, обнаружение макросов (новичок)

macro_selection_variants 
    : macro_compound_statement 
    | include_statement 
    | pragma_statement 
    | macro_selection_statement 
    | statement 
    ; 
macro_selection_statement 
    : MACRO_IFDEF IDENTIFIER macro_selection_variants MACRO_ENDIF 
    | MACRO_IFDEF IDENTIFIER macro_selection_variants MACRO_ELSE macro_selection_variants MACRO_ENDIF 
    | MACRO_IFNDEF IDENTIFIER macro_selection_variants MACRO_ENDIF 
    | MACRO_IFNDEF IDENTIFIER macro_selection_variants MACRO_ELSE macro_selection_variants MACRO_ENDIF 
    ; 

statement объявлен следующим образом:

statement 
    : labeled_statement  
    | compound_statement 
    | expression_statement 
    | selection_statement 
    | iteration_statement 
    | jump_statement  
    ; 

И лексер часть для этих макросов является:

"#ifdef"  { count(); return(MACRO_IFDEF); } 
"#ifndef"  { count(); return(MACRO_IFNDEF); } 
"#else"   { count(); return(MACRO_ELSE); } 
"#endif"  { count(); return(MACRO_ENDIF); } 

Так проблема я получаю 2 reduce/reduce ошибки б ecause я пытаюсь использовать statement в моем macro_selection_statement. Мне нужно использовать statement в макроэкономическом блоке выбора, потому что эти блоки могут иметь определения переменных любит так:

#ifdef USER 
#include "user.h" 
int some_var; 
char some_text[]="hello"; 
    #ifdef ONE 
     int two=0; 
    #endif 
#endif 

Что бы правильным шагом здесь? потому что я читал, что %expect -rr N - это действительно плохо, что связано с предупреждениями reduce.

+0

Проблема, вероятно, исходит из того, как вы добавили 'macro_selection_variants' другим правилам (' external_declaration' или ' block_item' или в другом месте), не имеет ничего общего с 'statement' или' macro_selection_statement'. Используйте опцию '-v' bison для генерации файла' .output', в котором подробно описываются состояния и где конфликты. –

ответ

1

Вы действительно не можете реализовать препроцессор (правильно) внутри грамматики C. Он должен быть * pre * процессором; то есть он читает текст программы, а его вывод отправляется на грамматику C.

Можно (в основном) избежать выполнения второго lex pass, поскольку (теоретически) препроцессор может выводить токены, а не поток символов. Вероятно, это будет хорошо работать с синтаксическим синтаксисом bison 2.7 или лучше, поэтому вы можете попробовать. Но традиционный подход - это просто поток персонажей, что может быть проще.

Важно помнить, что текст замены макроса, а также аргументы макроса, не имеют синтаксических ограничений. (. Или почти нет ограничений) Ниже вполне легальный:

#define OPEN { 
#define CLOSE } 
#define SAY(whatever) puts(#whatever); 

#include <stdio.h> 

int main(int argc, char** argv) OPEN SAY(===>) return 0; CLOSE 

И это только начало :)

+0

На самом деле мне не нужно, полный код этих макросов, моя цель - определить строковые литералы в файле (строковые константы, строковые переменные и определить константы), а затем encryprt некоторые из них по необходимости. Это моя первоначальная цель, я знаю, что это простая задача, но ее легче реализовать с помощью lex. Поэтому, если бы он просто «съел» эти макросы, execpt строка «определяет», я был бы счастлив. – Vanya

+0

Можно ли сделать компилятор предварительно обработать файлы C, поэтому я могу использовать те, у которых уже обработан макрос? – Vanya

+0

@ Vanya: gcc поставляется с отдельным инструментом (называемым 'cpp'), который препроцессы. Или вы можете вызвать 'gcc -E' только для предварительной обработки. – rici