{"id":9635,"date":"2024-01-01T15:01:00","date_gmt":"2024-01-01T07:01:00","guid":{"rendered":"https:\/\/www.orczhou.com\/?p=9635"},"modified":"2025-12-26T14:20:34","modified_gmt":"2025-12-26T06:20:34","slug":"flex-bison-4-a-sophisticated-program-part-2","status":"publish","type":"post","link":"https:\/\/www.orczhou.com\/index.php\/2024\/01\/flex-bison-4-a-sophisticated-program-part-2\/","title":{"rendered":"flex\/bison\u7cfb\u52174\uff1a\u66f4\u590d\u6742\u7684\u4e00\u4e2a\u7f16\u8bd1\u7a0b\u5e8f\u5b9e\u73b0\uff08\u4e0b\uff09"},"content":{"rendered":"\n\n\n\n<p style=\"margin-top:4px\">\u8fd9\u662f\u4e00\u4e2a\u7cfb\u5217\u6587\u7ae0\uff0c\u65e8\u5728\u4e86\u89e3\u5982\u4f55\u4f7f\u7528Flex\/Lex\u548cYacc\/Bison\u8fdb\u884c\u8bcd\u6cd5\u548c\u8bed\u6cd5\u89e3\u6790\u3002\u5728\u524d\u9762\uff0c\u5df2\u7ecf\u5b8c\u6210\u4e86<a href=\"https:\/\/www.orczhou.com\/index.php\/2023\/11\/learning-flex-bison-01\/\">\u4f7f\u7528Lex\/flex\u505a\u57fa\u7840\u7684\u8bcd\u6cd5\u89e3\u6790<\/a>\u3001<a href=\"https:\/\/www.orczhou.com\/index.php\/2023\/11\/using-yacc-bison-for-grammer\/\">\u5b9e\u73b0\u4e00\u4e2a\u7b80\u5355\u7684\u8ba1\u7b97\u5668<\/a>\u3001<a href=\"https:\/\/www.orczhou.com\/index.php\/2024\/01\/flex-bison-3-a-sophisticated-program-part-1\/\">flex\/bison\u7cfb\u52173\uff1a\u66f4\u590d\u6742\u7684\u4e00\u4e2a\u7f16\u8bd1\u7a0b\u5e8f\u5b9e\u73b0\uff08\u4e0a\uff09<\/a>\u3002\u5728<a href=\"https:\/\/www.orczhou.com\/index.php\/2024\/01\/flex-bison-3-a-sophisticated-program-part-1\/\">\u4e0a\u7bc7<\/a>\u4e2d\uff0c\u5df2\u7ecf\u5b8c\u6210\u8bed\u6cd5\u89c4\u5219\u3001\u4e3b\u8981\u7684\u6570\u636e\u7ed3\u6784\u8bbe\u8ba1\u3002\u8fd9\u91cc\u5c31\u7ee7\u7eed\u5b8c\u6210\u7a0b\u5e8f\uff0c\u6700\u540e\u7f16\u8bd1\u6d4b\u8bd5\u3002<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\u56de\u987e<\/h4>\n\n\n\n<p>\u8fd9\u4e2a\u7cfb\u5217\u6211\u4eec\u9700\u8981\u901a\u8fc7flex\/bison\u5b9e\u73b0\u4e00\u4e2a\u7f16\u8bd1\u7a0b\u5e8f\uff0c\u80fd\u591f\u5b9e\u73b0\u4e00\u79cd\u7b80\u5355\u7684\u7a0b\u5e8f\u8bed\u8a00\uff0c\u8fd9\u4e2a\u7a0b\u5e8f\u8bed\u8a00\u5305\u542b\u4e86\uff1a\u57fa\u7840\u8fd0\u7b97\u3001\u53d8\u91cf\u4e0e\u8d4b\u503c\u3001\u8868\u8fbe\u5f0f\u8ba1\u7b97\u3001<code>if<\/code>\u8bed\u53e5\u3001<code>while<\/code>\u8bed\u53e5\u3001<code>print<\/code>\u8bed\u53e5\u7b49\u3002\u4f8b\u5982\uff0c\u4f7f\u7528\u8be5\u7a0b\u5e8f\u8bed\u8a00\uff0c\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u5982\u4e0b\u7a0b\u5e8f\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">i = 1;\na = 0;\nwhile ( a &lt; 100 ) {\n  i = i + 1;\n  a = a + i;\n}\nprint i;<\/code><\/pre>\n\n\n\n<p> \u8be5\u7a0b\u5e8f\u89e3\u51b3\u7684\u95ee\u9898\u662f\uff1a\u5728\u81ea\u7136\u6570\u5e8f\u5217\uff081\u30012\u30014\u2026\uff09\u4e2d\uff0c\u524d\u9762\u591a\u5c11\u4e2a\u81ea\u7136\u6570\u7684\u548c\u9996\u6b21\u5927\u4e8e100\u3002\u4f60\u53ef\u4ee5\u4f7f\u7528\u4e0a\u9762\u5b9a\u4e49\u7684\u8bed\u8a00\uff0c\u7f16\u5199\u81ea\u5df1\u7684\u7a0b\u5e8f\u3002<\/p>\n\n\n\n<p>\u597d\u4e86\uff0c\u63a5\u7740\u524d\u9762\u4e09\u7bc7\u7684\u5185\u5bb9\uff0c\u6211\u4eec\u7ee7\u7eed\u5b8c\u6210\u8be5\u8bed\u8a00\u7684\u7f16\u8bd1\u7a0b\u5e8f\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\u4e3b\u8981\u7684\u51fd\u6570\u5b9e\u73b0<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">build_node\u51fd\u6570<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">t_node* build_node(enum NODETYPE nt,t_node* left,t_node* right, int i){\n    debug_print(__FILE__,__LINE__,__func__,\"\");\n    t_node *t_n;\n    t_n = NULL;\n    t_n = (t_node *)malloc(sizeof(t_node));\n    if (t_n == NULL){\n        printf(\"Out of Memory\\n\");\n        exit(1);\n    }\n    t_n-&gt;nt = nt;\n    t_n-&gt;left = left;\n    t_n-&gt;right = right;\n    t_n-&gt;i = i;\n    return t_n;\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">exec_node\u51fd\u6570<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">int exec_node(t_node *n){\n    if( n == NULL ) return 0;\n    debug_print(__FILE__,__LINE__,__func__,\"enter exec_node\");\n\n    switch(n-&gt;nt){\n        case NT_INTEGER:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_INTEGER node\");\n\t    break;\n        case NT_VAR_NAME:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_VAR_NAME node\");\n\t    break;\n        case NT_O_ADD:\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) + get_node_ret(n-&gt;right);\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_O_ADD node\");\n\t    break;\n        case NT_O_MINUS:\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) - get_node_ret(n-&gt;right);\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_O_MINUS node\");\n            break;\n        case NT_O_MULTIPLY:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_O_MULTIPLY node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) * get_node_ret(n-&gt;right);\n            break;\n        case NT_BOOL_EXPR_GT:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_BOOL_EXPR_GT node\");\n            n-&gt;i = 0;\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            if (get_node_ret(n-&gt;left) &gt; get_node_ret(n-&gt;right) )\n            { n-&gt;i = 1 ; }\n            break;\n        case NT_BOOL_EXPR_LT:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_BOOL_EXPR_LT node\");\n            n-&gt;i = 0;\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            if (get_node_ret(n-&gt;left) &lt; get_node_ret(n-&gt;right) )\n            { n-&gt;i = 1 ; }\n            break;\n        case NT_IF:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_IF node\");\n            exec_node(n-&gt;left);\n            if (get_node_ret(n-&gt;left)){\n                exec_node(n-&gt;right);\n            }\n            break;\n        case NT_WHILE:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_WHILE node\");\n            exec_node(n-&gt;left);\n            while( get_node_ret(n-&gt;left)  ){\n                exec_node(n-&gt;right);\n                exec_node(n-&gt;left);\n            }\n            break;\n        case NT_PRINT:\n            debug_print(__FILE__,__LINE__,__func__,\"NT_PRINT node\");\n            exec_node(n-&gt;left);\n            printf(\"print '%d'\",get_node_ret(n-&gt;left));\n            break;\n        case NT_ASSIGNMENT:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_ASSIGNMENT node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            var[n-&gt;left-&gt;i - 'a'] = get_node_ret(n-&gt;right);\n            break;\n        case NT_STATEMENT_BLOCK:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_STATEMENT_BLOCK node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            break;\n        case NT_PROGRAM:\n    \t    debug_print(__FILE__,__LINE__,__func__,\"NT_PROGRAM node\");\n            break;\n    }\n\n    return 0;\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">\u5185\u5b58\u91ca\u653e<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">int free_node(t_node *n){\n    if( n != NULL ) {\n        free_node(n-&gt;left);\n        free_node(n-&gt;right);\n    }\n    free(n);\n    return 0;\n}<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">\u5de5\u5177\u51fd\u6570debug_print<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">void debug_print(const char *fname, int lineno, const char *fxname, const char *debug_info){\n    #ifdef cal_DEBUG\n    printf(\"\\n debug: enter at line %d in %s,function: %s info: %s\\n\",\n        lineno,\n        fname,\n        fxname,\n\t\tdebug_info\n        );\n\t#endif\n}<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u8865\u5145\u8bed\u6cd5\u6587\u4ef6\u7684Action\u90e8\u5206<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">%%\nprogram:  statement_block\n            {\n                exec_node($1);\n                free_node($1);\n                printf(\"\\n job done! \\n\");\n            }\n;\n\nstatement_block: %empty\n            {\n                $$ = build_node(\n                        NT_STATEMENT_BLOCK,\n                        NULL,\n                        NULL,\n                        NULL,\n                        0\n                        );\n                debug_print(__FILE__,__LINE__,__func__,\"\");\n            }\n\n        | statement_block statement\n            { $$ = build_node(\n                    NT_STATEMENT_BLOCK,\n                    $1,\n                    $2,\n                    NULL,\n                    0\n                    );\n\n                debug_print(__FILE__,__LINE__,__func__,\"\");\n            }\n;\n\nstatement: assignment { $$ = $1; }\n        | print_func  { $$ = $1; }\n        | if_block    { $$ = $1; }\n        | while_block { $$ = $1; }\n;\n\nif_block: IF '(' bool_expr ')' '{' statement_block '}'\n            {\n                $$ = build_node(\n                        NT_IF,\n                        $3,\n                        $6,\n                        NULL,\n                        0\n                        );\n            }\n\nwhile_block: WHILE '('  bool_expr ')' '{' statement_block '}'\n            {\n                $$ = build_node(\n                        NT_WHILE,\n                        $3,\n                        $6,\n                        NULL,\n                        0\n                        );\n            }\n\nassignment: VAR_NAME '=' expression ';' { $$ = build_node(\n                                                    NT_ASSIGNMENT,\n                                                    build_node(NT_VAR_NAME,NULL,NULL,NULL,(int)$1),\n                                                    $3,\n                                                    NULL,\n                                                    0);\n                                        }\n\nprint_func : PRINT expression ';'   {  $$ = build_node(NT_PRINT,$2,NULL,NULL,0); }\n\nbool_expr: expression GT expression {  $$ = build_node(NT_BOOL_EXPR_GT,$1,$3,NULL,0);}\n        |  expression LT expression {  $$ = build_node(NT_BOOL_EXPR_LT,$1,$3,NULL,0);}\n\nexpression: INTEGER { $$ = build_node(NT_INTEGER,NULL,NULL,NULL,$1); }\n        | VAR_NAME  { $$ = build_node(NT_VAR_NAME,NULL,NULL,NULL,(int)$1); }\n        | expression O_ADD expression {  $$ = build_node(NT_O_ADD,$1,$3,NULL,0);}\n        | expression O_MINUS expression  {  $$ = build_node(NT_O_MINUS,$1,$3,NULL,0);}\n        | expression O_MULTIPLY expression {  $$ = build_node(NT_O_MULTIPLY,$1,$3,NULL,0);}\n\n\n%%<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">cal.header.h<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">enum NODETYPE{\n    NT_STATEMENT,\n    NT_IF,\n    NT_WHILE,\n    NT_PROGRAM,\n    NT_STATEMENT_BLOCK,\n    NT_O_ADD,\n    NT_O_MINUS,\n    NT_O_MULTIPLY,\n    NT_INTEGER,\n    NT_VAR_NAME,\n    NT_BOOL_EXPR_GT,\n    NT_BOOL_EXPR_LT,\n    NT_PRINT,\n    NT_ASSIGNMENT\n};\n\ntypedef struct t_node{\n    enum NODETYPE nt;\n    struct t_node* left;\n    struct t_node* right;\n    struct t_node* rrnode;\n    int i;  \/\/ for NT_INTEGER NT_VAR_NAME node\n}t_node;<\/code><\/pre>\n\n\n\n<p>\u6709\u4e86\u8fd9\u4e9b\u4fe1\u606f\uff0c\u5c31\u53ef\u4ee5\u4f7f\u7528<code>NODETYPE<\/code>\u6765\u6784\u5efa\uff0c\u89e3\u6790\u6811\u4e86\u3002\u5728\u6bcf\u6b21\u89e3\u6790\u5230\u5bf9\u5e94\u8282\u70b9\u6216\u8fdb\u884cReduction\u65f6\uff0c\u6211\u4eec\u5728\u8bed\u6cd5\u6587\u4ef6\u7684Action\u90e8\u5206\u5c31\u53ef\u4ee5\u8c03\u7528\u4e00\u4e2a<code>build_node<\/code>\u51fd\u6570\u6765\u6784\u5efa\u5bf9\u5e94\u7684\u8282\u70b9\u3002\u6211\u4eec\u53ef\u4ee5\u770b\u770b\u5982\u4e0b\u7684\u7a0b\u5e8f\u7684\u89e3\u6790\u6811\u7ed3\u6784\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">i = 1 ;\na = 0 ;\nwhile ( a &lt; 100 ) {\n    a = a + i;\n    i = i + 1;\n}\nprint i ;<\/code><\/pre>\n\n\n\n<p>\u8fd9\u4e2a\u7a0b\u5e8f\uff0c\u53ef\u4ee5\u627e\u5230\uff0c\u5728\u81ea\u7136\u6570\u7ea7\u6570\u4e2d\uff0c\u5230\u7b2c\u51e0\u9879\u7684\u65f6\u5019\uff0c\u5176\u548c\u5c31\u8d85\u8fc7\u4e86100\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\u5b8c\u6574\u7684\u4ee3\u7801<\/h4>\n\n\n\n<p>\u6700\u540e\u662f\u7a0b\u5e8f\u5b9e\u73b0\u7684\u90e8\u5206\uff0c\u5305\u62ec<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>build_node<\/li>\n\n\n\n<li>execute_node<\/li>\n\n\n\n<li>free_node<\/li>\n\n\n\n<li>get_node_ret<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h5 class=\"wp-block-heading\">cal.l lex\u6587\u4ef6<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">cat cal.l\n\n%{\n    #include \"cal.tab.h\"\n%}\n%option noyywrap\n%%\n[[:digit:]]+ {\n    yylval.a = atoi(yytext);\n    return INTEGER;\n}\n\n[a-z] {\n    yylval.c = yytext[0];\n    return VAR_NAME;\n}\n\n\"+\" { return O_ADD;};\n\"-\" { return O_MINUS;};\n\"*\" { return O_MULTIPLY;};\n\n\"while\"  {return WHILE;}\n\"if\"  {return IF;}\n\"print\"  {return PRINT;}\n\n\"&gt;\" {return GT;}\n\"&lt;\" {return LT;}\n\n[();={}]  {return yylval.c = *yytext;}\n\n%%<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">cal.header.h \u5934\u6587\u4ef6\/\u6570\u636e\u7ed3\u6784\u5b9a\u4e49<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">cat cal.header.h\n\nenum NODETYPE{\n    NT_STATEMENT,\n    NT_IF,\n    NT_WHILE,\n    NT_PROGRAM,\n    NT_STATEMENT_BLOCK,\n    NT_O_ADD,\n    NT_O_MINUS,\n    NT_O_MULTIPLY,\n    NT_INTEGER,\n    NT_VAR_NAME,\n    NT_BOOL_EXPR_GT,\n    NT_BOOL_EXPR_LT,\n    NT_PRINT,\n    NT_ASSIGNMENT\n};\n\ntypedef struct t_node{\n    enum NODETYPE nt;\n    struct t_node* left;\n    struct t_node* right;\n    struct t_node* rrnode;\n    int i;  \/\/ for NT_INTEGER NT_VAR_NAME node\n}t_node;<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">cal.y \u8bed\u8a00\u8bed\u6cd5\u6587\u4ef6<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">cat cal.y\n%{\n\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include \"cal.tab.h\"\n#include \"cal.header.h\"\n\n\/\/ #define cal_DEBUG 1\n\nvoid debug_print(const char *fname, int lineno, const char *fxname, const char *debug_info){\n    #ifdef cal_DEBUG\n    printf(\"\\n debug: enter at line %d in %s,function: %s info: %s\\n\",\n        lineno,\n        fname,\n        fxname,\n\t\tdebug_info\n        );\n\t#endif\n}\n\n\nt_node* build_node(enum NODETYPE nt,t_node* left,t_node* right, t_node* r_right , int i){\n    debug_print(__FILE__,__LINE__,__func__,\"\");\n    t_node *t_n;\n    t_n = NULL;\n    t_n = (t_node *)malloc(sizeof(t_node));\n    if (t_n == NULL){\n        printf(\"Out of Memory\\n\");\n        exit(1);\n    }\n\tt_n-&gt;nt = nt;\n\tt_n-&gt;left = left;\n\tt_n-&gt;right = right;\n\tt_n-&gt;rrnode = r_right;\n\tt_n-&gt;i = i;\n    return t_n;\n}\n\n\nint var[26];\n\nint main (){\n    int yydebug=1;\n    yyparse();\n    return 0;\n}\n\nvoid\nyyerror (char const *s)\n{\n  fprintf (stderr, \"something error: %s\\n over\", s);\n}\n\n\nint exec_node(t_node *n){\n    if( n == NULL ) return 0;\n    debug_print(__FILE__,__LINE__,__func__,\"enter exec_node\");\n\n    switch(n-&gt;nt){\n        case NT_INTEGER:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_INTEGER node\");\n\t\t\tbreak;\n        case NT_VAR_NAME:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_VAR_NAME node\");\n\t\t\tbreak;\n        case NT_O_ADD:\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) + get_node_ret(n-&gt;right);\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_O_ADD node\");\n\t\t\tbreak;\n        case NT_O_MINUS:\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) - get_node_ret(n-&gt;right);\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_O_MINUS node\");\n            break;\n        case NT_O_MULTIPLY:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_O_MULTIPLY node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            n-&gt;i = get_node_ret(n-&gt;left) * get_node_ret(n-&gt;right);\n            break;\n        case NT_BOOL_EXPR_GT:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_BOOL_EXPR_GT node\");\n            n-&gt;i = 0;\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            if (get_node_ret(n-&gt;left) &gt; get_node_ret(n-&gt;right) )\n            { n-&gt;i = 1 ; }\n            break;\n        case NT_BOOL_EXPR_LT:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_BOOL_EXPR_LT node\");\n            n-&gt;i = 0;\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            if (get_node_ret(n-&gt;left) &lt; get_node_ret(n-&gt;right) )\n            { n-&gt;i = 1 ; }\n            break;\n        case NT_IF:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_IF node\");\n            exec_node(n-&gt;left);\n            if (get_node_ret(n-&gt;left)){\n                exec_node(n-&gt;right);\n            }\n            break;\n        case NT_WHILE:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_WHILE node\");\n            exec_node(n-&gt;left);\n            while( get_node_ret(n-&gt;left)  ){\n                exec_node(n-&gt;right);\n                exec_node(n-&gt;left);\n            }\n            break;\n        case NT_PRINT:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_PRINT node\");\n            exec_node(n-&gt;left);\n            printf(\"print '%d'\",get_node_ret(n-&gt;left));\n            break;\n        case NT_ASSIGNMENT:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_ASSIGNMENT node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            var[n-&gt;left-&gt;i - 'a'] = get_node_ret(n-&gt;right);\n            break;\n        case NT_STATEMENT_BLOCK:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_STATEMENT_BLOCK node\");\n            exec_node(n-&gt;left);\n            exec_node(n-&gt;right);\n            break;\n        case NT_PROGRAM:\n    \t\tdebug_print(__FILE__,__LINE__,__func__,\"NT_PROGRAM node\");\n            break;\n    }\n\n    return 0;\n}\n\nint get_node_ret(t_node *n){\n    int r = n-&gt;i;\n    switch(n-&gt;nt){\n        case NT_VAR_NAME:\n            r = var[n-&gt;i - 'a'];\n            break;\n    }\n    return r;\n}\n\nint free_node(t_node *n){\n    if(n != NULL){\n        \/\/ printf(\"\\n try to free memory of node %d \\n\",n-&gt;nt);\n    }\n    return 0;\n}\n\n\n%}\n\n%union {\n    int a;  \/\/ for integer\n    char c; \/\/ for var_name\n    int int_bool; \/\/ for bool_expr\n    struct t_node* t_n;\n}\n\n\n%type &lt;t_n&gt; expression bool_expr print_func assignment\n%type &lt;t_n&gt; while_block statement statement_block if_block\n\n%token &lt;c&gt; VAR_NAME\n%token &lt;a&gt; INTEGER\n\n%token O_ADD O_MINUS O_MULTIPLY\n\n%token GT LT\n\n%token WHILE IF\n%token PRINT\n\n%left O_ADD O_MINUS\n%left O_MULTIPLY\n\n%%\nprogram:  statement_block\n            {\n                exec_node($1);\n                free_node($1);\n                printf(\"\\n job done! \\n\");\n            }\n;\n\nstatement_block: %empty\n            {\n                $$ = build_node(\n                        NT_STATEMENT_BLOCK,\n                        NULL,\n                        NULL,\n                        NULL,\n                        0\n                        );\n                debug_print(__FILE__,__LINE__,__func__,\"\");\n            }\n\n        | statement_block statement\n            { $$ = build_node(\n                    NT_STATEMENT_BLOCK,\n                    $1,\n                    $2,\n                    NULL,\n                    0\n                    );\n\n                debug_print(__FILE__,__LINE__,__func__,\"\");\n            }\n;\n\nstatement: assignment { $$ = $1; }\n        | print_func  { $$ = $1; }\n        | if_block    { $$ = $1; }\n        | while_block { $$ = $1; }\n;\n\nif_block: IF '(' bool_expr ')' '{' statement_block '}'\n            {\n                $$ = build_node(\n                        NT_IF,\n                        $3,\n                        $6,\n                        NULL,\n                        0\n                        );\n            }\n\nwhile_block: WHILE '('  bool_expr ')' '{' statement_block '}'\n            {\n                $$ = build_node(\n                        NT_WHILE,\n                        $3,\n                        $6,\n                        NULL,\n                        0\n                        );\n            }\n\nassignment: VAR_NAME '=' expression ';' { $$ = build_node(\n                                                    NT_ASSIGNMENT,\n                                                    build_node(NT_VAR_NAME,NULL,NULL,NULL,(int)$1),\n                                                    $3,\n                                                    NULL,\n                                                    0);\n                                        }\n\nprint_func : PRINT expression ';'   {  $$ = build_node(NT_PRINT,$2,NULL,NULL,0); }\n\nbool_expr: expression GT expression {  $$ = build_node(NT_BOOL_EXPR_GT,$1,$3,NULL,0);}\n        |  expression LT expression {  $$ = build_node(NT_BOOL_EXPR_LT,$1,$3,NULL,0);}\n\nexpression: INTEGER { $$ = build_node(NT_INTEGER,NULL,NULL,NULL,$1); }\n        | VAR_NAME  { $$ = build_node(NT_VAR_NAME,NULL,NULL,NULL,(int)$1); }\n        | expression O_ADD expression {  $$ = build_node(NT_O_ADD,$1,$3,NULL,0);}\n        | expression O_MINUS expression  {  $$ = build_node(NT_O_MINUS,$1,$3,NULL,0);}\n        | expression O_MULTIPLY expression {  $$ = build_node(NT_O_MULTIPLY,$1,$3,NULL,0);}\n\n\n%%<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\u7f16\u8bd1\u4e0e\u6267\u884c<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">lex cal.l &amp;&amp; \\\nbison -d cal.y &amp;&amp; \\\ngcc cal.tab.c lex.yy.c -o a.out &amp;&amp; \\\n.\/a.out &lt; p.f.txt<\/code><\/pre>\n\n\n\n<p>\u6700\u540e\uff0c\u9700\u8981\u6ce8\u610f\uff0c\u8be5\u7a0b\u5e8f\u66f4\u6ce8\u91cd\u7684\u662f\u6d4b\u8bd5\u4e0e\u5b9e\u73b0\uff0c\u6240\u4ee5\u5728\u201c\u5185\u5b58\u91ca\u653e\u201d\u53ef\u80fd\u4f1a\u5b58\u5728\u4e00\u4e9b\u6cc4\u9732\u7684\u95ee\u9898\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8fd9\u662f\u4e00\u4e2a\u7cfb\u5217\u6587\u7ae0\uff0c\u65e8\u5728\u4e86\u89e3\u5982\u4f55\u4f7f\u7528Flex\/Lex\u548cYacc\/Bison\u8fdb\u884c\u8bcd\u6cd5\u548c\u8bed\u6cd5\u89e3\u6790\u3002\u5728\u524d\u9762\uff0c\u5df2\u7ecf\u5b8c\u6210\u4e86\u4f7f\u7528Lex\/flex\u505a\u57fa\u7840\u7684\u8bcd\u6cd5\u89e3\u6790\u3001\u5b9e\u73b0\u4e00\u4e2a\u7b80\u5355\u7684\u8ba1\u7b97\u5668\u3001flex\/bison\u7cfb\u52173\uff1a\u66f4\u590d\u6742\u7684\u4e00\u4e2a\u7f16\u8bd1\u7a0b\u5e8f\u5b9e\u73b0\uff08\u4e0a\uff09\u3002\u5728\u4e0a\u7bc7\u4e2d\uff0c\u5df2\u7ecf\u5b8c\u6210\u8bed\u6cd5\u89c4\u5219\u3001\u4e3b\u8981\u7684\u6570\u636e\u7ed3\u6784\u8bbe\u8ba1\u3002\u8fd9\u91cc\u5c31\u7ee7\u7eed\u5b8c\u6210\u7a0b\u5e8f\uff0c\u6700\u540e\u7f16\u8bd1\u6d4b\u8bd5\u3002 \u56de\u987e \u8fd9\u4e2a\u7cfb\u5217\u6211\u4eec\u9700\u8981\u901a\u8fc7flex\/bison\u5b9e\u73b0\u4e00\u4e2a\u7f16\u8bd1\u7a0b\u5e8f\uff0c\u80fd\u591f\u5b9e\u73b0\u4e00\u79cd\u7b80\u5355\u7684\u7a0b\u5e8f\u8bed\u8a00\uff0c\u8fd9\u4e2a\u7a0b\u5e8f\u8bed\u8a00\u5305\u542b\u4e86\uff1a\u57fa\u7840\u8fd0\u7b97\u3001\u53d8\u91cf\u4e0e\u8d4b\u503c\u3001\u8868\u8fbe\u5f0f\u8ba1\u7b97\u3001if\u8bed\u53e5\u3001while\u8bed\u53e5\u3001print\u8bed\u53e5\u7b49\u3002\u4f8b\u5982\uff0c\u4f7f\u7528\u8be5\u7a0b\u5e8f\u8bed\u8a00\uff0c\u6211\u4eec\u53ef\u4ee5\u5b9e\u73b0\u5982\u4e0b\u7a0b\u5e8f\uff1a \u8be5\u7a0b\u5e8f\u89e3\u51b3\u7684\u95ee\u9898\u662f\uff1a\u5728\u81ea\u7136\u6570\u5e8f\u5217\uff081\u30012\u30014\u2026\uff09\u4e2d\uff0c\u524d\u9762\u591a\u5c11\u4e2a\u81ea\u7136\u6570\u7684\u548c\u9996\u6b21\u5927\u4e8e100\u3002\u4f60\u53ef\u4ee5\u4f7f\u7528\u4e0a\u9762\u5b9a\u4e49\u7684\u8bed\u8a00\uff0c\u7f16\u5199\u81ea\u5df1\u7684\u7a0b\u5e8f\u3002 \u597d\u4e86\uff0c\u63a5\u7740\u524d\u9762\u4e09\u7bc7\u7684\u5185\u5bb9\uff0c\u6211\u4eec\u7ee7\u7eed\u5b8c\u6210\u8be5\u8bed\u8a00\u7684\u7f16\u8bd1\u7a0b\u5e8f\u3002 \u4e3b\u8981\u7684\u51fd\u6570\u5b9e\u73b0 build_node\u51fd\u6570 exec_node\u51fd\u6570 \u5185\u5b58\u91ca\u653e \u5de5\u5177\u51fd\u6570debug_print \u8865\u5145\u8bed\u6cd5\u6587\u4ef6\u7684Action\u90e8\u5206 cal.header.h \u6709\u4e86\u8fd9\u4e9b\u4fe1\u606f\uff0c\u5c31\u53ef\u4ee5\u4f7f\u7528NODETYPE\u6765\u6784\u5efa\uff0c\u89e3\u6790\u6811\u4e86\u3002\u5728\u6bcf\u6b21\u89e3\u6790\u5230\u5bf9\u5e94\u8282\u70b9\u6216\u8fdb\u884cReduction\u65f6\uff0c\u6211\u4eec\u5728\u8bed\u6cd5\u6587\u4ef6\u7684Action\u90e8\u5206\u5c31\u53ef\u4ee5\u8c03\u7528\u4e00\u4e2abuild_node\u51fd\u6570\u6765\u6784\u5efa\u5bf9\u5e94\u7684\u8282\u70b9\u3002\u6211\u4eec\u53ef\u4ee5\u770b\u770b\u5982\u4e0b\u7684\u7a0b\u5e8f\u7684\u89e3\u6790\u6811\u7ed3\u6784\uff1a \u8fd9\u4e2a\u7a0b\u5e8f\uff0c\u53ef\u4ee5\u627e\u5230\uff0c\u5728\u81ea\u7136\u6570\u7ea7\u6570\u4e2d\uff0c\u5230\u7b2c\u51e0\u9879\u7684\u65f6\u5019\uff0c\u5176\u548c\u5c31\u8d85\u8fc7\u4e86100\u3002 \u5b8c\u6574\u7684\u4ee3\u7801 \u6700\u540e\u662f\u7a0b\u5e8f\u5b9e\u73b0\u7684\u90e8\u5206\uff0c\u5305\u62ec cal.l lex\u6587\u4ef6 cal.header.h \u5934\u6587\u4ef6\/\u6570\u636e\u7ed3\u6784\u5b9a\u4e49 cal.y \u8bed\u8a00\u8bed\u6cd5\u6587\u4ef6 \u7f16\u8bd1\u4e0e\u6267\u884c \u6700\u540e\uff0c\u9700\u8981\u6ce8\u610f\uff0c\u8be5\u7a0b\u5e8f\u66f4\u6ce8\u91cd\u7684\u662f\u6d4b\u8bd5\u4e0e\u5b9e\u73b0\uff0c\u6240\u4ee5\u5728\u201c\u5185\u5b58\u91ca\u653e\u201d\u53ef\u80fd\u4f1a\u5b58\u5728\u4e00\u4e9b\u6cc4\u9732\u7684\u95ee\u9898\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_eb_attr":"","inline_featured_image":false,"_tocer_settings":[],"footnotes":""},"categories":[137],"tags":[],"class_list":["post-9635","post","type-post","status-publish","format-standard","hentry","category-learning-more"],"_links":{"self":[{"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/posts\/9635","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/comments?post=9635"}],"version-history":[{"count":25,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/posts\/9635\/revisions"}],"predecessor-version":[{"id":21968,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/posts\/9635\/revisions\/21968"}],"wp:attachment":[{"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/media?parent=9635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/categories?post=9635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.orczhou.com\/index.php\/wp-json\/wp\/v2\/tags?post=9635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}