2009-06-04 109 views
12

是否有可能使YACC(或我是我的案例MPPG)输出抽象语法树(AST)。使YACC输出一个AST(令牌树)

我正在阅读的所有东西都表明它很容易让YACC做到这一点,但我很努力想知道如何知道在构建它时如何在树中移动节点。

回答

5

你看过the manual(搜索“解析树”来找到该点)?它建议将节点创建放在一个动作中,左右后裔的价格分别为1美元和3美元,或者任何可能的情况。在这种情况下,yacc会代表您以树的形式向上移动,而不是手动进行。

+1

谢谢你,我会在lexx&YACC书见过这个在返回之前被创建。但我会把它写成死胡同。 为了让它全部挂在一起,你需要修改联合标记中定义的LexType %union private_state; ... LexValue(状态,对象child1,对象child2){...} } 这允许您将树节点存储为您的状态。 然后,您可以使用$$别名 $$ = new LexValue(State.SchemaImport,$ 3,$ 5)将数据分配给它。 注意:词法分析器还需要将其令牌数据推送到此结构中。 简单,当你知道如何... – Sprotty 2009-06-04 19:17:04

6

扩大对郝的观点,并从the manual,你想要做的东西像下面这样:

假设你有一个功能node您的抽象语法树,会在树中的对象:

expr : expr '+' expr 
    { 
    $$ = node('+', $1, $3); 
    } 

这段代码翻译为“当用一个加号解析表达式时,取左边和右边的后代$1/$3并将它们用作节点的参数。将表达式的输出保存到$$(返回值)。

$$(从手动):

返回一个值,该动作通常 设置pseudovariable``$$ '' 一些 值。

1

其他的答案建议修改语法与C++语法(规则几百..)

幸运玩的时候,这是不可行的,我们可以自动做到这一点,通过重新定义调试宏。 在这段代码中,我们将重新定义YY_SYMBOL_PRINTYYDEBUG actived:

%{ 

typedef struct tree_t { 
    struct tree_t **links; 
    int nb_links; 
    char* type; // the grammar rule 
}; 

#define YYDEBUG 1 
//int yydebug = 1; 

tree_t *_C_treeRoot; 
%} 
%union tree_t 

%start program 

%token IDENTIFIER 
%token CONSTANT 

%left '+' '-' 
%left '*' '/' 
%right '^' 

%% 
progam: exprs { _C_treeRoot = &$1.t; } 
    | 
    | hack 
    ; 

exprs: 
    expr ';' 
    | exprs expr ';' 
    ; 


number: 
    IDENTIFIER 
    | '-' IDENTIFIER 
    | CONSTANT 
    | '-' CONSTANT 
    ; 

expr: 
    number 
    | '(' expr ')' 
    | expr '+' expr 
    | expr '-' expr 
    | expr '*' expr 
    | expr '/' expr 
    | expr '^' expr 
    ; 

hack: 
    { 
    // called at each reduction in YYDEBUG mode 
    #undef YY_SYMBOL_PRINT 
    #define YY_SYMBOL_PRINT(A,B,C,D) \ 
     do { \ 
      int n = yyr2[yyn]; \ 
      int i; \ 
      yyval.t.nb_links = n; \ 
      yyval.t.links = malloc(sizeof *yyval.t.links * yyval.t.nb_links);\ 
      yyval.t.str = NULL; \ 
      yyval.t.type = yytname[yyr1[yyn]]; \ 
      for (i = 0; i < n; i++) { \ 
       yyval.t.links[i] = malloc(sizeof (YYSTYPE)); \ 
       memcpy(yyval.t.links[i], &yyvsp[(i + 1) - n], sizeof(YYSTYPE)); \ 
      } \ 
     } while (0) 

    } 
    ; 
%% 

#include "lexer.c" 


int yyerror(char *s) { 
    printf("ERROR : %s [ligne %d]\n",s, num_ligne); 
    return 0; 
} 


int doParse(char *buffer) 
{ 
    mon_yybuffer = buffer; 
    tmp_buffer_ptr = buffer; 
    tree_t *_C_treeRoot = NULL; 
    num_ligne = 1; 
    mon_yyptr = 0; 

    int ret = !yyparse(); 

    /////////**** 
      here access and print the tree from _C_treeRoot 
    ***/////////// 
} 


char *tokenStrings[300] = {NULL}; 
char *charTokenStrings[512]; 

void initYaccTokenStrings() 
{ 
    int k; 
    for (k = 0; k < 256; k++) 
    { 
     charTokenStrings[2*k] = (char)k; 
     charTokenStrings[2*k+1] = 0; 
     tokenStrings[k] = &charTokenStrings[2*k]; 
    } 
    tokenStrings[CONSTANT] = "CONSTANT"; 
    tokenStrings[IDENTIFIER] = "IDENTIFIER"; 


    extern char space_string[256]; 

    for (k = 0; k < 256; k++) 
    { 
     space_string[k] = ' '; 
    } 
} 

的叶子刚刚在FLEX词法分析器