2016-11-02 20 views
0

flex와 bison을 사용하여 스캐너와 파서를 사용할 준비가되었습니다. 파서는 행동에 직접 나무를 구축하고, 할Bison에서 사용자 정의 유형을 사용할 때 액세스 식별자 내용

은 그래서

#define YYSTYPE_IS_DECLARED 
typedef STreeNode* YYSTYPE; 

를 사용하고 STreeNode 및 I라는 구조체를 생성 된 구조체는 다음과 같이 있습니다

typedef struct tagSTreeNode 
{ 
    EOperationType type; 
    int count; 
    struct tagSTreeNode **children; 
    char *string; 
} STreeNode; 

40 개의 토큰, 그리고 모든 규칙에 대해 나는 비슷한 것을 가짐

unlabeled_statement: 
     assignment               {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | function_call_statement           {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | goto                {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | return               {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | conditional              {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | repetitive              {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     | empty_statement             {$$ = createNode(eUNLABELED_STATEMENT, 1, $1);} 
     ; 

createNode functi 에

STreeNode *createNode(EOperationType type, int count, ...) { 

나무가 잘 작동합니다. 문제는 변수 이름, 함수 이름 등의 실제 값에 액세스하는 것입니다. YYSTYPE은 구조체이므로 $ x에는 구조체의 char * string 요소에 저장하려는 문자열 값이 없습니다.

IDENTIFIER라는 % 토큰과 INTEGER라는 다른 토큰이 있는데, 그 토큰은 원하는 값을 받아야합니다.

연구하면서, 특정 유형의 모든 토큰을 갖기 위해 조합 {}을 사용할 수 있다는 것을 발견했습니다. 아마 그게 도움이 될 수 있니? 그렇다면 모든 토큰 유형을 반드시 지정해야합니다. 어떻게 구현 될 수 있습니까?

yytext는 어떻습니까? 이 목표를 달성하는 데 사용할 수는 없습니까?

감사합니다.

--- 편집 -

그래서

%union { 
    char *string; 
    STreeNode *node; 
} 

를 만들어 그 중 하나가 될 수있는 모든 단자와 비 터미널 유형을 지정했습니다. 노드는 여전히 작동하지만 (예 : $ 1을 (를) 사용하는) 문자열은 null을 반환합니다.

스캐너에서 무엇인가를 변경해야합니까? 스캐너의 종류 :

[a-zA-Z][a-z0-9A-Z]*  { return IDENTIFIER; } 
[0-9]+      { return INTEGER; } 

다시 한번 감사드립니다.

+0

bison을 사용하는 경우 왜이 태그가 'yacc'입니까? –

+0

문제와 관련이없는 작은 질문이지만, 필요없는 노드를 만드는 이유는 무엇입니까? 'conditioal'을위한 새로운 노드를 생성하는 대신'$$'를'$ 1'로 설정하는 것만 큼 어떨까요? 그러면 트리가 단순 해지고 노드 수가 줄어 듭니다. –

+0

@ScottHunter'flex' 태그는 [Apache Flex] (http://flex.apache.org/) 용이며 GNU lex 클론이 아니므로 제거했습니다. –

답변

0

토큰에 유형이 설정된 경우 렉서는 yylval을 해당 유형으로 설정해야합니다. 다음과 같음 :

[a-zA-Z][a-z0-9A-Z]*  { yylval.string = strdup(yytext); return IDENTIFIER; } 
[0-9]+      { yylval.string = strdup(yytext); return INTEGER; }