2017-04-13 16 views
1

Windows에서 FLEX를 사용하여 어휘 분석기를 작성하려고합니다. 아이디어가flex에서 yylval을 사용하는 방법

%option noyywrap 
    %{ 
     #include<stdio.h> 
     #include<stdlib.h> 
     #include "tokens.h" 
     int nline = 1; 
     int size_token_array = 100; 
     int number_of_tokens_in_array = 0; 
     int inc_token_array = 50; 
     token *token_store ; 
     extern yylval; 

    %} 
    delim [ \t] 
    delim_nl [\n] 
    ws {delim}+ 
    nl {delim_nl}+ 
    letter [a-z] 
    digit [0-9] 
    id {letter}(letter.digit)* 
    int_num (0|([+-]?([1-9]{digit}*))) 
    real_num [+-]?{digit}+(\.{digit}+) 
    rel_op ">"|"<"|"<="|">="|"=="|"!=" 
    binary_ar_op "+"|"-"|"*"|"/"|"=" 
    task_id {letter}(letter+digit)* 
    signal_id {letter}(letter+digit)* 

    %% 
    "parbegin" {create_and_store_token(TOKEN_PARBEGIN,yytext,nline); return 1;} 
    "parend" {create_and_store_token(TOKEN_PAREND,yytext,nline); return 1;} 
    "task" {create_and_store_token(TOKEN_TASK,yytext,nline); return 1;} 
    "{" {create_and_store_token('{',yytext,nline); return 1;} 
    "}" {create_and_store_token('}',yytext,nline); return 1;} 
    "begin" {create_and_store_token(TOKEN_BEGIN,yytext,nline); return 1;} 
    "end" {create_and_store_token(TOKEN_END,yytext,nline); return 1;} 
    "integer" {create_and_store_token(TOKEN_INTEGER,yytext,nline); return 1;} 
    "real" {create_and_store_token(TOKEN_REAL,yytext,nline); return 1;} 
    "||" {create_and_store_token(TOKEN_PARALLEL,yytext,nline); return 1;} 
    ";" {create_and_store_token(';',yytext,nline); return 1;} 
    "," {create_and_store_token(',',yytext,nline); return 1;} 
    "do" {create_and_store_token(TOKEN_DO,yytext,nline); return 1;} 
    "until" {create_and_store_token(TOKEN_UNTIL,yytext,nline); return 1;} 
    "od" {create_and_store_token(TOKEN_OD,yytext,nline); return 1;} 
    "send" {create_and_store_token(TOKEN_SEND,yytext,nline); return 1;} 
    "accept" {create_and_store_token(TOKEN_ACCEPT,yytext,nline); return 1;} 
    "(" {create_and_store_token('(',yytext,nline); return 1;} 
    ")" {create_and_store_token(')',yytext,nline); return 1;} 
    "<" {create_and_store_token(LT,yytext,nline); yylval=rel_op; return 1;} 
    ">" {create_and_store_token(GT,yytext,nline); yylval=rel_op; return 1;} 
    "<=" {create_and_store_token(LE,yytext,nline); yylval=rel_op; return 1;} 
    ">=" {create_and_store_token(GE,yytext,nline); yylval=rel_op; return 1;} 
    "==" {create_and_store_token(EQ,yytext,nline); yylval=rel_op; return 1;} 
    "!=" {create_and_store_token(NE,yytext,nline); yylval=rel_op; return 1;} 
    "*" {create_and_store_token('*',yytext,nline); yylval=binary_ar_op; return 1;} 
    "/" {create_and_store_token('/',yytext,nline); yylval=binary_ar_op; return 1;} 
    "+" {create_and_store_token('+',yytext,nline); yylval=binary_ar_op; return 1;} 
    "-" {create_and_store_token('-',yytext,nline); yylval=binary_ar_op; return 1;} 
    "=" {create_and_store_token('=',yytext,nline); yylval=binary_ar_op; return 1;} 
    {ws} ; 
    {nl} nline++; 
    id {create_and_store_token(TOKEN_ID,yytext,nline); return 1;} 
    int_num {create_and_store_token(TOKEN_INT_NUM,yytext,nline); return 1;} 
    real_num {create_and_store_token(TOKEN_REAL_NUM,yytext,nline); return 1;} 
    binary_ar_op {create_and_store_token(TOKEN_AR_OP,yytext,nline); return 1;} 
    "task_id" {create_and_store_token(TOKEN_TASK_ID,yytext,nline); return 1;} 
    "signal_id" {create_and_store_token(TOKEN_SIGNAL_ID,yytext,nline); return 1;} 

    %% 
    int main() 
    { 
     token_store = (token*)calloc(size_token_array,sizeof(token)); 
     free(token_store); 
     return 0; 

    } 

    void create_and_store_token(int token_type,char* token_lexeme,int line_number){ 

     token new_token; 
     new_token.ivalue = token_type; 
     new_token.lexema = token_lexeme; 
     new_token.line_number = line_number; 

     if(size_token_array == (number_of_tokens_in_array-10)){ 

      token_store = (token*)realloc(token_store,inc_token_array*sizeof(token)); 
      size_token_array+=inc_token_array; 
      number_of_tokens_in_array++; 
      token_store[number_of_tokens_in_array]= new_token; 

     } 
     else{ 
      token_store[number_of_tokens_in_array]= new_token; 
      number_of_tokens_in_array++; 

     } 
    } 

    int nextToken(){ 
     return yylex(); 
    } 

    void backToken(){ 
     token_store[number_of_tokens_in_array].ivalue = 0; 
     token_store[number_of_tokens_in_array].lexema = ""; 
     token_store[number_of_tokens_in_array].line_number = 0; 
     number_of_tokens_in_array--; 
    } 

