Syntax Flex&;Bison:打印解析树

Syntax Flex&;Bison:打印解析树,syntax,tree,bison,flex-lexer,yacc,Syntax,Tree,Bison,Flex Lexer,Yacc,基本上,我有一个任务,我需要为C-做一个编译器,但我们要分5个步骤来完成。其中一个步骤是将BNF语法转换为bison,然后打印一个包含已编译内容的树。让我解释一下: BNF语法 1. program→declaration-list 2. declaration-list→declaration-list declaration | declaration 3. var-declaration| fun-declaration 4. var-declaration→type-specifierI

基本上,我有一个任务,我需要为C-做一个编译器,但我们要分5个步骤来完成。其中一个步骤是将BNF语法转换为bison,然后打印一个包含已编译内容的树。让我解释一下:

BNF语法

1. program→declaration-list
2. declaration-list→declaration-list declaration | declaration
3. var-declaration| fun-declaration
4. var-declaration→type-specifierID;| type-specifierID[NUM];
5. type-specifier→int | void
6. fun-declaration→type-specifierID(params)compound-stmt
7. params→param-list| void
8. param-list→param-list,param | param
9. param→type-specifierID | type-specifierID[]
10. compound-stmt→{local-declarations statement-list}
11. local-declarations→local-declarations var-declaration| empty
12. statement-list→statement-list statement| empty
13. statement→expression-stmt| compound-stmt| selection-stmt | iteration-stmt | return-stmt
14. expession-stmt→expression;| ;
15. selection-stmt→if(expression)statement| if(expression) statement else statement
16. iteration-stmt→while(expression)statement
17. return-stmt→return; | return expression;
18. expression→var=expression| simple-expression
19. var→ID| ID[expression]
20. simple-expression→additive-expression relop additive-expression| additive-expression
21. relop→<=| <| >| >=| ==| !=
22. additive-expression→additive-expression addop term| term
23. addop→+| -
24. term→term mulop factor| factor
25. mulop→*| /
26. factor→(expression)| var| call| NUM
27. call→ID(args)
28. args→arg-list| empty
29. arg-list→arg-list,expression| expression
基于树的示例代码

/* A program */

void main(void)
{
    int x; int y;
    x = input();
    y = x + 5;
}

我已将BNF语法转换为实际的.y文件,但在打印出消息的确切位置时遇到了问题。通常,一本语法书会在完成后打印出来

您呈现的所需输出是解析树的预排序遍历的结果

但是,bison生成一个自底向上的解析器,当节点的子树完成时,该解析器为解析树中的节点执行语义操作。因此,在语义操作中打印节点会生成一个后序遍历。我想这就是你最后一句话的意思

虽然有各种可能的解决方案,但最简单的可能是在解析过程中构造解析树,然后在解析结束时打印出来。(您可以在开始生产的语义操作中打印树,但这有时会导致打印错误输入的解析树。最好是返回解析树的根,并在验证解析成功后从主程序打印它。)


我不知道“构造一个解析树”在你的项目预期进展中的位置。解析树在大多数应用程序中几乎没有用处。更常见的是抽象语法树(AST)的构造,它从解析中省略了许多不相关的细节(如单元生成)。您可以从解析树构造AST,但通常在解析操作中直接构造AST更简单:代码看起来非常相似,但实际上很少,因为不必为单元生产构建树节点。

嘿,感谢您的回复!很难理解你的答案,但我正在努力!你能给我一个类似的解决方案吗?该项目由5个部分组成,第一部分是在.fl文件中编写一些正则表达式,查找C的“if”、“else”、“;”等,并返回一个句子“find an”if“on line.#”。现在,第二部分是在.y文件中编写bnf语法(猜测这是正确的术语),但现在在查找特定代码时打印输出。我已经研究过AST,但我认为这不是我需要的。@pigufilms:如果你只是在该产品的语义动作中打印每个产品,你会发现该产品遵循其组成部分。这就是自底向上解析的本质。也许这就是你的教授想要的;我不知道。但是如果你想按你指定的顺序打印,你需要建立一棵树,然后遍历它。我想打印我指定的顺序。基本上,如果你仔细观察它,不管它是什么语法,它都会立即执行一个代码(在我的例子中是printf)。但我正在努力解决这个问题,因为它没有按我希望的那样工作。@PiguFilms:它按我声明的顺序打印,因为这是自底向上解析的本质。一旦您了解了它为什么按顺序打印,您就会了解自底向上解析是如何工作的。这是一个有用的教训。但是让它按您希望的顺序打印意味着保存解析树。如果,就像你说的,你仔细看。呃,似乎找不到可能的答案。尝试用不同的变量保存解析树,并自己“制作”树,但没有成功。有什么提示吗?
%{
    #include <stdio.h>
    #include <stdlib.h>
    extern int yylex();
    extern int yyparse();
    void yyerror(const char* s);
 %}

