在PHP的實現過程中,包括PHP語言本身的詞法分析,一共有多達8處的地方使用了re2c,如我們常用的時間函數、pdo擴展等。對re2c的了解更能促進我們進PHP內核實現的認知。
本手冊是re2c官網的manual.html文件翻譯稿,僅適用于對re2c的初步了解,更多的資料見[re2c項目](http://sourceforge.net/projects/re2c/)中lessons目錄和doc目錄。
## Name[]()
re2c - 將正則表達式轉化成C/C++代碼
Synopsisre2c [-bdDefFghisuvVw1] [-o output] [-c [-t header]] file
## Description[]()
re2c是一個將正則表達式轉化成基于C語言標識的預處理器。
re2c的輸入包含C/C++代碼,并且以/*!re2c... */注釋的格式將掃描標識交錯嵌入到這些代碼中。在它的輸出中,這些注釋將會被生成的代碼替換掉,當執行時,它將會查找到下一個token,并且執行用戶提供的針對該token的特定代碼。如下示例:
char *scan(char *p)
{
/*!re2c re2c:define:YYCTYPE = "unsigned char"; re2c:define:YYCURSOR = p; re2c:yyfill:enable = 0; re2c:yych:conversion = 1; re2c:indent:top = 1; [0-9]+ {return p;} [^] {return (char*)0;} */
}
re2c將生成如下代碼:
/* Generated by re2c on Sat Apr 16 11:40:58 1994 */
char *scan(char *p)
{
{
unsigned char yych;
?
yych = (unsigned char)*p;
if(yych <= '/') goto yy4;
if(yych >= ':') goto yy4;
++p;
yych = (unsigned char)*p;
goto yy7;
yy3:
{return p;}
yy4:
++p;
yych = (unsigned char)*p;
{return char*)0;}
yy6:
++p;
yych = (unsigned char)*p;
yy7:
if(yych <= '/') goto yy3;
if(yych <= '9') goto yy6;
goto yy3;
}
?
}
你可以通過添加注釋:/*!max:re2c_/ 來輸出一個宏定義 YYMAXFILL 來保存輸入解析時字符的最大個數。如果使用了-1, YYMAXFILL 只能在最后的 /*!re2c_/ 后觸發一次。同時,你也可以使用 /*!ignore:re2c */ 來為掃描代碼添加注釋文檔,它們被輸出。
## Options[]()
re2c提供如下的選項:
- -?
- -h 幫助
- -b 當指定-b參數時,-s參數也會被默認同時指定。 使用位向量嘗試著從編譯器搗鼓出更好的代碼。它對于關鍵字比較多的規則很有用,比如大部分的編程語言。
re2c的實現是通過生成256個ascii字符的映射表,直接判斷對應的字符串是否應該跳轉到下一個字符,從而實現優化。
- -c 支持類lex或flex的表達式
- -d 創建一個解析器用來打印當前位置的信息,這對于調試非常有用。如果你要使用它,你需要定義一個供解析器調用的YYDEBUG宏,它像一個函數一樣,接受兩個參數:void YYDEBUG(int state,char current)。第一個參數是state或者-1,第二個參數是當前所解析的代碼位置。
在每個++YYCURSOR、不同的goto跳轉變化處,re2c自動添加YYDEBUG宏調用。如果在規則文件中沒定義YYDEUBG宏,在編譯C文件時會出錯。
- -D 輸出Graphviz dot 格式的數據,比如可以使用" dot -Tpng input.dot > output.png"來處理生成圖片。注意掃描器中如果包含太多的狀態可能會讓dot程序崩潰
- -e 從ASCII平臺交叉編譯EBCDIC
- -f 生成帶可存儲狀態的掃描器。更多詳情見下面的可存儲的掃描器小節。
- -F 部分支持flex語法。當-F標記有效時,flex的變量用大括號括起來,并且在定義時不需要等號,在結束時不需要用分號。否則,名字被認為是直接被引號的字符串。
- -g 使用GCC的goto特性生成掃描器。當決策復雜時re2c會生成決策跳轉表,使用goto針對不同的情況做不同的跳轉。僅適用于GCC編譯器。注意,這里默認指定了-b參數。re2c的實現中,-g參數會生成yytarget決策跳轉表,其實就是一個256個元素的一維數據,針對不同的字符,直接跳轉,以優化掃描器。
-
-i 不輸出行信息,當你的用戶從你的代碼編譯,而你又不要求他們擁有re2c環境,此時你可以使用CMS工具管理re2c的輸出文件時,此參數就有用武之地了。-o參數指定輸出文件。指在生成的.c文件中不使用#line宏。
-
-r 允許掃描器在每個 '/_!use:re2c'塊后面重用定義的 '/_!use:re2c' 塊。這些塊可以包含適當的配置,特別是 're2c:flags:w'和re2c:flags:u'。這種方法可能會為不同的字符類型,不同的輸入機制或不同的輸出機制多次創建相同的掃描器。'/_!use:re2c' 塊也可以在 '/_!rules:re2c'中的規則集中包含額外的規則。
-
-s 為一些switch語句生成嵌套的if語句。許多編譯器需要這個參數的輔助以便生成更好的代碼。
-
-t 生成一個類型定義的頭文件,以支持類(f)lex條件,當需要使用-t參數時,需同時指定-c參數,-t參數后面接生成的頭文件名稱。如果只指定re2c會報錯:re2c: error: Can only output a header file when using -c switch
-
-u 生成一個支持Unicode編碼的解析器。這意味著生成的代碼能處理任何有效的Unicode字符,直到x10FFFF。當需要支持UTF-8或UTF-16時,你需要自己將輸入的數據轉化成UTF-32編碼。
-
-v 查看版本信息。如:re2c 0.13.6
-
-V 以數字格式查看版本信息。如:001306
-
-w 創建支持寬字符格式的解析器,默認指定-s參數,不能和-e參數共存。
-
-1 強制一次生成,它不能和-f組合在一起使用,并且在re2c塊結束之前不能禁用YYMAXFILL。
-
--no-generation-date 禁止輸出生成日志,所以只會輸出re2c的版本信息。
- --case-insensitive 所有字符串不區分大小寫,所以,雙引號中的字符和單引號的意義一樣。
- --case-inverted 顛倒單引號和雙引號包含的字符中的意思,比如,有了這個開關,單引號內的字符串區分大小寫,雙引號內的字符串不區分大小寫。
-
## Interface Code(接口代碼)[]()
不像其他的掃描器程序,re2c 不會生成完整的掃描器:用戶必須提供一些接口代碼。用戶必須定義下面的宏或者是其他相應的配置。
-
YYCONDTYPE 用-c 模式你可以使用-t參數來生成一個包含了會被作為條件使用的枚舉類型的文件。枚舉類型中的每個值都會在規則集合里面作為條件來使用。
-
YYCTYPE 用來維持一個輸入符號。通常是 char 或者unsigned char。
-
YYCTXMARKER *YYCTYPE類型的表達式,生成的代碼回溯信息的上下文會保存在
-
YYCTXMARKER。如果掃描器規則需要使用上下文中的一個或多個正則表達式,則用戶需要定義這個宏。
-
YYCURSOR *YYCTYPE類型的表達式指針指向當前輸入的符號,生成的代碼作為符號相匹配,在開始的地方,YYCURSOR假定指向當前token的第一個字符。在結束時,YYCURSOR將會指向下一個token的第一個字符。
-
YYDEBUG(state,current) 這個只有指定-d標記的時候才會需要。調用用戶定義的函數時可以非常容易的調試生成的代碼。這個函數應該有以下簽名:void YYDEBUG(int state,char current)。第一個參數接受 state ,默認值為-1第二個參數接受輸入的當前位置。
-
YYFILL(n) 當緩沖器需要填充的時候,生成的代碼將會調用YYFILL(n):至少提供n個字符。YYFILL(n)將會根據需要調整YYCURSOR,YYLIMIT,YYMARKER 和 YYCTXMARKER。注意在典型的程序語言當中,n等于最長的關鍵詞的長度加一。用戶可以在/*!max:re2c_/一次定義YYMAXFILL來指定最長長度。如果使用了-1,YYMAXFILL將會在/*!re2c_/之后調用一次阻塞。
-
YYGETCONDITION() 如果使用了-c模式,這個定義將會在掃描器代碼之前獲取條件集。這個值必須初始化為枚舉YYCONDTYPE的類型。
-
YYGETSTATE() 如果指定了-f模式,用戶就需要定義這個宏。此種情況下,掃描器在開始時為了獲取保存的狀態,生成的代碼將會調用YYGETSTATE()。YYGETSTATE()必須返回一個有符號的整數,這個值如果是-1,告訴掃描器這是第一次執行,否則這個值等于以前YYSETSTATE(s) 保存的狀態。否則,掃描器將會恢復操作之后立即調用YYFILL(n)。
-
YYLIMIT 這是一個類型為*YYCTYPE的表達式,它標記了緩沖器的結尾(YYLIMIT[-1]是緩沖區的最后一個字符)。生成的代碼將會不斷的比較YYCORSUR 和 YYLIMIT 以決定 什么時候填充緩沖區。
-
YYSETCONDITION(c) 這個宏用來在轉換規則中設置條件,它只有在指定-c模式和使用轉換規則時有用。
-
YYSETSTATE(s) 用戶只需要在指定-f模式時定義這個宏,如果是這樣,生成的代碼將會在YYFILL(n)之前調用YYSETSTATE(s),YYSETSTATE的參數是一個有符號整型,被稱為唯一的標示特定的YYFILL(n)實例。
-
YYMARKER 類型為*YYCTYPE的表達式,生成的代碼保存回溯信息到YYMARKER。一些簡單的掃描器可能用不到。
-
解析器支持條件 當使用-c參數時,你可以使用正則表達式條件列表。這樣re2c會為每個條件生成掃描塊,在每一個生成的掃描器都有自己的先決條件。先決條件是定義YYGETCONDETION ,而且類型必須是YYCONDTYPE。
- YYSETSTATE(s) 用戶只需要在指定-f模式時定義這個宏。在此種情況下,生成的代碼將會在YYFILL(n)之前調用YYSETSTATE(s),YYSETSTATE的參數是一個有符號整型,被稱為唯一的標示特定的YYFILL(n)實例。如果用戶希望保存掃描器的狀態并用YYFILL(n) 將狀態返回給調用 者,他所需要做的是在變量中保存這個唯一的標識。然后,當再次調用掃描器時,它將調用
- YYGETSTATE()并在恢復到之前離開的地方繼續執行。即使禁用了 YYFILL(n) ,生成的代碼也會包含YYSETSTATE(s)和YYGETSTATE。
## Scanner With Storable States可存儲狀態的掃描器[]()
當指定-f標記時,re2c會生成一個存儲了它當前狀態的掃描器,它能精確的恢復到之前離開的位置,并返回給調用者。
re2c的默認行為是拉模式,無論何時需要,它都可以要求額外的輸入,然而,這種操作模式是基于掃描器可以控制解析循環這一前提的,而這個前提并不一定會存在。通常情況下,如果有一個預處理過程或其它相關的源程序數據在掃描器之前先執行,則掃描器無法再要求更多的數據,除非他們都在獨立的線程之中。
-f標記剛好可以解決這個問題:它讓用戶設計的掃描器以拉模式工作,即數據一塊一塊的輸入到掃描器中。當掃描器運行數據時,它僅存儲它的狀態,并返回給調用者。當更多的輸入數據輸入到掃描器時,它能很精確的恢復到之前離開的位置。
當re2c使用-f選項時,它不能接收標準輸入,因為它必須做兩次完整的全局掃描,而兩次掃描就需要讀取兩次。這就意味著,如果不能打開輸入兩次或第一次輸入影響第二次輸入,re2c會執行失敗。
相對于拉模式,可存儲的掃描器有以下不同:
1. 用戶必須提供YYSETSTATE() 宏和YYGETSTATE(state)宏
1. -f參數禁止了yych和yyaccept的聲明。因此用戶必須聲明這些,并且必須能夠保存和恢復他們。在example/push.re文件的示例中,這些都被聲明為C++類的字段,因此他們不再需要明確的保存或恢復。對于C語言來說,我們可以通過宏,以參數傳遞的方式從結構體中獲取這些字段。或者,可以將他們聲明為局部變量,當它決定返回并將之作為函數的一個項保存在 YYFILL(n)中。此外, 使用YYFILL(n)保存的效率更高,因為可以無條件的調用YYSETSTATE(state)。然而,YYFILL(n) 并不能將state作為參數,因此,我們必須通過YYSETSTATE(state)將state保存到局部變量中。
1. 如果需要更多的輸入,需要修改YYFILL(n) ,使之可以從調用它的函數處返回。
1. 修改調用者的邏輯,使其在需要更多的輸入時做出相應的應答。
1. 生成的代碼中將包含一個選擇邏輯塊,這個選擇邏輯會被用來通過跳轉到相應的YYFILL(n)調用處,以恢復最后的狀態。這個代碼塊會在第一個 "/*!re2c */"塊收尾的地方自動生成。通過放置 "/*!getstate:re2c */"注釋,可能會觸發YYGETSTATE() 的生成操作。這對于被包含在循環中的掃描器非常有用。
請查看 examples/push.re文件中的推模式示例掃描器。它生成的代碼可以通過"state:abort"和"state:nextlabel"調整。Scanner With Condition Support可判斷條件的掃描
當使用-c參數時,你可以在正則表達式之前優先一系統的條件名。在這種情況下,re2c會針對每個條件生成掃描代碼塊。這些代碼塊都有它自己的前置條件,這此前置條件都是通過接口定義YYGETCONDITON實現,并且必須為YYCONDTYPE類型。
其中有兩個特別的類型,一個是‘*’,它表示滿足所有條件;另一個是空條件,它提供一個沒有掃描內容的代碼塊,這意味著不需要任何正則表達式。這個特殊的塊始終有一個固定的枚舉值0。這些特殊的規則可以被用來初始化一個掃描器。這些特殊的規則并不是必須的,但是有時可以用它來聲明一些沒有初始化的狀態。
非空規則允許指定新的條件,這些條件將導致規則的變化。它會生成定義的YYSETCONDTITION,除此之外再無其它。
還有另一種特殊的規則,它允許在所有的有規則和沒有規則代碼前添加代碼。例如,它可以用來保存掃描的字符串的長度。這個特殊的規則以感嘆號開始,后面可以接條件 <! condition, ... > 或星號<!*>。當re2c為這個規則生成代碼時,如果這個規則的狀態沒有起始規則或已經在在一個星號規則,那么這個代碼將作為起始代碼。
## Scanner Specifications 掃描器規則[]()
每個掃描器規格都由 規則集、命名定義和配置構成。
規則由正則以及緊跟其后面的C/C++代碼構成,當正則匹配時,其后的C/C++代碼會被執行。你可以以大括號或:=開始代碼。當用大括號開始代碼時,re2c會根據大括號判斷其嘗試并自動結束代碼的查找。如果不使用大括號開始代碼,則re2c會在第一行不為空時停止查找。
regular-expression { C/C++ code }
regular-expression := C/C++ code
如果指定-c參數,則每個正則前面都會有一系列的由逗號分隔的條件名稱。除了正常命名的規則以外,有兩種特殊的情況。一個規則可能包含一個單獨的條件名稱'*'和沒有條件名稱。對于沒有條件名稱的情況,其后面不能接正則表達式。非空規則可能會進一步指定新的條件。在這種情況下,re2c可能會自動生成必要的代碼來改變條件。如上所示代碼,其以大括號和':='開始代碼。更進一步,更多的規則可以使用':=>'快捷方式來自動生成代碼,它不僅僅可以設置新的狀態,還可以繼續執行新的狀態。一個快捷規則不應該在循環中使用,這些循環代碼在循環開始和re2c塊之間,除非用 re2c:cond:goto使之 'continue;'如果一段代碼必須放在所有的規則之前,你可以使用<! 偽規則。
<condition-list> regular-expression { C/C++ code }<condition-list> regular-expression := C/C++ code
<condition-list> regular-expression => condition { C/C++ code }
<condition-list> regular-expression => condition := C/C++ code
<condition-list> regular-expression :=> condition
<*> regular-expression { C/C++ code }
<*> regular-expression := C/C++ code
<*> regular-expression => condition { C/C++ code }
<*> regular-expression => condition := C/C++ code
<*> regular-expression :=> condition
<> { C/C++ code }
<> := C/C++ code
<> => condition { C/C++ code }
<> => condition := C/C++ code
<> :=> condition
<!condition-list> { C/C++ code }
<!condition-list> := C/C++ code
<!*> { C/C++ code }
<!*> := C/C++ code
命名定義格式如下:
name = regular-expression;
如果使用了-F 模式,可以使用如下命名定義方法:
name regular-expression
以"re2c"開始的命名定義配置如下所示:
re2c:name = value;
re2c:name = "value";
## Summary Of Re2c Regular-expressionsre2c正則表達式小結[]()
- "foo" 字符串foo。可以使用ANSI-C轉義序列。
- [xyz] 字符集;此種情況匹配字符x,y或z
- [abj-oZ] 包含區間的字符集,此種情況匹配a,b,j到o之間的任一字符,或z
- [^class] 字符集否定匹配,匹配沒有在方括號中定義的字符。
- r\s 匹配非s的正則,r和s都必須是可以表示為字符集的正則表達式
- r* 零次或多次匹配,r是任一正則表達式
- r+ 一次或多次匹配(至少一次)
- r? 零次或一次匹配
- name 這里name就是在前面的定義段給出的名字
- (r) 匹配規則表達式r,圓括號可以提高其優先級。
- rs 匹配規則表達式r,其后緊跟著表達式s。這稱為聯接(concatenation)。
- r|s 或者匹配規則表達式r,或者匹配表達式s。
- r/s 匹配模式r,但是要求其后緊跟著模式s。s并不會參與文本的匹配。這種正則表達式的匹配稱之為“尾部上下文”
- r{n} n次匹配
- r{n,} 至少n次匹配
- r{n,m} 至少n次,至多m次匹配;匹配除換行符外的任意字符
- def 當沒有使用-F參數時,匹配的命名定義通過def定義。當-F參數指定時,def語名和雙引號包含的效果一樣,直接匹配def字符串。字符集和字符串可能包含有八進制或十六進制或如下的轉義字符 (\n, \t, \v, \b, \r, \f, \a, \)。一個八進制字符由一個反斜杠和緊跟著它的三個八進制數字組成,一個十六進制字符由一個反斜杠,一個小寫的x,以及兩個十六進制數字組成,或由一個反斜杠,一個大寫的X,以及四個十六進制數字組成。
re2c進一步會支持更多的C/C++的unicode符號。這些unicode符號由一個反斜杠+u+四個十六進制數字或一個反斜杠+U+八個十六進制的數字組成。然后,僅當-u模式下才能處理這些uincode字符。
在非unicode模式下,大于\X00FF的字符是無法直接匹配的,除非使用”萬金油“類型的 (.|"\n")和[^]正則表達式匹配所有的字符時,包含它們。
如上所示的正則表達式列表按優先級分組,從最上面的最高優先級到最下面的最低優先級。這些組合之間的優先級相同。
## Inplace Configuration現場配置[]()
它可能在re2c塊中配置并生成代碼,如下所示為可用的配置項:
-
re2c:condprefix = yyc_ ;允許指定條件標簽的前綴。它將在生成的輸出文件中的所有條件標簽前添加指定的前綴。
-
re2c:condenumprefix = yyc ;允許指定條件值的前綴。它將在生成的輸出文件中的所有條件枚舉值前添加指定的前綴。
-
re2c:cond:divider = "/* *********************************** */" ;允許為條件塊自定義分隔符。你可以使用'@@'輸出條件的名字或使用
-
re2c:cond:divider@cond = @@ ;指定即將被 re2c:cond:divider中的條件名替換的占位符。
-
re2c:cond:goto = "goto @@;" ;允許使用 ':=>' 規則自定義條件跳轉語句。你可以使用'@@'輸出條件的名字或使用re2c:cond:divider@cond自定義占位符,同時你也可以使用此語句繼續下一個循環周期,這個循環周期包括循環開始到re2c塊之間的任何代碼。
-
re2c:cond:goto@cond = @@ ;指定即將在 re2c:cond:goto語句中被替換的條件標簽占位符
-
re2c:indent:top = 0 ;指定最小的縮進,大于或等于0
-
re2c:indent:string = "\t" ;指定縮進用的字符串。除非你想使用外部工具,否則就需要只包含空白字符串。最簡單的方法就是用單引號或雙引號包含它們。如果你不需要任何縮進,直接使用""即可。
-
re2c:yych:conversion = 0 ;當此設置非零時,re2c會在讀取yych時自動生成轉換代碼。此時的類型必須使用re2c:define:YYCTYPE定義。
-
re2c:yych:emit = 1 ;設置為0可以禁止yych的生成。
-
re2c:yybm:hex = 0 ;如果設置為0,則生成一個十進制表格,否則將生成一個十六進制表格
-
re2c:yyfill:enable = 1 ;將此設置為0可以禁止YYFILL(n)的生成。當使用它時請確認生成的掃描器在輸入之后不再讀取。允許此行為將給你的程序引入服務安全問題。
-
re2c:yyfill:check = 1 ;當YYLIMIT + max(YYFILL)一直可用時,把此設置為0可以禁止使用YYCURSOR和YYLIMIT的先決條件的輸出。
-
re2c:yyfill:parameter = 1 ;允許禁止YYFILL調用的參數傳遞。如果設置為0,將沒有任何參數傳遞到YYFILL。然而,define:YYFILL@LEN允許指定一個字符串替換實際字符中的長度。如果設置為非0,除非設置re2c:define:YYFILL:naked,否則YYFILL將使用緊跟其后的大括號內的所要求的字符數。其它請參照:re2c:define:YYFILL:naked和re2c:define:YYFILL@LEN.
-
re2c:startlabel = 0 ;如果設置為0的整數,即使沒有掃描器本身,下一個掃描塊的開始標簽也會被生成。否則僅在需要的時候生成常規的yy0開始標簽。如果設置為一個文本值,不管常規的開始標簽生成是否,包含當前文本的標簽都會被生成。在開始標簽生成后,當前設置會被重置為0。
-
re2c:labelprefix = yy ;允許修改數字標簽的前綴,默認為yy,任何有效的標簽都是可以的。
-
re2c:state:abort = 0 ;當設置為非零,并且開啟-f模式時,YYGETSTATE 塊會包含一個默認的情況,初始化時設置為-1
-
re2c:state:nextlabel = 0 ;當開啟-f模式時,使用此設置可以控制是否在YYGETSTATE塊后面接yyNext標簽行。通常,你可以用startlabel配置強制指定開始標簽或用默認的yy0作為開始標簽,而不是用yyNext。通常我們通過放置"/*!getstate:re2c */" 注釋來分隔實際掃描器的YYGETSTATE 代碼,而不是專用的標簽。
-
re2c:cgoto:threshold = 9 ;當啟用-g模式時,這個值指定生成的跳轉表的復雜度閾值,而不是使用嵌套的if語句和決策位字段。
-
re2c:yych:conversion = 0 ;當輸入使用有符號字符時,并且開啟-s和-b械時,re2c會自動將其轉化為無符號類型。當設置為0時會禁用空字符串轉化。設置為非零時,轉化將在YYCTYPE處進行。如果這個值通過現場配置,則使用該值。否則,將會變成(YYCTYPE),并且不能再修改成配置。當設置為一個字符串時,必須用括號括起來。現在,假設你的輸入為char*并且使用上述的設置,你可以設置YYCTYPE為unsigned char,并且當前值設置為1或者"(unsigned char)"
-
re2c:define:define:YYCONDTYPE = YYCONDTYPE ;枚舉用于支持-c模式的條件
-
re2c:define:YYCTXMARKER = YYCTXMARKER ;允許覆蓋定義的YYCTXMARKER ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYCTYPE = YYCTYPE ;允許覆蓋定義的YYCTYPE ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYCURSOR = YYCURSOR ;允許覆蓋定義的YYCURSOR ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYDEBUG = YYDEBUG ;允許覆蓋定義的YYDEBUG ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYFILL = YYFILL ;允許覆蓋定義的YYFILL ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYFILL:naked = 0 ;當設置為1時,括號、參數、分號都會被發出。
-
re2c:define:YYFILL@len = @@ ;當使用 re2c:define:YYFILL 時,并且re2c:yyfill:parameter 為0時,YYFILL 中的任何文本將會被新的實際的長度值替換。
-
re2c:define:YYGETCONDITION = YYGETCONDITION ;允許覆蓋定義的YYGETCONDITION
-
re2c:define:YYGETCONDITION:naked = ;當設置為1時,括號、參數、分號都會被發出。
-
re2c:define:YYGETSTATE = YYGETSTATE ;允許覆蓋定義的YYGETSTATE ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYGETSTATE:naked = 0 ;當設置為1時,括號、參數、分號都會被發出。
-
re2c:define:YYLIMIT = YYLIMIT ;允許覆蓋定義的YYLIMIT ,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYMARKER = YYMARKER ;允許覆蓋定義YYMARKER,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYSETCONDITION = YYSETCONDITION ;允許覆蓋定義的YYSETCONDITION
-
re2c:define:YYSETCONDITION@cond = @@ ;當使用 re2c:define:YYSETCONDITION時,YYSETCONDITION中的任何文本將會被新的實際的條件值替換。
-
re2c:define:YYSETSTATE = YYSETSTATE ;允許覆蓋定義的YYSETSTATE,從而避免將其設置為實際所需的代碼。
-
re2c:define:YYSETSTATE:naked = 0 ;當設置為1時,括號、參數、分號都會被發出。
-
re2c:define:YYSETSTATE@state = @@ ;當使用re2c:define:YYSETSTATE時,YYSETCONDITION中的任何文本將會被新的實際的狀態值替換
-
re2c:label:yyFillLabel = yyFillLabel ;允許覆蓋標簽yyFillLabel,即可以自定義生成的yyFillLabel 變量名。
-
re2c:label:yyNext = yyNext ;允許覆蓋標簽yyNext ,即可以自定義生成的yyNext變量名。
-
re2c:variable:yyaccept = yyaccept ;允許覆蓋變量yyaccept,即可以自定義生成的yyaccept變量名。
-
re2c:variable:yybm = yybm ;允許覆蓋變量yybm,即可以自定義生成的yybm變量名。
-
re2c:variable:yych = yych ;允許覆蓋變量yych,即可以自定義生成的yych變量名。
-
re2c:variable:yyctable = yyctable ;當指定-c參數和-g參數時,re2c會使用此變量為YYGETCONDITION生成靜態跳轉表。
-
re2c:variable:yystable = yystable ;當指定-f參數和-g參數時,re2c會使用此變量為YYGETSTATE生成靜態跳轉表。
-
re2c:variable:yytarget = yytarget ;允許覆蓋變量yytarget,即可以自定義生成的yytarget變量名。
## Understanding Re2c 理解re2c[]()
re2c的子目錄中包含各種例子教你一步一步的如何開啟re2c的世界,所有的例子都是可編譯運行的。
## Features特點[]()
re2c不提供默認的動作:生成的代碼假定輸入包含一系列token。通常,可以通過添加一條規則實現,例如上面示例中的異常字符
因為re2c不提供結束表達式,所以用戶必須安排一個輸入結束符并讓一個規則匹配并捕獲它。如果來源是一個以空字符串結尾的字符串,則匹配一個空字符串就可以了。如果來源是一個文件,你可以在文件后添加一個換行(或其它不會出現的標記);通過識別這個字符,以檢查這是否為一個標記點并執行相應的操作。同樣,你也可以使用YYFILL(n)判斷是否沒有足夠的字符可用時結束掃描。
BugsDifference only works for character sets.The re2c internal algorithms need documentation.See Alsoflex(1), lex(1).More information on re2c can be found here:http://re2c.org/Authors
Peter Bumbulis [peter@csg.uwaterloo.ca](#)Brian Young [bayoung@acm.org](#)Dan Nuffer [nuffer@users.sourceforge.net](#)Marcus Boerger [helly@users.sourceforge.net](#)Hartmut Kaiser [hkaiser@users.sourceforge.net](#)Emmanuel Mogenet [mgix@mgix.com](#) added storable state
英文原地址:http://re2c.org/manual.html譯者:胖子(http://www.phppan.com/)友情協助:吳帥(http://www.imsiren.com/)校驗:reeze(http://www.reeze.cn)
- 第一章 準備工作和背景知識
- 第一節 環境搭建
- 第二節 源碼結構、閱讀代碼方法
- 第三節 常用代碼
- 第四節 小結
- 第二章 用戶代碼的執行
- 第一節 生命周期和Zend引擎
- 第二節 SAPI概述
- Apache模塊
- 嵌入式
- FastCGI
- 第三節 PHP腳本的執行
- 詞法分析和語法分析
- opcode
- opcode處理函數查找
- 第四節 小結
- 第三章 變量及數據類型
- 第一節 變量的結構和類型
- 哈希表(HashTable)
- PHP的哈希表實現
- 鏈表簡介
- 第二節 常量
- 第三節 預定義變量
- 第四節 靜態變量
- 第五節 類型提示的實現
- 第六節 變量的生命周期
- 變量的賦值和銷毀
- 變量的作用域
- global語句
- 第七節 數據類型轉換
- 第八節 小結
- 第四章 函數的實現
- 第一節 函數的內部結構
- 函數的內部結構
- 函數間的轉換
- 第二節 函數的定義,傳參及返回值
- 函數的定義
- 函數的參數
- 函數的返回值
- 第三節 函數的調用和執行
- 第四節 匿名函數及閉包
- 第五節 小結
- 第五章 類和面向對象
- 第一節 類的結構和實現
- 第二節 類的成員變量及方法
- 第三節 訪問控制的實現
- 第四節 類的繼承,多態及抽象類
- 第五節 魔術方法,延遲綁定及靜態成員
- 第六節 PHP保留類及特殊類
- 第七節 對象
- 第八節 命名空間
- 第九節 標準類
- 第十節 小結
- 第六章 內存管理
- 第一節 內存管理概述
- 第二節 PHP中的內存管理
- 第三節 內存使用:申請和銷毀
- 第四節 垃圾回收
- 新的垃圾回收
- 第五節 內存管理中的緩存
- 第六節 寫時復制(Copy On Write)
- 第七節 內存泄漏
- 第八節 小結
- 第七章 Zend虛擬機
- 第一節 Zend虛擬機概述
- 第二節 語法的實現
- 詞法解析
- 語法分析
- 實現自己的語法
- 第三節 中間代碼的執行
- 第四節 PHP代碼的加密解密
- 第五節 小結
- 第八章 線程安全
- 第二節 線程,進程和并發
- 第三節 PHP中的線程安全
- 第九章 錯誤和異常處理
- 第十章 輸出緩沖
- 第十六章 PHP語言特性的實現
- 第一節 循環語句
- foreach的實現
- 第二十章 怎么樣系列(how to)
- 附錄
- 附錄A PHP及Zend API
- 附錄B PHP的歷史
- 附錄C VLD擴展使用指南
- 附錄D 怎樣為PHP貢獻
- 附錄E phpt測試文件說明
- 附錄F PHP5.4新功能升級解析
- 附錄G:re2c中文手冊