2011-04-19 2 views
1

내 렉스 파일이 있습니다추가 오른쪽 중괄호는

word [^{}"=,\t\[email protected]\\ ]+ 

\{ { 
    return(LBRACE); 
} 

\} { 
    return(RBRACE); 
} 

{word} { 
    yylval = yytext; printf("WORD=%s",yytext); return(WORD); 
} 

내 Yacc에 파일이 있습니다 입력에

phrase: LBRACE WORD RBRACE {printf("LBRACE %s RBRACE\n",$2);}; 

:

{FooBar} 

를 내가 얻을 :

WORD=FooBar 
LBRACE FooBar} RBRACE 

나는 내가 단지 $ 2 인쇄하고있어 비록 여분의 오른쪽 중괄호을 받고 있어요 왜 확실 해요 어떤해야

답변

3

할 수 있다고 생각 :이 어휘를 처리하는 동안

{word} { 
    yylval = yytext; printf("WORD=%s",yytext); return(WORD); 
} 

yytext에서의 값은에만 유효합니다. 다음 어휘로 옮기면 버퍼의 내용을 덮어 쓸 수 있습니다. 따라서 yytext 포인터를 저장하는 것은 좋은 일을하지 않습니다. 버퍼에서 토큰을 복사해야합니다.

{word} { yylval = (char*)calloc(yylen+1, sizeof(char)); 
      strncpy(yylval, yytext, yylen); // Remember you need to free this. 
      return WORD; 
     } 
+0

답변 해 주셔서 감사합니다! 나는 당신이 글로벌 변수 yyleng을 의미한다고 생각 하죠, 그렇죠? 또한,'strncpy'가'yyleng + 1' 문자를 넘겨서 종료 null을 얻지 않아야합니까? 'strndup'가 사용되면 자체적으로 종료 null을 추가합니다. –

+0

@crypto : 그렇습니다. 나는 lex가 제공 한 글로벌 yylen을 의미합니다. 반환 된 기본 메모리가 null 인 것을 보장하는 calloc()을 사용하기 때문에 strncpy가 yylen +1을 복사 할 필요가 없습니다. 따라서 strncpy가 '\ 0'을 추가하는 것처럼 '\ 0'을 추가할지 여부는 중요하지 않습니다. –

2

그것은 WORD 생산 (yylval 통해) yytext의 값을 저장하기 위해 당신에게 달려 이상적입니다. 그것은 렉스의 작업 공간에 대한 포인터 일뿐입니다. RBRACE을 구문 분석 한 후 작업 공간이 변경된 것을 볼 수 있습니다. LBRACE WORD COMMA WORD LBRACE과 같은 yacc 규칙을 상상해보십시오.

별도의 생산을하지 않으려면

난 당신이 여기 LBRACE WORD { code to strdup yylval } RBRACE { ... }

+0

왜'$ 2' 및 전달 된'yylval' 문자열 값에 차이가 있는가? –

+0

'yylval'은 그 자체로 "문자열"이 아니며 lex 개인 데이터를 가리키는 포인터 *입니다. 당신은'yylval'을 소유하고 있지만 그것이 가리키는 것을 소유하고 있지 않습니다. 'yylex()'가 리턴하고 다시 호출하는 사이의 주어진 터미널 심볼에 대해서만 유효합니다. 무슨 뜻인지'yylval = strdup (yytext)'라고 해보자. –

+0

strdup은 안전하지 않습니다. 렉스 버퍼가 '\ 0'종료된다는 보장은 없습니다. 필요한 버퍼 부분을 추출하려면 yylen을 사용해야합니다. –

관련 문제