/* vi:set ts=8: */ #define A 258 #define B 259 #ifndef YYSTYPE #define YYSTYPE int #endif #include #define YYFINAL 5 #define YYFLAG -32768 #define YYNTBASE 5 #define YYTRANSLATE(x) ((unsigned)(x) <= 259 ? yytranslate[x] : 6) yylex の値からトークンシンボルへの変換表 static const char yytranslate[] = {0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4 }; 還元先のシンボル static const short yyr1[] = {0, 5 }; 還元の長さ static const short yyr2[] = {0, 2 }; デフォルトのアクション static const short yydefact[] = {0, 0, 1, 0, 0, 0 }; デフォルトのgoto static const short yydefgoto[] = {3 }; actionテーブルのポインタ static const short yypact[] = {-3, -2, -32768, 1, 3, -32768 }; gotoテーブルのポインタ static const short yypgoto[] = {-32768 }; 還元の数 + 1 (受理) #define YYLAST 3 メインテーブル static const short yytable[] = {1, 4, 2, 5 }; チェック表 static const short yycheck[] = {3, 0, 4, 0 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY -2 #define YYEOF 0 #define YYACCEPT return(0) #define YYABORT return(1) #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { yychar = (token), yylval = (value); \ yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* If nonreentrant, generate the variables here */ int yychar; /* the lookahead symbol */ YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ int yynerrs; /* number of parse errors so far */ /* YYINITDEPTH indicates the initial size of the parser's stacks */ #ifndef YYINITDEPTH #define YYINITDEPTH 200 #endif /* YYMAXDEPTH is the maximum size the stacks can grow to (effective only if the built-in stack extension method is used). */ #define YYMAXDEPTH 10000 int yyparse() { register int yystate; 現在の状態 register int yyn; register short *yyssp; 状態スタックの先頭 register YYSTYPE *yyvsp; 値スタックの先頭 int yyerrstatus; エラーから回復するためにシフトしなければいけない残数 int yychar1 = 0; 内部トークン表現 short yyssa[YYINITDEPTH]; 状態スタック YYSTYPE yyvsa[YYINITDEPTH]; 値スタック short *yyss = yyssa; 状態スタックの先頭(成長するバージョン) YYSTYPE *yyvs = yyvsa; 値スタックの先頭 #define YYPOPSTACK (yyvsp--, yyssp--) int yystacksize = YYINITDEPTH; YYSTYPE yyval; /* the variable used to return */ /* semantic values from the action */ /* routines */ int yylen; /* ------------------------------------------------------------------------ */ 変数の初期化 if (yydebug) fprintf(stderr, "Starting parse\n"); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; yychar が YYEMPTY だと読みこむ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss - 1; yyvsp = yyvs; /* -------------------------------------------------------------- */ yynewstate: 状態をプッシュ なにをするか決める アクションの探索(1) ポインタを得る yyn = yypact[yystate]; if (yyn == YYFLAG) goto yydefault; トークン読みこみ if (yychar == YYEMPTY) { if (yydebug) fprintf(stderr, "Reading a token: "); yychar = yylex(); } トークンを内部形式に変換 if (yychar <= 0) { /* This means end of input. */ yychar1 = 0; yychar = YYEOF; /* Don't call yylex() any more */ if (yydebug) fprintf(stderr, "Now at end of input.\n"); } else { yychar1 = YYTRANSLATE(yychar); if (yydebug) { fprintf(stderr, "Next token is %d (%s", yychar, yytname[yychar1]); /* Give the individual parser a way to print the precise meaning of a token, for further debugging info. */ fprintf(stderr, ")\n"); } } アクションの探索(2) トークン値とあわせて実際のアクションを得る yyn += yychar1; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; 得られた yyn = yytable[yyn]; マイナスは還元、ただしYYFLAG(=すごく小さい値)と 0 はエラー 正はシフト 最大値のシフトは受理 if (yyn < 0) { if (yyn == YYFLAG) goto yyerrlab; エラー yyn = -yyn; goto yyreduce; 還元 } else if (yyn == 0) goto yyerrlab; エラー if (yyn == YYFINAL) YYACCEPT; 受理 残りはシフト 変換前のトークンを捨てる if (yychar != YYEOF) yychar = YYEMPTY; スタックにプッシュ *++yyvsp = yylval; エラー状態なら正常に近づく if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /* -------------------------------------------------------------- */ yydefault: /* Do the default action for the current state. */ デフォルトのアクションを探す yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; デフォルトがシフトということはない /* -------------------------------------------------------------- */ yyreduce: /* Do a reduction. yyn is the number of a rule to reduce with */ 還元する 前準備 yylen = yyr2[yyn]; if (yylen > 0) yyval = yyvsp[1 - yylen]; /* implement default value of the action */ (アクションをコール) スタックを減らす yyvsp -= yylen; yyssp -= yylen; アクションの値をプッシュ *++yyvsp = yyval; 次の状態を探索 エラーはない (還元先トークンをシフトする必要はない) yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTBASE] + *yyssp; if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; /* -------------------------------------------------------------- */ yyerrlab: /* here on detecting error */ エラーが検出された すでにエラー回復中でなければ報告 if (!yyerrstatus) { ++yynerrs; yyerror("parse error"); } /* -------------------------------------------------------------- */ yyerrlab1: /* here on error raised explicitly by an action */ エラーの続き エラー回復中にすぐ失敗したら (yyerrstatus == 3) トークンをすてる (そうしないと、無限ループになる!) if (yyerrstatus == 3) { if (yychar == YYEOF) YYABORT; yychar = YYEMPTY; } 最初からやりなおし… yyerrstatus = 3; /* Each real token shifted decrements this */ goto yyerrhandle; /* -------------------------------------------------------------- */ yyerrdefault: とくになにもしない /* -------------------------------------------------------------- */ yyerrpop: /* pop the current state because it can't handle the error token */ 値スタック、状態スタックを一回ずつ pop スタックが空だったら死に if (yyssp == yyss) YYABORT; yyvsp--; yystate = *--yyssp; /* -------------------------------------------------------------- */ yyerrhandle: error トークンがシフトできるかどうか試す yyn = yypact[yystate]; if (yyn == YYFLAG) goto yyerrdefault; yyn += YYTERROR; if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) goto yyerrdefault; みつかった(ただしシフトかどうかはわからない) yyn = yytable[yyn]; if (yyn < 0) { if (yyn == YYFLAG) goto yyerrpop; やっぱりエラー yyn = -yyn; goto yyreduce; 還元できそう } else if (yyn == 0) goto yyerrpop; 受理 if (yyn == YYFINAL) YYACCEPT; エラートークンをシフトできる *++yyvsp = yylval; yystate = yyn; goto yynewstate; }