2014-09-26 18 views
-1

我想解析像'x = 1;'的語句使用彎曲和野牛。爲此,我創建一個符號表來存儲'x'和它的值1.因此,下一次當解析器看到像'x = 2'這樣的語句時它會將符號表中x的值更新爲2. 現在我的野牛和flex代碼對於單個字母變量(例如:x,y,a,b,c等)可以正常工作。但是,當我嘗試使用字符串變量(多個字符)時,程序將引發分段錯誤。我不完全瞭解到底發生了什麼問題以及在哪裏。下面是拋出Seg Fault的代碼。如何掃描Flex中的字符串,然後解析它在野牛

這是flex.l文件:

%{ 
#include <stdio.h> 
#include "calc.tab.h" 
%} 

digit ([0-9]) 
id  ([a-z]) 



%% 

"print"  {  return(TOK_PRINTLN);} 

"prints" { return(TOK_PRINTSTR);} 

"main()" {return(TOK_MAIN);} 
"{"   {return(TOK_LBRACE);} 
"}"   {return(TOK_RBRACE);} 

{digit}+ { 
     sscanf(yytext, "%d", &yylval); 
     return TOK_NUM; 
     } 
"("  { return(TOK_LPARAN);} 
")"  { return(TOK_RPARAN);} 
";" { return(TOK_SEMICOLON); } 

"+" { return(TOK_ADD); } 
"+=" { return(TOK_ADDEQ); } 
"-" { return(TOK_SUB); } 
"-=" { return(TOK_SUBEQ); } 
"=" { return(TOK_EQUAL); } 
{id}+ { 
    sscanf(yylval.character,"%s",strdup(yytext)); 
    return (TOK_ID); 
} 
[ \n] {} 

. {printf("Invalid character '%c', ignored\n", 
      yytext[0]); 
      printf("Line Number %d\n", yylineno); 
    } 

%% 

這是野牛代碼.Y文件:

%{ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

typedef struct Node 
{ 
    char *sym; //changed 
    int val; 
    struct Node *next; 
}SymTable; 

SymTable *Head; 

int symExists(char *c) //changed 
{ 
    SymTable *tmp = malloc(sizeof(SymTable)); 
    tmp = Head; 
    while(tmp != NULL) 
    { 
     if(!(strcmp(tmp->sym,c))) //changed 
     return 1; 
     tmp = tmp->next; 
    } 
    return 0; 
} 

SymTable *getNodeOf(char *c)//changed 
{ 
    SymTable *tmp = malloc(sizeof(SymTable)); 
    tmp = Head; 
    while(tmp != NULL) 
    { 
     if(!strcmp(tmp->sym,c))//changed 
     return tmp; 
     tmp = tmp->next; 
    } 
    return NULL; 
} 


void Insert(char *sym,int val)//changed 
{ 
    //printf("%s\n",sym); 
    //int i = getstrlen(sym); 

    SymTable *tmp =(SymTable*) malloc(sizeof(SymTable)); 
    //printf("Here 1\n"); 
    //tmp->sym = (char *) malloc(50*sizeof(char)); 
    //printf("Here 2\n"); 
    /*tmp->sym=sym;*/strcpy(tmp->sym,sym);//changed 
    tmp->val = val; 

    if(Head == NULL) 
    { 
     tmp->next = NULL; 
     Head = tmp; 
    } 
    else 
    { 
     if(symExists(sym))//changed 
     { 
      tmp = getNodeOf(sym);//changed 
      tmp->val = val; 
     } 
     else 
     { 
      tmp->next = Head; 
      Head = tmp; 
     } 
    } 
    fprintf(stdout,"val:%d sym: %s\n",tmp->val,tmp->sym); //changed 

} 

int getTokIdVal(char *sym) //changed 
{ 
    SymTable *tmp = malloc(sizeof(SymTable)); 
    tmp = Head; 
    while(tmp!=NULL) 
    { 
     if(!strcmp(tmp->sym,sym)) //changed 
     return tmp->val; 
     tmp= tmp->next; 
    } 
    return 0; 
} 

int eval(int a,int b,char c,char *sym) //changed 
{ 

    switch(c) 
    { 
     case '+': 
     return a+b; 
     break; 
     case '-': 
     return a-b; 
     break; 
     case 'n': 
     return a; 
     break; 
     case '=': 
     Insert(sym,a); 
     break; 
     case 'm': 
     return -a; 
     break; 

    } 
    return 0; 
} 


%} 

%token TOK_SEMICOLON TOK_ADD TOK_SUB TOK_MUL TOK_DIV TOK_NUM TOK_PRINTLN TOK_EQUAL TOK_PRINTSTR TOK_QUOTE TOK_LPARAN TOK_RPARAN TOK_ADDEQ TOK_SUBEQ TOK_MAIN TOK_LBRACE TOK_RBRACE 

%union{ 
     int int_val; 
     char *character;//changed 
} 

%token <character> TOK_ID//changed 


/*%type <int_val> expr TOK_NUM*/ 
%type <int_val> expr TOK_NUM 



%left TOK_ADD TOK_SUB 
%left TOK_MUL TOK_DIV 

%% 



stmt: 
    |stmt expr_stmt 
; 

expr_stmt: 
     expr TOK_SEMICOLON 
     | TOK_PRINTLN expr TOK_SEMICOLON 
     { 
      fprintf(stdout, "the value is %d\n", $2); 
     } 

; 

expr: 
    expr TOK_ADD expr 
     { 
      $$ = eval($1,$3,'+',NULL); 
     } 
    | TOK_ID TOK_ADDEQ expr 
     { 
      $$ = eval(getTokIdVal($1),$3,'+',NULL); 
      Insert($1,$$); 

     } 
    | expr TOK_SUB expr 
     { 
      $$ = eval($1,$3,'-',NULL); 
     } 
    | TOK_ID TOK_SUBEQ expr 
     { 
      $$ = eval(getTokIdVal($1),$3,'-',NULL); 
      Insert($1,$$); 

     } 
    | TOK_NUM 
     { 
     $$ = eval($1,0,'n',NULL); 
     } 
    | TOK_ID TOK_EQUAL expr 
     { 
      $$ = eval($3,0,'=',$1); 

     } 
    | TOK_ID 
     { 
     $$ = getTokIdVal($1); 
     } 
    | TOK_LPARAN TOK_SUB expr TOK_RPARAN 
    { 
     $$ = eval($3,0,'m',NULL); 
    } 

; 



%% 


int yyerror(char *s) 
{ 
    printf("%s\n", s); 

    return 0; 
} 

int main() 
{ 
    yyparse(); 

    return 0; 
} 

回答

1

你爲你的符號表鏈表代碼是完全炒 - 這代碼(它出現在多個地方)是無稽之談:

SymTable *tmp = malloc(sizeof(SymTable)); 
tmp = Head; 

因爲它爲對象分配空間,但隨後立即overw儀表返回的指針,所以內存泄漏。在符號表中搜索時,不需要分配任何內存,並且Insert只需要在符號尚未存在時分配。閱讀基本教程用C鏈表,如this one

這種說法是無稽之談,以及:

sscanf(yylval.character,"%s",strdup(yytext)); 

它試圖從沒有被設置爲任何事情yylval.character閱讀並覆蓋符號你正在嘗試返回。您可能只需要:

yylval.character = strdup(yytext); 

這裏。

+0

謝謝克里斯。 – Sandeep 2014-09-27 03:36:33