definitions %% rules %% user code
These expressions all designate a set of characters equivalent to the corresponding standard C isXXX function.
If the start condition is inclusive, then rules with no start conditions at all will also be active.
If it is exclusive, then only rules qualified with the start condition will be active.
%s example ; example 是 inclusive start condition。 %% ; 當切換到 example start condition 時,foo 和 bar 都會被激活。 <example>foo do_something(); bar something_else();
/* left recursion */ expseq1: exp | expseq1 ',' exp ; /* right recursion */ expseq1: exp | exp ',' expseq1 ;
%token <TYPE> TOKEN
Each call to yylex() returns an integer value which represents a token type. This tells YACC what kind of token it has read. The token may optionally have a value, which should be placed in the variable yylval.
By default yylval is of type int, but you can override that from the YACC file by re#defining YYSTYPE.
使用 %union 讓 yylval 可以有多種型別。
%union { int number; char *string; } %token <number> STATE %token <number> NUMBER %token <string> WORD [0-9]+ yylval.number=atoi(yytext); return NUMBER; [a-z0-9]+ yylval.string=strdup(yytext);return WORD;
The relative precedence of different operators is controlled by the order in which they are declared. The first precedence/associativity declaration in the file declares the operators whose precedence is lowest, the next such declaration declares the operators whose precedence is a little higher, and so on.
Bison 中所寫的語法規則,有些僅是用來處理運算子優先順序,和程式無關。抽象語法樹即是將前述語法規則剔除。
A mid-rule action may refer to the components preceding it using $n, but it may not refer to subsequent components because it is run before they are parsed.
The mid-rule action itself counts as one of the components of the rule. This makes a difference when there is another action later in the same rule (and usually there is another at the end): you have to count the actions along with the symbols when working out which number n to use in $n.
The mid-rule action can also have a semantic value. The action can set its value with an assignment to $$, and actions later in the rule can refer to the value using $n. Since there is no symbol to name the action, there is no way to declare a data type for the value in advance, so you must use the ‘$<…>n’ construct to specify a data type each time you refer to this value.
There is no way to set the value of the entire rule with a mid-rule action, because assignments to $$ do not have that effect. The only way to set the value for the entire rule is with an ordinary action at the end of the rule.
If you invoke ‘%define parse.error verbose’ in the Bison declarations section (see The Bison Declarations Section), then Bison provides a more verbose and specific error message string instead of just plain "syntax error". However, that message sometimes contains incorrect information if LAC is not enabled (see LAC).
%option bison-locations
(%option bison-bridge
可移除)。/* handle locations */ //static int yycloumn = 1; // yycloumn 自動產生 #define YY_USER_ACTION yylloc->first_line = yylloc->last_line = yylineno; \ yylloc->first_column = yycloumn; yylloc->last_column = yycloumn+yyleng-1; \ yycolumn += yyleng;
%locations
。函式 yyerror 第一個參數為 YYLTYPE*。stmt : whileStmt | ifStmt | ... | error NEWLINE /* 此處選擇斷行符做為同步點。*/ ;
根本原因: 當 Bison 試圖 reduce 時,有其它 shift 或是 reduce 的可能,即為 shift/reduce 或是 reduce/reduce conflict。以下圖來看,"." 出現在規則結尾處時,代表有 reduce 發生。此時,如果有其它 "." 出現,代表衝突發生。
State 14 conflicts: 1 shift/reduce ... State 14 12 input_state_path: T_INPUT_STATE_NO_PATH . T_DIVIDE identifier 13 | T_INPUT_STATE_NO_PATH . T_DIVIDE shift, and go to state 19 T_DIVIDE [reduce using rule 13 (input_state_path)] $default reduce using rule 13 (input_state_path)
$ grep "State 14" -n Syntax_InputState.output $ sed -n '211,222p' Syntax_InputState.output > Syntax_InputState.output.new
對於原本文法存在的 shift/reduce 或是 reduce/reduce conflict,GLR parser 於衝突處分成多個 parser 同時並行處理。注意! GLR parser 處理時間隨 conflict 個數增加。
%glr-parser %expect 2 %expect-rr
Additional syntax error message on GLR parser when syntax is ambiguous
# 先關閉 waring,再開啟 conflicts-sr % bison -Wnone,conflicts-sr
YY_BUFFER_STATE 是 lex 對特定輸入流所產生的句柄。其中包含輸入流的緩衝區,和其它相關變數。
#define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; ... }
yy_switch_to_buffer (yy_scan_buffer (char *base, yy_size_t size) );
token 由兩部分組成: token 和 token value。
%{ // declaration and option setting #include <stdio.h> #include <y.tab.h> // yacc 根據 *.y 產生的 *.h,定義 token (number) %} %% // pattern and action REGEXP1 ACTION REGEXP2 {ACTIONS} %% // helper function
%{ // include C header files %} // 定義 token。parser 據此判斷該符號是 token。 // 其餘非 token 的符號必須出現在 rule 左邊至少一次。 %% // rule (grammer) // EXPS ($$) // EXP ($1) // FACTORS ($2) // TOKEN ($3) EXPS: /* empty, match the beginning of the input */ | EXP FACTORS TOKEN { ACTIONS } ; /* end of rule */ %% // helper function
<START COND>REGEXP ACTION
%x SN_CONDITION_MACRO_DEFINITION SN_CONDITION_MACRO_CALL SN_CONDITION_MACRO_CALL_DELIM %x SN_CONDITION_MACRO_EXPANSION SN_CONDITION_MACRO_DECL SN_CONDITION_INCLUDE %x SN_CONDITION_FALSE %x SN_CONDITION_COPY SN_CONDITION_MESSAGE %x SN_NO_BOUNDARY_TWO_STRING SN_NO_BOUNDARY_ONE_STRING %x SN_COMMENT_CONDITION SN_COMMENT_CONDITION2 %x SN_NO_BOUNDARY_THREE_TOKEN
// 透過 yyscan_t 傳遞 scanner 狀態 // struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; typedef void* yyscan_t; /* For convenience, these vars (plus the bison vars far below) are macros in the reentrant scanner. */ #define yyin yyg->yyin_r #define yyout yyg->yyout_r #define yyextra yyg->yyextra_r #define yyleng yyg->yyleng_r #define yytext yyg->yytext_r #define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) #define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) #define yy_flex_debug yyg->yy_flex_debug_r /* Holds the entire state of the reentrant scanner. */ struct yyguts_t { /* User-defined. Not touched by flex. */ YY_EXTRA_TYPE yyextra_r; /* The rest are the same as the globals declared in the non-reentrant scanner. */ FILE *yyin_r, *yyout_r; size_t yy_buffer_stack_top; /**< index of top of stack. */ size_t yy_buffer_stack_max; /**< capacity of stack. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ char yy_hold_char; int yy_n_chars; int yyleng_r; char *yy_c_buf_p; int yy_init; int yy_start; int yy_did_buffer_switch_on_eof; int yy_start_stack_ptr; int yy_start_stack_depth; int *yy_start_stack; yy_state_type yy_last_accepting_state; char* yy_last_accepting_cpos; int yylineno_r; int yy_flex_debug_r; char *yytext_r; int yy_more_flag; int yy_more_len; YYSTYPE * yylval_r; }; /* end struct yyguts_t */
yyscanner is available to all your actions. In addition, yylex has a local variable called yyg that holds the entire state, and most macros conveniently refer to yyg.