%token  T_IF T_ELSE T_INT T_RETURN T_VOID T_WHILE 
        T_GREAT T_GREATEQ T_SMALL T_SMALLEQ T_COMPARE T_NOTEQ 
        T_COMM T_ID T_NUM

%%
program: declaration-list       { printf("program"); }
    ;

declaration-list: declaration-list declaration
    | declaration
    ;

declaration: var-declaration
    | fun-declaration
    ;

var-declaration: type-specifier T_ID ';'
    | type-specifier T_ID'['T_NUM']' ';'
    ;

type-specifier: T_INT
    | T_VOID
    ;

fun-declaration: type-specifier T_ID '('params')' compound-stmt
    ;

params: param-list 
    | T_VOID
    ;

param-list: param-list',' param 
    | param
    ;

param: type-specifier T_ID
    | type-specifier T_ID'['']'
    ;

compound-stmt: '{' local-declarations statement-list '}'
    ;

local-declarations: local-declarations var-declaration
    |
    ;

statement-list: statement-list statement 
    |
    ;

statement: expression-stmt 
    | compound-stmt 
    | selection-stmt 
    | iteration-stmt 
    | return-stmt 
    ;

expression-stmt: expression ';'
    | ';'
    ;

selection-stmt: T_IF '('expression')' statement
    | T_IF '('expression')' statement T_ELSE statement
    ;

iteration-stmt: T_WHILE '('expression')' statement 
    ;

return-stmt: T_RETURN ';'
    | T_RETURN expression ';'
    ;

expression: var '=' expression 
    | simple-expression
    ;

var: T_ID                   { printf("\nterm\nfactor_var\nvar(x)"); }
    | T_ID '['expression']'
    ;

simple-expression: additive-expression relop additive-expression
    | additive-expression
    ;

relop: T_SMALLEQ
    | T_SMALL
    | T_GREAT
    | T_GREATEQ
    | T_COMPARE
    | T_NOTEQ
    ;

additive-expression: additive-expression addop term 
    | term                                  
    ;

addop: '+'      { printf("\naddop(+)"); }
    | '-'       { printf("\naddop(-)"); }
    ;

term: term mulop factor                             
    | factor                                
    ;

mulop: '*'      { printf("\nmulop(*)"); }
    | '/'       { printf("\nmulop(/)"); }
    ;

factor: '('expression')'    { printf("\nfactor1"); }
    | var               
    | call          
    | T_NUM                 { printf("\nterm\nfactor(5)"); }
    ;

call: T_ID '('args')'       { printf("\ncall(input)"); }
    ;

args: arg-list
    |                       { printf("\nargs(empty)"); }
    ;

arg-list: arg-list',' expression
    | expression
    ;
%%

int main(void) {
    return yyparse();
}

void yyerror(const char* s) {
    fprintf(stderr, "Parse error: %s\n", s);
    exit(1);
}
program
    declaration_list
        declaration
            fun_definition(VOID-main)
                params_VOID-compound
                    params(VOID)
                    compound_stmt
                        local_declarations
                            local_declarations
                                local_declarations(empty)
                                var_declaration(x)
                                    type_specifier(INT)
                            var_declaration(y)
                                type_specifier(INT)
                        statement_list
                            statement_list
                                statement_list(empty)
                                statement
                                    expression_stmt
                                        expression
                                            var(x)
                                        expression
                                            simple_expression
                                                additive_expression
                                                    term
                                                        factor
                                                            call(input)
                                                                args(empty)
                        statement
                            expression_stmt
                                expression
                                    var(y)
                                expression
                                    simple_expression
                                        additive_expression(ADDOP)
                                            additive_expression
                                                term
                                                    factor_var
                                                        var(x)
                                                addop(+)
                                                term
                                                factor(5)
/* A program */

void main(void)
{
    int x; int y;
    x = input();
    y = x + 5;
}