2017-01-12 9 views
0

Я пишу демоверсию генерации кода llvm для определенного языка, который включает в себя инструкцию if. Вот правила и действия, соответствующие моему вопросу:Анализ синтаксического выражения в yacc

IfStatement : IF CondExpression THEN Statement      {if_Stmt(string($2),string($4));}      %prec LOWER_THAN_ELSE ; 
      | IF CondExpression THEN Statement ELSE Statement  {if_else_Stmt(string($2),string($4),string($6));} 
      ;    

CondExpression : Expression Relop Expression   { $$ = operation($2,string($1),string($3));printf("Relop value : %s \n",$2);} 
       | Expression       {$$ = $1;} 
       ; 

Relop :  EE     {$$ = (char *)(string("icmp eq ").c_str());printf("%s\n",$$);}     
     | NE     {$$ = (char *)(string("icmp ne ").c_str());} 
     | LT     {$$ = (char *)(string("icmp slt ").c_str());} 
     | GT     {$$ = (char *)(string("icmp sgt ").c_str());} 
     | LTE     {$$ = (char *)(string("icmp sle ").c_str());} 
     | GTE     {$$ = (char *)(string("icmp sge ").c_str());} 
      ; 

Правило CondExpression следует разобрать условное выражение. Я использую функцию печати для печати значения токена Relop, который имеет тип < char *>. Relop должен иметь значение условных токенов внутри строковой функции, как показано выше в коде. Тем не менее, результат функции печати, 0

Relop value : 0 

и результат второго печати внутри Relop является правильным,

Relop value : icmp eq 

почему значение Relop в CondExpression является 0, и как это сделать возьмите правильное значение, возвращенное из правила Relop.

+0

Каков твой семантический тип? – rici

+0

char * для CondExpression и Relop –

ответ

1

не только

(char *)(string("icmp ne ").c_str() 

абсурдно запутанных способ написания

"icmp ne" 

также вводит Неопределенное поведение, отсутствующей в простой и очевидной альтернативы. Конструктор string создает и возвращает временную строку, а c_str затем используется для возврата указателя на внутреннее хранилище этого временного. Затем вы сохраняете этот указатель в стеке парсера и позволяете временному деконструировать, осировая сохраненный указатель. Поэтому, когда вы пытаетесь напечатать строку, вы передаете висячий указатель, и все может произойти, например, память повторно используется для какого-либо другого объекта, что приводит к печати таинственной строки.

Конечно, если ваш семантический тип char *, C++ будет жаловаться, что $$ = "icmp eq"; не является const-safe. Мне не сразу кажется, почему вы не используете char *const в качестве семантического типа, если какая-либо другая часть вашего кода не намерена изменять строку или, возможно, потребуется освободить память (потому что в некоторых случаях строка была динамически распределена). В этом случае вы можете заставить копию строки использовать, например, strdup. Если ваша библиотека не обеспечивает strdup или вы не хотите, чтобы полагаться на то, что легко можно определить как нечто вроде

char* strdup(const char* s, size_t len=strlen(s)) { 
    char* r = malloc(len + 1); 
    memcpy(r, s, len); 
    r[len] = 0; 
    return r; 
} 

Хотя более C++ - как решение будет использовать std::string* в качестве смыслового типа , что позволяет вам написать:

$$ = new std::string("icmp eq"); 
+0

это строки для равных, не равных, меньше, чем ..etc: http: //releases.llvm.org/2.7/docs/LangRef.html. Я попросил найти решение, чтобы не создать проблему. –

+1

@rational: я понимаю, что означают строки. Решение состоит в том, чтобы устранить проблему, которую я идентифицировал. Либо используйте строковый литерал или копию строкового литерала (если по какой-то причине вам нужна копия.) Но не создавайте оборванного указателя. – rici

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

  • Нет связанных вопросов^_^