下面來分析
flex文件的最后一部份,就是輔助代碼部份,這部份代碼是原封不動地拷貝到生成的文件里。它的代碼如下:
#001?%%
這個雙百分號開始,就表示
flex文件的第三部分開始了。
?
#002?
#003?LLScriptAllocationManager?*gAllocationManager;
定義分配管理器指針。
?
#004 ?LLScriptScript
???????????? *gScriptp;
定義腳本的指針。
?
#005?
#006?// Prototype for the yacc parser entry point
#007?int yyparse(void);
前置聲明
yacc的語法分析的函數。
?
#008?
#009?int yyerror(const char *fmt, ...)
#010?{
#011?
?? gErrorToText.writeError(yyout, gLine, gColumn, LSERROR_SYNTAX_ERROR);
#012?
?? return 0;
#013?}
分析出錯時輸出錯誤位置。
?
#014?
#015?//#define EMERGENCY_DEBUG_PRINTOUTS
#016?//#define EMIT_CIL_ASSEMBLER
#017?
?
下面開始進行腳本編譯處理。
#018?BOOL lscript_compile(const char* src_filename, const char* dst_filename,
#019?
?????????????????? ?const char* err_filename, BOOL is_god_like)
#020?{
#021?
?? BOOL??????????? b_parse_ok = FALSE;
#022?
?? BOOL??????????? b_dummy = FALSE;
#023?
?? U64???????????? b_dummy_count = FALSE;
#024?
?? LSCRIPTType???? type = LST_NULL;
#025?
#026?
?? gInternalColumn = 0;
#027?
?? gInternalLine = 0;
#028?
?? gScriptp = NULL;
#029?
#030?
?? gErrorToText.init();
#031?
?? init_supported_expressions();
#032?
?? init_temp_jumps();
#033?
?? gAllocationManager = new LLScriptAllocationManager();
#034?
?
下面打開腳本文件。
#035?
?? yyin = LLFile::fopen(src_filename, "r");
#036?
?? if (yyin)
#037?
?? {
?
打開錯誤輸出文件。
#038?
?????? yyout = LLFile::fopen(err_filename, "w");
#039?
#040?
?????? // Reset the lexer's internal buffering.
#041?
?
讀入腳本文件。
#042?
?? ????yyrestart(yyin);
#043?
?
進行語法分析。
#044?
?????? b_parse_ok = !yyparse();
#045?
#046?
?????? if (b_parse_ok)
#047?
?????? {
?
語法分析成功。
#048?#ifdef EMERGENCY_DEBUG_PRINTOUTS
#049?
?????????? char compiled[256];
#050?
?????????? sprintf(compiled, "%s.o", src_filename);
#051?
?????????? FILE* compfile;
#052?
?????????? compfile = LLFile::fopen(compiled, "w");
#053?#endif
#054?
#055?
?????????? if(dst_filename)
#056?
?????????? {
#057?
?????????????? gScriptp->setBytecodeDest(dst_filename);
#058?
?????????? }
#059?
#060?
?????????? gScriptp->mGodLike = is_god_like;
#061?
#062?
?????????? gScopeStringTable = new LLStringTable(16384);
#063?#ifdef EMERGENCY_DEBUG_PRINTOUTS
?
下面的代碼遍歷語法樹,生成腳本的中間代碼。
#064?
?????????? gScriptp->recurse(compfile, 0, 4, LSCP_PRETTY_PRINT, LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count, NULL, NULL,
#065?0, NULL, 0, NULL);
#066?#endif
#067?
?????????? gScriptp->recurse(yyout, 0, 0, LSCP_PRUNE,????? LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count,
#068?NULL, NULL, 0, NULL, 0, NULL);
#069?
?????????? gScriptp->recurse(yyout, 0, 0, LSCP_SCOPE_PASS1, LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0,
#070?NULL, 0, NULL);
#071?
?????????? gScriptp->recurse(yyout, 0, 0, LSCP_SCOPE_PASS2, LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count, NULL, NULL, 0,
#072?NULL, 0, NULL);
#073?
?????????? gScriptp->recurse(yyout, 0, 0, LSCP_TYPE,?????? LSPRUNE_INVALID, b_dummy, NULL, type, type, b_dummy_count,
#074?NULL, NULL, 0, NULL, 0, NULL);
#075?
?????????? if (!gErrorToText.getErrors())
#076?
?????????? {
#077?
?????????????? gScriptp->recurse(yyout, 0, 0, LSCP_RESOURCE, LSPRUNE_INVALID,????? b_dummy,
#078?NULL, type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);
#079?#ifdef EMERGENCY_DEBUG_PRINTOUTS
#080 ?
?????????????? gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_ASSEMBLY, LSPRUNE_INVALID,?b_dummy, NULL, type, type,
#081?b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);
#082?#endif
#083?#ifdef EMIT_CIL_ASSEMBLER
#084?
?????????????? const char* cil_output_file_name = dst_filename? dst_filename : "lscript.cil";
#085?
?????????????? FILE* cilout = LLFile::fopen(cil_output_file_name, "w");
#086?
?????????????? if(NULL == cilout)
#087?
?????????????? {
#088?
?????????????????? fprintf(yyout, "Error opening cil output file %s/n", cil_output_file_name);
#089?
?????????????? }
#090?
?????????????? else
#091?
?????????????? {
#092?
?????????????????? gScriptp->recurse(cilout, 0, 0, LSCP_EMIT_CIL_ASSEMBLY, LSPRUNE_INVALID,?b_dummy, NULL,
#093?type, type, b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);
#094?
?????????????????? if(fclose(cilout) == EOF)
#095?
?????????????????? {
#096?
?????????????????????? fprintf(yyout, "Error closing cil output file %s/n", cil_output_file_name);
#097?
?????????????????? }
#098?
?????????????? }
#099?#endif
#100?
?????????????? gScriptp->recurse(yyout, 0, 0, LSCP_EMIT_BYTE_CODE, LSPRUNE_INVALID, b_dummy, NULL, type, type,
#101?b_dummy_count, NULL, NULL, 0, NULL, 0, NULL);
#102?
?????????? }
#103?
?????????? delete gScopeStringTable;
#104?
?????????? gScopeStringTable = NULL;
#105?#ifdef EMERGENCY_DEBUG_PRINTOUTS
#106?
?????????? fclose(compfile);
#107?#endif
#108?
?????? }
#109?
?????? fclose(yyout);
#110?
?? }
#111?
#112?
?? fclose(yyin);
#113?
?? delete gAllocationManager;
#114?
?? delete gScopeStringTable;
#115?
??
#116?
?? return b_parse_ok && !gErrorToText.getErrors();
#117?}
#118?
#119?
輸入文件名稱的腳本編譯函數。
#120?BOOL lscript_compile(char *filename, BOOL is_god_like = FALSE)
#121?{
?
生成輸入和輸出文件名稱。
#122?
?? char src_filename[MAX_STRING];
#123?
?? sprintf(src_filename, "%s.lsl", filename);
#124?
?? char err_filename[MAX_STRING];
#125?
?? sprintf(err_filename, "%s.out", filename);
?
調用前面腳本編譯函數。
#126?
?? return lscript_compile(src_filename, NULL, err_filename, is_god_like);
#127?}
#128?
#129?
?
下面處理
GCC編譯問題。
#130?S32 yywrap()
#131?{
#132?#if defined(FLEX_SCANNER) && !defined(LL_WINDOWS)
#133?
?? // get gcc to stop complaining about lack of use of yyunput
#134?
?? (void) yyunput;
#135?#endif
#136?
?? return(1);
#137?}
#138?
?
跳過所有腳本注釋部份。
#139?void comment()
#140?{
#141?
?? char c;
#142?
#143?
?? while ((c = yyinput()) != '/n' && c != 0 && c != EOF)
#144?
?????? ;
#145?}
#146?
?
統計編譯所在的行號和列號。
#147?void count()
#148?{
#149?
?? S32 i;
#150?
#151?
?? gColumn = gInternalColumn;
#152?
?? gLine = gInternalLine;
#153?
#154?
?? for (i = 0; yytext[i] != '/0'; i++)
#155?
?????? if (yytext[i] == '/n')
#156?
?????? {
#157?
?????????? gInternalLine++;
#158?
?????????? gInternalColumn = 0;
#159?
?????? }
#160?
?????? else if (yytext[i] == '/t')
#161?
?????????? gInternalColumn += 4 - (gInternalColumn % 8);
#162?
?????? else
#163?
?????????? gInternalColumn++;
#164?}
#165?
?
分析腳本的字符串。
#166?void parse_string()
#167?{
#168?
?? S32 length = (S32)strlen(yytext);
#169?
?? length = length - 2;
#170?
?? char *temp = yytext + 1;
#171?
#172?
?? S32 i;
#173?
?? S32 escapes = 0;
#174?
?? S32 tabs = 0;
#175?
?? for (i = 0; i < length; i++)
#176?
?? {
#177?
?????? if (temp[i] == '//')
#178?
?????? {
#179?
?????????? escapes++;
#180?
?????????? i++;
#181?
?????????? if (temp[i] == 't')
#182?
?????????????? tabs++;
#183?
?????? }
#184?
?? }
#185?
#186?
?? S32 newlength = length - escapes + tabs*3;
#187?
?? yylval.sval = new char[newlength + 1];
#188?
#189?
?? char *dest = yylval.sval;
#190?
#191?
?? for (i = 0; i < length; i++)
#192?
?? {
#193?
?????? if (temp[i] == '//')
#194?
?????? {
#195?
?????????? i++;
#196?
?????????? // linefeed
#197?
?????????? if (temp[i] == 'n')
#198?
?????????? {
#199?
?????? ??????? *dest++ = 10;
#200?
?????????? }
#201?
?????????? else if (temp[i] == 't')
#202?
?????????? {
#203?
?????????????? *dest++ = ' ';
#204?
?????????????? *dest++ = ' ';
#205?
?????????????? *dest++ = ' ';
#206?
?????????????? *dest++ = ' ';
#207?
?????????? }
#208?
?????????? else
#209?
?????????? {
#210?
?????????????? *dest++ = temp[i];
#211?
?????????? }
#212?
?????? }
#213?
?????? else
#214?
?????? {
#215?
?????????? *dest++ = temp[i];
#216?
?????? }
#217?
?? }
#218?
?? yylval.sval[newlength] = 0;
#219?}
#220?
?
輔助代碼部份主要調用語法分析生成函數來編譯腳本,當然語法分析的函數里又調用詞法分析的函數來獲取所需要的單詞,最后生成腳本的樹中間代碼。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