누구 나는이 문제를 어떻게 해결해야

"undefined reference to `yylval'"

내가 다음과 같이 모든 정의가 이루어되는 extern 형 최대로하는 yylval 선언 : 는 항상 오류를 받고 있어요?

답변

1

extern yylval;yylval이 다른 곳에 정의됨을 의미합니다. 그래서 당신은 그렇게해야합니다.

일반적으로 yacc/bison 생성 구문 분석기에서 정의되므로 스캐너와 구문 분석기를 연결할 때 이름을 확인할 수 있습니다. bison/yacc을 사용하지 않는 경우 yylval을 직접 정의해야합니다. (실제로 코드가 필요한 경우 코드는 필요한 것을 알려주지 않습니다.)

그런데 코드에는 많은 다른 문제가 있습니다. 특히 두드러진 점은 스캐너가 다음 토큰으로 이동 한 후에 포인터 yytext의 값을 사용할 수 없다는 것입니다. yytext이 가리키는 문자열의 영구 복사본이 필요하면 더 이상 필요하지 않을 때 복사본에 할당 된 메모리를 확보해야합니다.

또한 많은 정규식이 잘못되었습니다. . 매크로 사용 ("정의")은 중괄호로 묶어야하므로

id {create_and_store_token(TOKEN_ID,yytext,nline); return 1;} 

은 예상 한 것과 일치하지 않습니다. 2 문자 시퀀스와 일치합니다. . {id}으로 변경하면 이 시작되지만 id이라는 정의도 올바르지 않습니다.

개인적으로 매크로에 값을 추가하지 않기 때문에 개인적으로 매크로를 사용하지 않습니다. 그들은 종종 혼란을 일으킨다. 예를 들어, letter의 정의에는 소문자 만 포함되며 사용자의 코드를 읽는 사람에게는 전혀 알 수 없습니다. 정의를 필요로하지 않고 그 의미가 모호하지 않은 Posix 문자 클래스를 사용하는 것이 훨씬 더 좋습니다. 문자의 경우 [[: alpha:]], 문자의 경우 [[:lower:]], 문자 또는 숫자의 경우 [[:alnum:]]