2009-06-04 16 views
12

YACC (veya benim durumum MPPG) çıktısını bir Özet Sözdizimi Ağacı (AST) yapmak mümkün mü?YACC çıktısını bir AST (simge ağacı) yapılıyor

Okumakta olduğum her şey, YACC'nin bunu yapmasını kolaylaştıracağını gösteriyor, ancak ağaçtaki bir düğümü ne zaman yapacağınızı nasıl anladığınızı görmek için uğraşıyorum.

cevap

5

the manual'a baktınız (noktayı bulmak için "parse tree" için arama yapınız)? Düğüm oluşturmayı, sol ve sağ torunlarınızın 1 $ ve 3 $ ile ya da her ne olursa olsun bir eylemde bulundurmasını önerir. Bu durumda yacc, elinizdeki işi yapmak yerine ağacı sizin adınıza hareket ettirir.

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

: Eğer ağacında bir nesne oluşturur fonksiyonu node ile soyut sözdizimi ağacı var varsayarsak

: Hao'nun noktada ve the manual itibaren Genişleyen

+1

sayesinde, lexx & yacc kitapta önce bu görmüştü FLEX lexer içinde DÖNÜŞÜ önce oluşturulur. Ama bir çeşit çıkmaz olarak yazdım. Hepsini bir arada takmak için , % union birleşim etiketinde tanımlanan LexType'ı değiştirmeniz gerekir { private State _state; ... LexValue (Durum durumu, object child1, object child2) {...} } } Bu, bir ağaç düğümünü durumunuz olarak kaydetmenize olanak tanır. Daha sonra $$ = new LexValue (State.SchemaImport, 3 $, $ 5) kullanarak verileri ona atayabilirsiniz; Not: Lexer'ın jeton verisini de bu yapıya doğru itmesi gerekir. Nasıl olduğunu bildiğiniz zaman kolay ... – Sprotty

6

, aşağıdaki gibi bir şey yapmak istiyorum Bu kod, "Bir artı ile ifade ayrıştırırken, $1/$3 sol ve sağ soyundan alın ve bunları düğüme argümanlar olarak kullanın. Çıktının $$ (dönüş değeri) ifadesine kaydedin.

$$ (manuel):

bir değer döndürmek için, işlem, normal olarak pseudovariable `` $$ '' Bazı değere ayarlar.

Neyse bir C++ gramer (kurallar birkaç yüz ..) ile oynarken

1

diğer cevaplar dilbilgisi değiştirmek teklif, bu hata ayıklama yeniden tanımlayarak, biz, bunu otomatik olarak yapabilirsiniz yapılabilir değil makrolar. Bu kodda, biz YYDEBUG ile actived YY_SYMBOL_PRINT yeniden tanımlayan:

%{ 

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] = ' '; 
    } 
} 

yapraklar sadece