문제

토큰의 실제 문자열을 전달하고 싶습니다. ID라는 토큰이 있으면 YACC 파일이 실제로 ID가 호출되는 것을 알기를 원합니다. 나는 yylval을 사용하여 yaCC 파일을 Flex 파일에서 yACC 파일로 전달해야합니다. 어떻게해야하나요?

도움이 되었습니까?

해결책

보다 YACC와의 인터페이스에 대한 Flex 매뉴얼 섹션.

15 YACC와의 인터페이스

Flex의 주요 용도 중 하나는 YACC Parser-Generator의 동반자입니다. YACC Parsers는 Yylex ()라는 루틴을 호출하여 다음 입력 토큰을 찾을 것으로 기대합니다. 이 루틴은 다음 토큰의 유형을 반환하고 글로벌 yylval에 관련 값을 부여해야합니다. YACC와 함께 Flex를 사용하려면 YACC에 나타나는 모든 %토큰의 정의를 포함하는 파일 y.tab.h를 생성하도록 지시하기 위해 YACC에 대한`-d '옵션을 지정합니다. 이 파일은 Flex 스캐너에 포함됩니다. 예를 들어, 토큰 중 하나가 Tok_number 인 경우 스캐너의 일부는 다음과 같이 보일 수 있습니다.

     %{
     #include "y.tab.h"
     %}

     %%

     [0-9]+        yylval = atoi( yytext ); return TOK_NUMBER;

다른 팁

yylval을 통해 문자열 또는 복잡한 유형을 반환하는 열쇠는 Y.Tab.h 파일에서 YACC가 만든 Yystype Union입니다. YYSTYPE는 YACC 소스 파일 내에 정의 된 각 유형의 토큰에 대해 멤버와의 통합입니다. 예를 들어 YACC 소스 파일의 기호 토큰과 관련된 문자열을 반환하려면이 Yystype Union을 사용하여 선언합니다. %노동 조합 YACC 소스 파일에서 :

/*** Yacc's YYSTYPE Union ***/

/* The yacc parser maintains a stack (array) of token values while
   it is parsing.  This union defines all the possible values tokens
   may have.  Yacc creates a typedef of YYSTYPE for this union. All
   token types (see %type declarations below) are taken from
   the field names of this union.  The global variable yylval which lex
   uses to return token values is declared as a YYSTYPE union.
 */

    %union {
        long int4;              /* Constant integer value */
        float fp;               /* Constant floating point value */
        char *str;              /* Ptr to constant string (strings are malloc'd) */
        exprT expr;             /* Expression -  constant or address */
        operatorT *operatorP;   /* Pointer to run-time expression operator */
    };

%type <str> SYMBOL

그런 다음 Lex 소스 파일에는 기호 토큰과 일치하는 패턴이 있습니다. 기호를 나타내는 실제 문자열을 반환하는 것은 해당 규칙과 관련된 코드의 책임입니다. 일치하는 각 토큰에 대해 재사용되는 정적 버퍼이기 때문에 YYText 버퍼에 포인터를 전달할 수는 없습니다. 일치하는 텍스트를 반환하려면 정적 yytext 버퍼를 _strdup ()와 함께 힙에 복제하고 yyval.str를 통해 전달 된이 문자열에 대한 포인터를 복제해야합니다. 그런 다음 YACC 규칙은 힙이 완료 될 때 힙 할당 된 문자열을 풀어야하는 기호 토큰의 책임과 일치합니다.

[A-Za-z_][A-Za-z0-9_]*  {{
    int i;

    /*
    * condition letter followed by zero or more letters
    * digits or underscores
    *      Convert matched text to uppercase
    *      Search keyword table
    *      if found
    *          return <keyword>
    *      endif
    * 
    *      set lexical value string to matched text
    *      return <SYMBOL>
    */

    /*** KEYWORDS and SYMBOLS ***/
    /* Here we match a keywords or SYMBOL as a letter
    * followed by zero or more letters, digits or 
    * underscores.
    */

    /* Convert the matched input text to uppercase */
    _strupr(yytext);         /* Convert to uppercase */

    /* First we search the keyword table */
    for (i = 0; i<NITEMS(keytable); i++) {
        if (strcmp(keytable[i].name, yytext)==0)
            return (keytable[i].token);
    }

    /* Return a SYMBOL since we did not match a keyword */
    yylval.str=_strdup(yytext);
    return (SYMBOL);
}}

컨텍스트 설정

구문 분석 (입력 텍스트가 지정된 문법을 따르는 지 확인)은 두 단계로 구성됩니다.

  1. lex 또는 flex와 같은 도구에 의해 수행되는 토큰 화, 인터페이스 yylex ()) 및
  2. 1 단계 (사용자 지정 문법에 따라)에서 생성 된 토큰 스트림을 구문 분석하는데, 이는 인터페이스 yyparse ()와 함께 Bison/YACC와 같은 도구에 의해 수행됨).

하는 동안 1 단계, 입력 스트림이 주어지면 yylex ()에 대한 각 호출은 토큰 (숯 문자열)을 식별하고 yytext는 해당 문자열의 첫 번째 문자를 가리 킵니다. 예를 들어 : "int x = 10;"의 입력 스트림. 그리고 C 언어를 준수하는 토큰 화에 대한 LEX 규칙을 사용하면 yylex ()에 대한 처음 5 개의 호출은 다음 5 개의 토큰 "int", "x", "=", "10", ";" 그리고마다 yytext가 돌아올 때마다 돌아올 것입니다.

2 단계, Parser (YACC라고 언급 한)는 토큰을 얻기 위해 매번이 Yylex 기능을 부르는 프로그램 이며이 토큰을 사용하여 문법 규칙과 일치하는지 확인합니다. Yylex에 대한 이러한 호출은 일부 정수 코드로 토큰을 반환합니다. 예를 들어 이전 예제에서 Yylex ()에 대한 처음 5 개의 호출은 다음 정수를 파서로 반환 할 수 있습니다 : 유형, ID, EQ_OPERATOR 및 Integer (실제 정수 값이 일부 헤더 파일에 정의 됨).

이제 모든 파서가 볼 수있는 정수 코드는 때때로 유용하지 않을 수 있습니다. 예를 들어, 실행중인 예제에서 유형을 int에, ID를 일부 기호 테이블 포인터에, 정수를 10 진수로 연결할 수 있습니다. 이를 위해 사용자 정의 유형이있을 수 있습니다. Lex 환경 에서이 값은 yylval로 액세스됩니다.

예를 들어, 실행중인 예제에 따라 Yylex가 10을 식별하는 다음 규칙을 가질 수 있습니다.

[0-9]+   {  yylval.intval = atoi(yytext); return INTEGER; }

그리고 다음 x를 식별하기 위해

[a-zA-Z][a-zA-Z0-9]*   {yylval.sym_tab_ptr = SYM_TABLE(yytext); return ID;}

여기서는 값 (또는 yylval) 유형을 int (intval)와 int* 포인터 (sym_tab_ptr)를 포함하는 노조로 정의했습니다.

그러나 YACC 세계 에서이 값은 $ n으로 식별 / 액세스됩니다. 예를 들어, 특정 할당 문을 식별하려면 다음 YACC 규칙을 고려하십시오.

TYPE ID '=' VAL:  { //In this action part of the yacc rule, use $2 to get the symbol table pointer associated with ID, use $4 to get decimal 10.}

당신의 질문에 대답합니다

YACC World에서 특정 토큰 (Lex World와 관련된)의 Yytext 값에 액세스하려면 오랜 친구 값을 Folowing으로 사용하십시오.

  1. 다른 필드를 추가하기 위해 Union 유형의 값을 보강하십시오 char* lex_token_str
  2. lex 규칙에서 yylval.lex_token_str = strdup (yytext)
  3. 그런 다음 YACC에서는 적절한 $ n을 사용하여 액세스하십시오.
  4. 단일 값의 토큰에 액세스하려는 경우 (예 : LEX 식별 토큰 ID의 경우, 파서는 이름과 기호 테이블 포인터 모두에 액세스 할 수 있습니다). char* (이름) 및 int* (Symtab 포인터 용)를 포함하는 구조 멤버.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top