锘??xml version="1.0" encoding="utf-8" standalone="yes"?> 鍦―FA涓紝鏌愪釜鐘舵佸搴斿埌ε-NFA涓殑鑻ュ共鐘舵侊紝搴旀鎴戜滑灝嗕細寰楀埌涓嬮潰榪欐牱鐨勪竴涓粨鏋勩?/p> 鍙互鐪嬪埌錛屼負浜嗚皟璇曟柟渚挎垜浠湪緇撴瀯涓畾涔変簡鐘舵佺殑鍞竴ID浠ュ強瀵瑰簲鍒?#949;-NFA鐘舵佺殑闆嗗悎鍜屼竴涓爣璁頒綅銆?/p>
鍏充簬鑷姩鏈虹殑璇存槑錛岃繖閲屼笉涓嶅啀澶嶈堪錛岃鍒?a href="http://zh.wikipedia.org/wiki/鑷姩鏈? target="_blank">http://zh.wikipedia.org/wiki/鑷姩鏈?/a>鏌ョ湅銆?/p>
棣栧厛錛屾垜浠瀹氳〃杈懼紡涓彧鍏佽杈撳叆Char_Type鍜孲tring_Type綾誨瀷鐨勫瓧絎︺?/p>
瀵逛簬涓涓姸鎬佹潵璇達紝鎴戜滑騫朵笉闇瑕佺煡閬撲粬鐨勪換浣曚俊鎭?/p>
鍦ㄤ笂闈㈢殑浠g爜涓紝涓轟簡璋冭瘯鏂逛究錛屾垜涓哄叾鍔犲叆浜唅dx鍩燂紝騫朵負姣忎釜鐘舵佸垎閰嶄簡涓涓敮涓鐨処D銆?/p>
ε-NFA涓殑杈歸兘鏄湁鍚戠殑銆傚浜庝換鎰忎竴鏉¤竟鏉ヨ錛屾渶閲嶈鐨勬槸浠栫殑涓や釜绔偣鏄皝浠ュ強榪欐潯杈規墍瀵瑰簲鐨勫瓧絎﹂泦錛堣嫢榪欐潯杈逛笉鏄?#949;杈癸級銆?/p>
鏈変簡浠ヤ笂涓や釜緇撴瀯涔嬪悗錛屾垜浠負Rule娣誨姞涓変釜鎴愬憳鍙橀噺 pEpsilonStart鍜宲EpsilonEnd鍒嗗埆琛ㄧず榪欐潯琛ㄨ揪寮忔墍瀵瑰簲鐘舵佹満鐨剆tart鍜宔nd鐘舵侊紝epsilonNFA_Edges鍒欐槸浠ユ煇涓姸鎬佷綔涓簁ey錛屼粠榪欎釜鐘舵佸埌杈懼彟涓涓姸鎬佹墍緇忚繃鐨勮竟浣滀負value鐨刪ash琛ㄣ?/p>
緇堜簬鍒頒簡姝i錛岄鍏堬紝鎴戜滑鎶婃墍鏈夌殑鍏崇郴鍒嗕負涓茶仈鍏崇郴銆佸茍鑱斿叧緋匯佸彲閫夊叧緋匯?嬈″強浠ヤ笂鐨勯噸澶嶅叧緋匯佽嚦灝?嬈′互涓婄殑閲嶅鍏崇郴鍜屽彇鍙嶅叧緋匯備笅闈㈠垎鍒粙緇嶆瘡縐嶅叧緋葷殑ε-NFA濡備綍鏉ョ敓鎴愩傦紙涓嬫枃涓嫢娌℃湁鎸囧嚭榪炴帴杈圭殑綾誨瀷鍒欐槸ε杈?/strong>錛?/p>
姝e涓婃枃鎵璇達紝瀛楃闆嗗寘鎷珻har_Type鍜孲tring_Type綾誨瀷鐨勫瓧絎︼紝搴旀鐢熸垚瀛楃闆嗙殑鐘舵佹満灝辨瘮杈冪畝鍗曚簡錛屽彧闇鍒涘緩鍑轟袱涓姸鎬侊紝鐒跺悗閫氳繃涓鏉$粡榪囪繖涓瓧絎﹂泦鐨勮竟灝嗚繖涓や釜鐘舵佹寜鐓ф煇涓柟鍚戣繛鎺ワ紝鏈鍚庡皢涓涓姸鎬佹爣璁頒負start鐘舵侊紝鍙︿竴涓姸鎬佹爣璁頒負end鐘舵佸嵆鍙?/p>
涓茶仈鍏崇郴涓紝鍙渶瑕佸皢鍓嶄竴涓姸鎬佹満鐨別nd鐘舵侀氳繃ε杈硅繛鎺ュ埌鍙︿竴涓姸鎬佹満鐨剆tart鐘舵侊紝鏈鍚庡皢鍓嶄竴涓姸鎬佺殑start鐘舵佹爣璁頒負鏂扮姸鎬佹満鐨剆tart鐘舵侊紝鍚庝竴涓姸鎬佹満鐨別nd鐘舵佹爣璁頒負鏂扮姸鎬佹満鐨別nd鐘舵佸嵆鍙?/p>
騫惰仈鍏崇郴涓紝闇瑕佸垎鍒柊寤轟竴涓猻tart鍜宔nd鐘舵佸仛涓烘柊鐘舵佹満鐨剆tart鍜宔nd鐘舵侊紝鐒跺悗灝嗘柊鐢熸垚鐨剆tart鐘舵佸垎鍒繛鎺ュ埌鍘熺姸鎬佹満鐨剆tart鐘舵侊紝鍘熺姸鎬佹満鐨別nd鐘舵佽繛鎺ュ埌鏂扮敓鎴愮殑end鐘舵佸嵆鍙?/p>
鍦ㄦ鍒欒〃杈懼紡涓瓨鍦ㄥ艦濡?a)+鍜?a)*鐨勪袱縐嶉噸澶嶅叧緋伙紝瀵逛簬榪欎袱縐嶉噸澶嶅叧緋伙紝鐢熸垚鐨勭姸鎬佹満鐨勫尯鍒粎鍦ㄤ簬end鐘舵佸浜庝竴嬈′互涓婄殑閲嶅錛屽彧闇瑕佺粰鍘熺姸鎬佹満娣誨姞涓鏉′粠end鐘舵佸埌start鐘舵佺殑ε杈瑰嵆鍙傝屽浜庨浂嬈′互涓婄殑閲嶅錛屼笉鍏夐渶瑕佹坊鍔?#949;杈癸紝鍚屾椂闇瑕佸皢鏂扮姸鎬佹満鐨別nd鐘舵佹爣璁頒負start鐘舵侊紝鍥犱負闆舵閲嶅鏃朵笉闇瑕佺粡榪囦換鎰忚竟鏃㈠彲琚帴鍙椼?/p>
涓婇潰榪欎笁縐嶆槸鏈鍩烘湰鐨勭敓鎴愭柟娉曪紝閫氳繃浠ヤ笂榪欎笁縐嶇敓鎴愭柟娉曞凡瓚沖搴斾粯澶氭暟鐨勮〃杈懼紡銆?/p>
涓嬮潰鏉ョ湅鐪嬩竴浜涙嫇灞曞艦寮忕殑鐘舵佹満鏄浣曠敓鎴愮殑銆?/p>
鍦ㄥ彲閫夊叧緋諱腑錛屽彧闇瑕佺粰鍘熺姸鎬佹満娣誨姞涓鏉′粠start鐘舵佸埌end鐘舵佺殑ε杈瑰嵆鍙傜敱浜?#949;-NFA鍙厑璁告湁涓涓猻tart鍜宔nd鐘舵佺殑鍏崇郴錛屽簲姝ゅ綋鏉′歡涓嶆垚绔嬫椂浠巗tart鐘舵佸氨鍙洿鎺ラ氳繃ε杈瑰埌杈緀nd鐘舵併?/p>
鐢變簬鎴戜滑鍙鐞咰har_Type鍜孲tring_Type綾誨瀷鐨勫瓧絎﹂泦錛屽簲姝ゅ浜庡彇鍙嶆垜浠彧闇瑕佸皢褰撳墠鐘舵佹満鍐呮墍鏈夌被鍨嬩負TChar鎴朤String綾誨瀷鐨勮竟鍙栦竴涓嬪弽鍗沖彲錛?strong>闇瑕佹敞鎰忕殑鏄彲鑳藉瓨鍦ㄨ礋璐熷緱姝g殑鎯呭喌錛屾棦鍙栧伓鏁版鍙嶇瓑浜庢病鍙栧弽 鎵璋撶殑char-char鍏崇郴灝辨槸姝e垯琛ㄨ揪寮忎腑鐨刐a-z]琛ㄨ揪寮忋傚叾瀹炶繖鏄竴縐嶅茍鑱斿叧緋葷殑鎷撳睍錛岀敱涓や釜鍘熷鐘舵佹満鎷撳睍鍒頒簡N涓紝鐢熸垚鏂規硶涔熺被浼箋?/p>
璁╂垜浠潵緙栧啓涓涓嚱鏁版潵鎵撳嵃鍑烘暣涓敓鎴愬悗鐨勭姸鎬佹満銆?/p>
鏈鍚庢垜浠潵緙栧啓涓浜涙祴璇曚唬鐮佹潵璇曡瘯鐢熸垚鏁堟灉濡備綍 鍙墦鍗板嚭濡備笅鍐呭 鏈鍚庡艦鎴愬艦濡備笅鍥劇殑鐘舵佹満 瀹屾暣鐨勪唬鐮佸彲鍒?a target="_blank">http://code.google.com/p/qlanguage涓嬭澆銆?/p>
璇村埌ParserGenerator涓嶅緱涓嶆彁鐨勬槸BNF錛屽簲姝ParserGenerator涔熸湁瀹冭嚜宸辯殑BNF錛岃繖鏃舵湁浜轟細闂瓸NF絀剁珶鏄粈涔堝憿錛熺畝鍗曠殑璇碆NF灝辨槸鐢ㄦ潵鎻忚堪涓縐嶈娉曠殑涓滆タ錛屾瘮濡傚湪Basic涓璉f鍚庨潰璺熻〃杈懼紡鐒跺悗鏄疶hen涓棿鏄鍙ュ潡鏈熬蹇呴』瑕佹湁End If絳夌瓑鐨勪竴緋誨垪鎻忚堪錛屾洿涓撲笟鐨勮В閲婃垜浠彲浠ョ湅涓涓?a target="_blank">緇村熀鐧劇涓婄殑瑙i噴銆?br />
濂戒簡錛岃瀹屼簡BNF閭h鎴戜滑鏉ョ湅涓涓婹ParserGenerator鐨凚NF鍒板簳鏄暱鍟ユ牱鐨?br />
%start start;
strings -> strings "{String}"
| "{String}"
;
vs -> vs "{Letter}"
| vs "{String}"
| "{Letter}"
| "{String}"
;
option -> "[" vs "]"
;
oneProductionRight -> oneProductionRight option
| oneProductionRight vs
| option
| vs
;
someProductionRight -> someProductionRight "|" oneProductionRight
| oneProductionRight
;
token -> "%" "token" strings ";"
;
someTokens -> someTokens token
| token
;
production -> "{Letter}" "-" ">" someProductionRight ";"
;
someProductions -> someProductions production
| production
;
start -> someTokens "%" "start" "{Letter}" ";" someProductions
| "%" "start" "{Letter}" ";" someProductions
;
棣栧厛鍙互鐪嬪埌鏈欏朵笂鏈変竴浜涗互%token寮澶寸殑瀛楃涓詫紙鍦–璇█涓垜浠皢鐢ㄥ弻寮曞彿鎷搗鏉ョ殑瀛楃搴忓垪縐頒負瀛楃涓詫級浠ュ強鏈鍚庣殑涓涓垎鍙鳳紝鍏跺疄榪欓噷鐨勮繖浜涘瓧絎︿覆姝f槸BNF涓璇寸殑緇堢粨絎︼紝鎵浠ユ垜浠瀹氾紝鎵鏈夊叾浠栨病鐢?token澹版槑鐨勭鍙烽兘鏄潪緇堢粨絎︺傜粓緇撶鏄敤鏉ュ仛縐昏繘鎿嶄綔鐨勶紝鍦ㄦ煇縐嶇壒瀹氱殑璇█涓粬琛ㄧ幇涓轟竴涓猼oken錛岃岄潪緇堢粨絎﹀彲浠ョ悊瑙d負涓涓唬璇嶏紝閫氬父涓涓潪緇堢粨絎﹂兘鍙互灞曞紑涓轟竴鏉℃垨澶氭潯瑙勫垯錛?a target="_blank">浜х敓寮?/a>錛夈傝嚦浜庤涓轟粈涔堟瘡鏉″唴瀹瑰悗闈㈤兘浼氭湁鍒嗗彿鍛紝鍙槸涓轟簡澶勭悊涓婄殑鏂逛究錛堟秷闄よ娉曚笂鐨勫啿紿侊紵錛夈?br />
濂戒簡錛屾垜浠妸緇堢粨絎﹀拰闈炵粓緇撶榪欎袱涓笓涓氭湳璇粰瑙i噴瀹屼簡錛屾帴涓嬫潵鍙互鐪嬪埌鐨勬槸涓涓互%start寮澶村悗璺熶竴涓潪緇堢粨絎︾殑璇彞錛屼粬琛ㄦ槑浜嗘墍鏈夎鍒欙紙浜х敓寮?/a>錛夋槸浠庡摢閲屽紑濮嬬殑錛堟湁濮嬫棤緇堢殑鑺傚-_-||鏉叿鍟婏級銆?br />
鏈鍚庡氨鏄垜浠殑閲嶅ご浜嗭紝澶氱┖涓琛屼篃涓嶄負榪囧惂銆傝繖閲屾湁涓澶у爢鐨勪駭鐢熷紡錛岄偅鎴戜滑濡備綍鏉ラ槄璇諱粬鍛紝鍏跺疄涓婇潰宸茬粡浠嬬粛浜嗘湁涓〃鏄庝簡鎵鏈夎鍒欏紑澶寸殑闈炵粓緇撶錛屽ソ閭h鎴戜滑鏉ユ壘涓涓嬩粬鎵瀵瑰簲鐨勪駭鐢熷紡鍦ㄥ摢閲?br />
| "%" "start" "{Letter}" ";" someProductions
;
涓嬮潰璁╂垜浠潵鐪嬩竴涓嬮瀹氫箟鐨勭粓緇撶鏈夊摢浜涳紝浠?a target="_blank">Parser.cpp鐨勪唬鐮佷腑鍙煡棰勫畾涔夌殑緇堢粨絎︽湁"{String}"銆?{Digit}"銆?{Real}"銆?{Letter}"銆?br />
"{String}"錛氳〃紺烘鍒欒〃杈懼紡\"[^\"]*\"
"{Digit}"錛氳〃紺烘鍒欒〃杈懼紡[0-9]+
"{Real}"錛氳〃紺烘鍒欒〃杈懼紡[0-9]*.[0-9]+
"{Letter}"錛氳〃紺烘鍒欒〃杈懼紡((_[0-9]+)|([_a-zA-Z]+))[_0-9a-zA-Z]*
浠庤繖浜涙鍒欒〃杈懼紡涓彲瑙?{String}"琛ㄧず涓涓甫鍙屽紩鍙風殑瀛楃涓詫紝"{Digit}"鍒欒〃紺轟竴涓暟瀛楋紝"{Real}"鍒欒〃紺轟竴涓誕鐐規暟錛?{Letter}"鍒欒〃紺轟竴涓笉甯﹀弻寮曞彿鐨勫瓧絎︿覆銆傚綋鐒惰繖浜涙鍒欒〃杈懼紡鍐欑殑騫朵笉瀹屽錛屾瘮濡?{String}"涓病鏈夋敮鎸佽漿涔夌瓑絳夈?br />
鐒跺悗璁╂垜浠潵鐪嬩竴涓嬫瘡鏉¤鍒欐敮鎸佸摢浜涜娉曪紝棣栧厛浠庝笅闈㈠嚑鏉℃枃娉曚腑鍙煡錛屽彲鐢ㄦ柟鎷彿灝嗕竴浜涘彲閫夐」鎷搗鏉ャ?br />
2 | vs "{String}"
3 | "{Letter}"
4 | "{String}"
5 ;
6
7 option -> "[" vs "]"
8 ;
鑰屽浜庝竴涓鍒欐潵璇翠粬鍙互鐢ㄨ嫢騫叉潯浜х敓寮忔潵璇存槑浠栵紝鍏朵腑姣忔潯浜х敓寮忎箣闂存槸鎴?/font>鐨勫叧緋匯?br />
2 | oneProductionRight vs
3 | option
4 | vs
5 ;
6
7 someProductionRight -> someProductionRight "|" oneProductionRight
8 | oneProductionRight
9 ;
鍏朵粬涓浜涜鍒欏垯璇存槑浜嗕竴浜涗笂鏂囨彁鍒扮殑瑙勫垯錛屾瘮濡傚紑澶存槸涓浜泃oken鐨勫畾涔夌瓑銆傜粓浜庢妸QParserGenerator鐨勬枃娉曟枃浠剁殑緇撴瀯緇欎粙緇嶅畬浜嗭紝鍦ㄦ帴涓嬫潵鐨勪竴綃囨枃绔犱腑鎴戜滑灝嗕粙緇嶅浣曠敤QParserGenerator鏉ョ敓鎴愪竴涓甫鎷彿浼樺厛綰х殑鍥涘垯娣峰悎榪愮畻璁$畻鍣紝鍏舵枃娉曞彲瑙?a target="_blank">Calculator.txt錛孮Language鏁翠釜欏圭洰鐨勪唬鐮佸彲瑙?a target="_blank">https://github.com/lwch/QLanguage/銆?img src ="http://www.shnenglu.com/lwch/aggbug/203576.html" width = "1" height = "1" />
]]>
搴旀錛岀浉搴旂殑make鍑芥暟鍙樻垚浜?br />
{
vector<LALR1Production> v;
v.push_back(inputProductions[begin][0]);
pStart = closure(v);
pStart->idx = Item::inc();
context.states.insert(pStart);
items.push_back(pStart);
queue<Item*> q;
q.push(pStart);
vector<Item*> changes;
bool bContinue = false;
while (!q.empty())
{
Item* pItem = q.front();
vector<Production::Item> s;
symbols(pItem, s);
select_into(s, vts, compare_production_item_is_vt, push_back_unique_vector<Production::Item>);
select_into(s, vns, compare_production_item_is_vn, push_back_unique_vector<Production::Item>);
for (vector<Production::Item>::const_iterator i = s.begin(), m = s.end(); i != m; ++i)
{
Item* pNewItem = NULL;
if (go(pItem, *i, pNewItem))
{
long n = itemIndex(pNewItem);
if (n == -1)
{
pNewItem->idx = Item::inc();
q.push(pNewItem);
items.push_back(pNewItem);
context.states.insert(pNewItem);
}
else
{
items[n]->mergeWildCards(pNewItem, bContinue);
changes.push_back_unique(items[n]);
destruct(pNewItem, has_destruct(*pNewItem));
Item_Alloc::deallocate(pNewItem);
}
edges[pItem].push_back_unique(Edge(pItem, n == -1 ? pNewItem : items[n], *i));
}
}
q.pop();
}
while (bContinue)
{
vector<Item*> v;
v.reserve(changes.size());
bContinue = false;
for (vector<Item*>::const_iterator i = changes.begin(), m = changes.end(); i != m; ++i)
{
vector<Production::Item> s;
symbols(*i, s);
for (vector<Production::Item>::const_iterator j = s.begin(), n = s.end(); j != n; ++j)
{
Item* pNewItem = NULL;
if (go(*i, *j, pNewItem))
{
long n = itemIndex(pNewItem);
if (n == -1) throw error<const char*>("unknown item", __FILE__, __LINE__);
else
{
items[n]->mergeWildCards(pNewItem, bContinue);
v.push_back_unique(items[n]);
destruct(pNewItem, has_destruct(*pNewItem));
Item_Alloc::deallocate(pNewItem);
}
}
}
}
changes = v;
}
}
涓涓ず渚?/strong>
涓嬮潰鎴戜滑鐢ㄤ竴涓緥瀛愭潵璇存槑LALR1 DFA鏄浣曠敓鎴愮殑錛岄鍏堝畠鐨勬枃娉曞涓?br />
| R "+"
| R
;
L -> "*" R
| "id"
;
R -> L
;
棣栧厛鎴戜滑鍐欏嚭榪欎釜鏂囨硶鐨勫騫挎枃娉?br />
wildCards:
#
S -> . L "=" R
wildCards:
#
S -> . R "+"
wildCards:
#
S -> . R
wildCards:
#
L -> . "*" R
wildCards:
"=" "+"
L -> . "id"
wildCards:
"=" "+"
R -> . L
wildCards:
"+" #
棣栧厛鐢ㄧ鍙稴姹傚嚭鏂扮姸鎬?br />
wildCards:
#
鎺ヤ笅鏉ョ敤絎﹀彿L姹傚嚭鏂扮姸鎬?br />
wildCards:
#
R -> L
wildCards:
"+" #
鐒跺悗鐢ㄧ鍙稲姹傚嚭鏂扮姸鎬?br />
wildCards:
#
S -> R
wildCards:
#
鐒跺悗鐢ㄧ鍙?姹傚嚭鏂扮殑鐘舵?br />
wildCards:
"=" "+"
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
鐒跺悗鏄鍙穒d鐨?br />
wildCards:
"=" "+"
榪欐牱錛屼粠start鐘舵佽漿縐誨嚭鏉ョ殑5鏉¤竟灝辯敓鎴愬ソ浜嗭紝涓嬮潰鏉ョ湅鐪嬭繖5涓柊鐢熸垚鐨勭姸鎬佸張浼氱敓鎴愪竴浜涗粈涔堝憿
wildCards:
#
wildCards:
#
R -> L
wildCards:
"+" #
wildCards:
#
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
wildCards:
#
S -> R
wildCards:
#
wildCards:
#
wildCards:
"=" "+"
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
1.閫氳繃絎﹀彿R杞Щ鍒版柊鐘舵?br />
wildCards:
"=" "+"
2.閫氳繃絎﹀彿L杞Щ鍒版柊鐘舵?br />
wildCards:
"+" # "="
3.閫氳繃*鍒欏彲杞Щ鍒板畠鑷繁
4.閫氳繃id杞Щ鍒扮5涓姸鎬?br />
絎簲涓姸鎬佸垯娌℃湁浠諱綍鐨勮漿縐匯?br />
wildCards:
#
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
1.閫氳繃絎﹀彿R鍙漿縐誨埌鏂扮姸鎬?br />
wildCards:
#
2.閫氳繃絎﹀彿L鍙漿縐誨埌鐘舵?
3.閫氳繃絎﹀彿*鍙漿縐誨埌鐘舵?
4.閫氳繃絎﹀彿id鍙漿縐誨埌鐘舵?
絎?銆?銆?涓姸鎬侀兘娌℃湁浠諱綍杞Щ
鐒跺悗璁╂垜浠潵鐪嬩笅changes鍒楄〃閲屾湁鍝簺涓滆タ錛屾牴鎹?a href="http://www.shnenglu.com/lwch/archive/2013/05/12/200203.html" target="_blank">涓婁竴綃?/a>鐨勭畻娉曞彲鐭ワ紝鎵鏈夊凡瀛樺湪鐨勭姸鎬侀兘鍦╟hanges鍒楄〃閲岋紝搴旀瀹冮噷闈㈠簲璇ヤ細鏈?銆?鍜?涓変釜鐘舵併?br />
鑷蟲錛屾暣涓嚜鐢熺殑閮ㄥ垎瀹屾垚浜嗭紝涓嬮潰鎴戜滑灝嗗叾鐢繪垚涓寮犲浘
涓嬮潰鏄紶鎾儴鍒?/strong>
鍦ㄧ涓嬈′紶鎾椂changes鍒楄〃閲屾湁3涓姸鎬侊紝鍒嗗埆瀵硅繖3涓姸鎬佺敤go鍑芥暟姹傚嚭鏂扮殑灞曟湜絎︼紝騫舵妸瀹冧滑鍚堝茍鍒板師鏈夌殑鐘舵佷笂銆?br />
棣栧厛鐪嬬姸鎬?錛屽畠鏈?涓姸鎬佽漿縐葷錛屽垎鍒槸R銆丩銆?鍜宨d
1.閫氳繃絎﹀彿R鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"=" "+" #
2.閫氳繃絎﹀彿L鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"+" # "="
3.閫氳繃絎﹀彿*鍙漿縐誨埌瀹冭嚜宸憋紝鍚屾椂瀹冪殑灞曟湜絎﹀涓?br />
wildCards:
"=" "+" #
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
4.閫氳繃絎﹀彿id鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"=" "+" #
鐒跺悗鎴戜滑鏉ョ湅涓涓嬬姸鎬?鍜?錛屽畠浠病鏈変換浣曠姸鎬佽漿縐葷錛屽簲姝ゅ畠浠笉浼氫紶鎾換浣曞睍鏈涚銆?br />
鐜板湪changes鍒楄〃閲屾湁4涓姸鎬侊紝鍒嗗埆涓?銆?銆?鍜?錛屽張鐢變簬絎?涓姸鎬佸凡緇忎駭鐢熶簡鏂扮殑灞曟湜絎?搴旀闇瑕佺戶緇紶鎾?br />
絎簩嬈′紶鎾?/strong>
棣栧厛鍏堢湅鐘舵?鍜?錛屽畠浠病鏈変換浣曠姸鎬佽漿縐葷錛屽簲姝ゅ畠浠笉浼氫紶鎾換浣曞睍鏈涚銆?br />
鐒跺悗鏉ョ湅鐘舵?錛屽悓鏍風殑瀹冩湁4涓姸鎬佽漿縐葷錛屽垎鍒負R銆丩銆?鍜宨d銆?br />
1.閫氳繃絎﹀彿R鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"=" "+" #
2.閫氳繃絎﹀彿L鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"+" # "="
3.閫氳繃絎﹀彿*鍙漿縐誨埌瀹冭嚜宸憋紝鍚屾椂瀹冪殑灞曟湜絎﹀涓?br />
wildCards:
"=" "+" #
R -> . L
wildCards:
"+" # "="
L -> . "*" R
wildCards:
"=" "+" #
L -> . "id"
wildCards:
"=" "+" #
4.閫氳繃絎﹀彿id鍙漿縐誨埌鐘舵?錛屽悓鏃跺畠鐨勫睍鏈涚濡備笅
wildCards:
"=" "+" #
鏈鍚庢垜浠潵鐪嬬姸鎬?錛屽畠娌℃湁浠諱綍鐘舵佽漿縐葷錛屽簲姝ゅ畠涓嶄細浼犳挱浠諱綍灞曟湜絎︺?br />
鐜板湪changes鍒楄〃閲屽悓鏍鋒湁4涓姸鎬侊紝鍒嗗埆涓?銆?銆?鍜?錛岀敱浜庢病鏈変竴涓姸鎬佷駭鐢熶簡鏂扮殑灞曟湜絎︼紝搴旀瀹冨皢涓嶄細緇х畫浼犳挱涓嬪幓浜嗐?br />
鐜板湪鏁翠釜鏂囨硶鐨凞FA灝辯敓鎴愬畬姣曚簡錛岃鎴戜滑鏉ヤ慨鏀逛竴涓嬪師鍏堢殑閭e紶鍥炬潵鐪嬬湅鏈緇堢殑DFA鏄粈涔堟牱鐨勩?br />
鏁翠釜紺轟緥灝卞厛浠嬬粛鍒拌繖閲岋紝鍦ㄦ帴涓嬫潵鐨勪竴綃囨枃绔犱腑灝嗕細閫氳繃鍑犱釜紺轟緥鏉ヤ粙緇峜losure鍜実o鍑芥暟鐨勫師鐞嗭紝甯屾湜榪欑鐢辯矖鍒扮粏鐨勮瑙i『搴忚兘澶熻璇昏呮墍鎺ュ彈銆傛渶鍚庡畬鏁寸殑浠g爜鍙埌http://code.google.com/p/qlanguage涓嬭澆銆?img src ="http://www.shnenglu.com/lwch/aggbug/200608.html" width = "1" height = "1" />
]]>
]]>DFA鐨勭姸鎬?/h1>
struct DFA_State
{
set<EpsilonNFA_State*> content;
bool bFlag;
#ifdef _DEBUG
uint idx;
#endif
DFA_State(const set<EpsilonNFA_State*>& x) : content(x), bFlag(false)
{
#ifdef _DEBUG
idx = inc();
#endif
}
inline const bool operator==(const DFA_State& x)const
{
if (&x == this) return true;
return content == x.content;
}
#ifdef _DEBUG
inline uint inc()
{
static uint i = 0;
return i++;
}
#endif
};
DFA鐨勮竟
]]>琛ㄨ揪寮?/h1>
template <typename Char_Type, typename String_Type>
class Rule
{
};
ε-NFA鐨勭姸鎬?/h1>
struct EpsilonNFA_State
{
#ifdef _DEBUG
uint idx;
EpsilonNFA_State()
{
idx = inc();
}
static uint inc()
{
static uint i = 0;
return i++;
}
#else
EpsilonNFA_State() {}
#endif
};
ε-NFA鐨勮竟
struct EpsilonNFA_Edge
{
struct
{
Char_Type char_value;
String_Type string_value;
}data;
enum Edge_Type
{
TUnknown = 0,
TNot = 1,
TChar = 2,
TString = 4,
TEpsilon = 8
};
uchar edge_type;
EpsilonNFA_State* pFrom;
EpsilonNFA_State* pTo;
EpsilonNFA_Edge(EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TEpsilon), pFrom(pFrom), pTo(pTo) {}
EpsilonNFA_Edge(const Char_Type& x, EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TChar), pFrom(pFrom), pTo(pTo)
{
data.char_value = x;
}
EpsilonNFA_Edge(const String_Type& x, EpsilonNFA_State* pFrom, EpsilonNFA_State* pTo) : edge_type(TString), pFrom(pFrom), pTo(pTo)
{
data.string_value = x;
}
inline void negate()
{
edge_type ^= TNot;
}
inline const bool isNot()const
{
return (edge_type & TNot) == TNot;
}
inline const bool isEpsilon()const
{
return (edge_type & TEpsilon) == TEpsilon;
}
inline const bool isChar()const
{
return (edge_type & TChar) == TChar;
}
inline const bool isString()const
{
return (edge_type & TString) == TString;
}
const Edge_Type edgeType()const
{
if (isEpsilon()) return TEpsilon;
else if (isChar()) return TChar;
else if (isString()) return TString;
else return TUnknown;
}
};
EpsilonNFA_State *pEpsilonStart, *pEpsilonEnd;
hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash> epsilonNFA_Edges;
鐢熸垚鐘舵佹満
瀛楃闆?/h2>
Rule(const Char_Type& x, Context& context) : pDFAStart(NULL), context(context)
{
pEpsilonStart = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonStart);
pEpsilonEnd = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonEnd);
epsilonNFA_Edges[pEpsilonStart].push_back(EpsilonNFA_Edge(x, pEpsilonStart, pEpsilonEnd));
context.epsilonNFA_States.insert(pEpsilonStart);
context.epsilonNFA_States.insert(pEpsilonEnd);
}
Rule(const String_Type& x, Context& context) : pDFAStart(NULL), context(context)
{
pEpsilonStart = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonStart);
pEpsilonEnd = EpsilonNFA_State_Alloc::allocate();
construct(pEpsilonEnd);
epsilonNFA_Edges[pEpsilonStart].push_back(EpsilonNFA_Edge(x, pEpsilonStart, pEpsilonEnd));
context.epsilonNFA_States.insert(pEpsilonStart);
context.epsilonNFA_States.insert(pEpsilonEnd);
}
涓茶仈鍏崇郴
self operator+(const self& x)
{
self a = cloneEpsilonNFA(*this), b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, b.pEpsilonStart));
a.pEpsilonEnd = b.pEpsilonEnd;
return a;
}
騫惰仈鍏崇郴
self operator|(const self& x)
{
self a = cloneEpsilonNFA(*this), b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
EpsilonNFA_State* _pStart = EpsilonNFA_State_Alloc::allocate();
construct(_pStart);
EpsilonNFA_State* _pEnd = EpsilonNFA_State_Alloc::allocate();
construct(_pEnd);
context.epsilonNFA_States.insert(_pStart);
context.epsilonNFA_States.insert(_pEnd);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, a.pEpsilonStart));
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, b.pEpsilonStart));
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, _pEnd));
a.epsilonNFA_Edges[b.pEpsilonEnd].push_back(EpsilonNFA_Edge(b.pEpsilonEnd, _pEnd));
a.pEpsilonStart = _pStart;
a.pEpsilonEnd = _pEnd;
return a;
}
閲嶅鍏崇郴
self operator*()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges.insert(EpsilonNFA_Edge(a.pEpsilonEnd, a.pEpsilonStart));
a.pEpsilonEnd = a.pEpsilonStart;
return a;
}
self operator+()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, a.pEpsilonStart));
return a;
}
涓浜涙嫇灞?/h1>
鍙夊叧緋?/h2>
inline self opt()
{
self a = cloneEpsilonNFA(*this);
a.epsilonNFA_Edges[a.pEpsilonStart].push_back(EpsilonNFA_Edge(a.pEpsilonStart, a.pEpsilonEnd));
return a;
}
鍙栧弽鍏崇郴
self operator!()
{
self a = cloneEpsilonNFA(*this);
for (typename hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash>::iterator i = a.epsilonNFA_Edges.begin(), m = a.epsilonNFA_Edges.end(); i != m; ++i)
{
for (typename vector<EpsilonNFA_Edge>::iterator j = i->second.begin(), n = i->second.end(); j != n; ++j)
{
if (j->isChar() || j->isString()) j->negate();
}
}
return a;
}
Char-Char鍏崇郴
self operator-(const self& x)
{
self a = cloneEpsilonNFA(*this);
if (epsilonNFA_Edges.size() == 1 && x.epsilonNFA_Edges.size() == 1 &&
epsilonNFA_Edges.begin()->second.size() == 1 && x.epsilonNFA_Edges.begin()->second.size() == 1 &&
epsilonNFA_Edges.begin()->second.begin()->edge_type == EpsilonNFA_Edge::TChar && x.epsilonNFA_Edges.begin()->second.begin()->edge_type == EpsilonNFA_Edge::TChar)
{
EpsilonNFA_State* _pStart = EpsilonNFA_State_Alloc::allocate();
construct(_pStart);
EpsilonNFA_State* _pEnd = EpsilonNFA_State_Alloc::allocate();
construct(_pEnd);
context.epsilonNFA_States.insert(_pStart);
context.epsilonNFA_States.insert(_pEnd);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, a.pEpsilonStart));
a.epsilonNFA_Edges[a.pEpsilonEnd].push_back(EpsilonNFA_Edge(a.pEpsilonEnd, _pEnd));
const Char_Type chStart = epsilonNFA_Edges.begin()->second.begin()->data.char_value;
const Char_Type chEnd = x.epsilonNFA_Edges.begin()->second.begin()->data.char_value;
for (Char_Type ch = chStart + 1; ch < chEnd; ++ch)
{
self y(ch, context);
copyEpsilonNFA_Edges(y, a);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, y.pEpsilonStart));
a.epsilonNFA_Edges[y.pEpsilonEnd].push_back(EpsilonNFA_Edge(y.pEpsilonEnd, _pEnd));
}
self b = cloneEpsilonNFA(x);
copyEpsilonNFA_Edges(b, a);
a.epsilonNFA_Edges[_pStart].push_back(EpsilonNFA_Edge(_pStart, b.pEpsilonStart));
a.epsilonNFA_Edges[b.pEpsilonEnd].push_back(EpsilonNFA_Edge(b.pEpsilonEnd, _pEnd));
a.pEpsilonStart = _pStart;
a.pEpsilonEnd = _pEnd;
}
else
{
throw error<string>("doesn't support", __FILE__, __LINE__);
}
return a;
}
灝懼0
void printEpsilonNFA()
{
printf("-------- ε- NFA Start --------\n");
for (typename hashmap<EpsilonNFA_State*, vector<EpsilonNFA_Edge>, _hash>::const_iterator i = epsilonNFA_Edges.begin(), m = epsilonNFA_Edges.end(); i != m; ++i)
{
for (typename vector<EpsilonNFA_Edge>::const_iterator j = i->second.begin(), n = i->second.end(); j != n; ++j)
{
printf("%03d -> %03d", j->pFrom->idx, j->pTo->idx);
switch (j->edgeType())
{
case EpsilonNFA_Edge::TEpsilon:
printf("(ε)");
break;
case EpsilonNFA_Edge::TChar:
printf("(%c)", j->data.char_value);
break;
case EpsilonNFA_Edge::TString:
printf("(%s)", j->data.string_value.c_str());
break;
default:
break;
}
if (j->isNot()) printf("(not)");
printf("\n");
}
}
printf("start: %03d -> end: %03d\n", pEpsilonStart->idx, pEpsilonEnd->idx);
printf("--------- ε- NFA End ---------\n");
}
Rule_Type::Context context;
Rule_Type a('a', context), b('b', context), d('d', context);
Rule_Type result = (a - d).opt() + (+b | !(a + b));
#ifdef _DEBUG
result.printEpsilonNFA();
#endif
2 {
3 I temp = input;
4 if(O Result = left.Parser(input)) return Result;
5 input = temp;
6 if(O Result = right.Parser(input)) return Result;
7 input = temp;
8 O Result(GetMM());
9 return Result;
10 }
搴旀鎴戜負CParser_Input澧炲姞浜嗕袱涓垚鍛樺彉閲忎繚瀛樻鏃剁殑SymbolStack鍜孲tringStack鐨凷ize,褰揝ymbolStack鍜孲tringStack Push鐨勬椂鍊欏悓鏃跺鍔爄nput鐩稿簲鐨勫?
鏈鍚庨噸杞紺Parser_Input鐨刼perator=璧嬪兼搷浣滅,鍦ㄥ叾涓牴鎹師鍏堢殑SymbolStack鍜孲tringStack鐨凷ize鏉ュ脊鍑虹浉搴旀暟閲忕殑閲嶅鍊?br />
2 {
3 LexerTokenList = _value.LexerTokenList;
4 index = _value.index;
5
6 if(_value.symbolCount < symbolCount && _value.symbolCount)
7 {
8 int Count = symbolCount - _value.symbolCount;
9 for(int i=0;i<Count;i++) SymbolStack.Pop();
10 }
11
12 if(_value.stringCount < stringCount && _value.stringCount)
13 {
14 int Count = stringCount - _value.stringCount;
15 for(int i=0;i<Count;i++) StringStack.Pop();
16 }
17
18 symbolCount = SymbolStack.Size();
19 stringCount = StringStack.Size();
20 return *this;
21 }
]]>
1.AST鐨勬瘡涓妭鐐圭敱2涓煙緇勬垚,榪?涓煙鍒嗗埆琛ㄧず褰撳墠鑺傜偣鐨勭被鍨嬪拰闄勫姞淇℃伅銆?br />2.AST鐨勬瘡涓妭鐐瑰寘鍚竴涓寚鍚戝叾瀛愯妭鐐圭殑欏哄簭琛ㄣ?br />3.AST鐨勬瘡涓妭鐐瑰寘鍚寚鍚戜笅涓涓妭鐐圭殑鎸囬拡銆?br />緇間笂鎵榪版垜浠緱鍒癆ST鑺傜偣鐨勪唬鐮侊細
2 {
3 public:
4 CSyntaxTreeNode(int _type,int _value) : type(_type),value(_value){}
5
6 inline List<NAutoPtr<CSyntaxTreeNode>>& Child()
7 {
8 return child;
9 }
10
11 inline NAutoPtr<CSyntaxTreeNode> Next()
12 {
13 return next;
14 }
15
16 inline int& Type()
17 {
18 return type;
19 }
20
21 inline int& Value()
22 {
23 return value;
24 }
25 protected:
26 int type;
27 int value;
28 List<NAutoPtr<CSyntaxTreeNode>> child;
29 NAutoPtr<CSyntaxTreeNode> next;
30 };
2 enum TYPE
3 {
4 stNull,
5 stDeclare,
6 stFunction,
7 stParamterList,
8 stIf,
9 stDo,
10 stExp,
11 };
2 {
3 public:
4 inline void Push(NAutoPtr<CSyntaxTreeNode>& Node)
5 {
6 SyntaxTreeStack.Push(Node);
7 }
8
9 inline NAutoPtr<CSyntaxTreeNode> Pop()
10 {
11 return SyntaxTreeStack.Pop();
12 }
13
14 inline NAutoPtr<CSyntaxTreeNode> Top()
15 {
16 return SyntaxTreeStack.Top();
17 }
18
19 inline NAutoPtr<CSyntaxTreeNode> Root()
20 {
21 return SyntaxTreeRoot;
22 }
23 protected:
24 NAutoPtr<CSyntaxTreeNode> SyntaxTreeRoot; // 璇硶鏍戞牴鑺傜偣
25 Stack<NAutoPtr<CSyntaxTreeNode>> SyntaxTreeStack; // 璇硶鏍戞爤
26 };
榪欓噷鎴戜滑綆鍗曠殑鍒嗘瀽涓涓嬪垎鏋愯繃紼嬶細
浠f璇彞涓轟緥錛屽叾緇勫悎瀛愪唬鐮佷負錛?br />
2 (str_then + stmt_list)[if_desc_second] +
3 Parser_Combinator_Node::opt((str_else + stmt_list)[if_desc_third]) +
4 (str_end + str_if)[if_desc_fourth];
2 declare b as integer
3 end if
鍒嗘瀽榪囩▼濡備笅鍥撅細
1.
2.
3.
4.
5.
6.
7.
]]>
2 end class
2.綾諱腑鍙互鍖呭惈(澹版槑錛屽嚱鏁幫紝鏂扮被銆傚叾涓櫎浜哻lass閮藉惈鏈塸ublic銆乸rivate銆乸rotected鍜宻tatic灞炴?
2 [public] declare a as string // 澹版槑
3
4 [private] [static] function main() // 鍑芥暟
5 end function
6
7 class b // 鏂扮被
8 end class
9 end class
2 end function
2 stmt_list
3 [else stmt_list]
4 end if
2 stmt_list
3 while experience end
2 stmt_list
3 end while
2 stmt_list
3 next
2 case experience:
3 [stmt_list]
4 [case experience:
5 [stmt_list]]
6 [default:
7 [stmt_list]]
8 end switch
2 璧嬪艱鍙?br /> 3 symbol
4 string
5 number
6 true
7 false
8 (+|-)experience
9 not experience
10 experience (&|||^|%) experience
11 experience (>|<|>=|<=|==|!=) experience
12 experience (+|-|*|/) experience
13 ++symbol
14 --symbol
15 symbol++
16 symbol--
緇勫悎瀛愪唬鐮?br />
2 item = declare_desc |
3 class_desc |
4 function_desc;
5 property_desc = str_public |
6 str_private |
7 str_protected;
8 declare_type = str_integer |
9 str_string |
10 str_bool |
11 str_real |
12 type_symbol;
13 paramter_desc_list = (type_symbol + str_as + declare_type) +
14 *(str_comma + type_symbol + str_as + declare_type);
15 paramter_value_list = exp_desc + *(str_comma + exp_desc);
16 declare_desc = str_declare + type_symbol + str_as + declare_type +
17 *(str_comma + type_symbol + str_as + declare_type);
18 class_desc = str_class + type_symbol +
19 Parser_Combinator_Node::opt(str_inherit + type_symbol +
20 *(str_comma + (type_symbol & Parser_Combinator_Node::not(str_class | str_function | property_desc | str_static)))
21 ) + *class_content_desc + str_end + str_class;
22 class_content_desc = (Parser_Combinator_Node::opt(property_desc) + Parser_Combinator_Node::opt(str_static) +
23 (declare_desc | function_desc)) |
24 class_desc;
25 function_desc = (str_function + type_symbol) +
26 (str_leftbracket + Parser_Combinator_Node::opt(paramter_desc_list) + str_rightbracket) +
27 Parser_Combinator_Node::opt(str_as + declare_type) +
28 stmt_list +
29 (str_end + str_function);
30 stmt_list = *(stmt & Parser_Combinator_Node::not(str_end));
31 stmt = declare_desc |
32 if_desc |
33 do_desc |
34 while_desc |
35 for_desc |
36 switch_desc |
37 exp_desc;
38 if_desc = (str_if + exp_desc) +
39 (str_then + stmt_list) +
40 Parser_Combinator_Node::opt(str_else + stmt_list) +
41 (str_end + str_if);
42 do_desc = (str_do + stmt_list) +
43 (str_while + exp_desc + str_end);
44 while_desc = str_while + exp_desc + str_do + stmt_list + str_end + str_while;
45 for_desc = str_for + stmt_list + str_to + exp_desc + str_by + stmt_list + str_do + stmt_list + str_next;
46 switch_desc = str_switch + exp_desc + str_do + case_list + str_end + str_switch;
47 case_list = *case_desc;
48 case_desc = (str_case + exp_desc + str_colon + stmt_list) |
49 (str_default + str_colon + stmt_list);
50 assign_desc = type_symbol + str_equal + exp_desc;
51 call_desc = type_symbol + str_leftbracket + Parser_Combinator_Node::opt(paramter_value_list) + str_rightbracket;
52 logic_desc = (str_not + compare_desc) |
53 (compare_desc + *((str_operator_and | str_operator_or | str_xor | str_mod) + compare_desc));
54 compare_desc = term_desc + *((str_bigger | str_smaller |
55 str_bigger_equal | str_smaller_equal |
56 str_equal_equal | str_not_equal) + term_desc);
57 term_desc = factor_desc + *((str_add | str_sub) + factor_desc);
58 factor_desc = self_desc + *((str_mul | str_div) + self_desc);
59 self_desc = (str_add_add + type_symbol) |
60 (str_sub_sub + type_symbol) |
61 (type_symbol + str_add_add) |
62 (type_symbol + str_sub_sub) |
63 value_desc;
64 value_desc = call_desc |
65 assign_desc |
66 type_symbol |
67 type_string |
68 type_number |
69 str_true |
70 str_false |
71 ((str_add | str_sub) + logic_desc) |
72 (str_leftbracket + logic_desc + str_rightbracket);
73 exp_desc = logic_desc;
濡傛湁浠諱綍琛ュ厖灝嗕細鍦ㄦ鏂囨。鏇存柊銆?br />
]]>
淇浜嗕竴浜涜繍琛屾椂鐨凚ug.
鏀寔浜嗗崟琛屾敞閲?/鍜屽琛屾敞閲?* */
鏀寔浜嗘墍鏈夌殑鍑芥暟澹版槑褰㈠紡.
ESEngine_Demo5.rar
1.Samples鏂囦歡澶逛笅鏈夊嚑涓緥瀛?br>2.鍑芥暟鐩墠鍙啓浜?br> "function" "{Symbol}" "{LQ}" "{RQ}" stmt_list "end" "function"
"function" "{Symbol}" "{LQ}" "{RQ}" "end" "function"
"function" "{Symbol}" "{LQ}" paramter_list "{RQ}" "as" var_type stmt_list "end" "function"
榪欎笁綾?鎵浠ュ浜?br> function mn(integer s)
stmts
end function
鍦ㄧ敓鎴愯娉曟爲鏃朵細浜х敓閿欒
ESEngine_Demo1_0.rar