第二人生的源码分析(110)脚本的语法分析(5)

 

在脚本里有很多语句组成的,那么对于语句又是怎么进行语法分析的呢?下面就来分析for语句的分析过程,它的声明代码如下:

#001  class LLScriptFor : public LLScriptStatement

#002  {

#003  public:

 

构造函数,输入保存的值。

#004     LLScriptFor(S32 line, S32 col, LLScriptExpression *sequence, LLScriptExpression *expression, LLScriptExpression *expressionlist, LLScriptStatement *statement)

#005         : LLScriptStatement(line, col, LSSMT_FOR), mSequence(sequence), mExpression(expression), mExpressionList(expressionlist), mStatement(statement),

#006  mType(LST_NULL)

#007     {

#008     }

#009 

 

析构造函数。

#010     ~LLScriptFor()

#011     {

#012     }

#013 

 

递归处理函数。

#014     void recurse(FILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type,

#015  LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);

 

获取语句生成代码的大小。

#016     S32 getSize();

#017 

 

初始化表达式。

#018     LLScriptExpression      *mSequence;

 

条件判断表达式。

#019     LLScriptExpression      *mExpression;

 

最后执行的表达式列表。

#020     LLScriptExpression      *mExpressionList;

 

循环体的语句块。

#021     LLScriptStatement       *mStatement;

 

脚本的类型。

#022     LSCRIPTType             mType;

#023  };

 

 

下面来分析它的递归调用函数的处理:

#001  void LLScriptFor::recurse(FILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type,

#002  LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)

#003  {

 

如果分析出错就返回。

#004     if (gErrorToText.getErrors())

#005     {

#006         return;

#007     }

 

下面根据不同的遍来处理。

#008     switch(pass)

#009     {

 

打印输出脚本的代码。

#010     case LSCP_PRETTY_PRINT:

#011         fdotabs(fp, tabs, tabsize);

#012         fprintf(fp, "for ( ");

#013         if(mSequence)

#014             mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#015  NULL);

#016         fprintf(fp, " ; ");

#017         mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);

#018         fprintf(fp, " ; ");

#019         if(mExpressionList)

#020             mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry,

#021  entrycount, NULL);

#022         fprintf(fp, " )/n");

#023         if(mStatement)

#024             mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#025  NULL);

#026         break;

 

 

下面输出编译出来的汇编代码。

#027     case LSCP_EMIT_ASSEMBLY:

#028         {

#029             S32 tjump1 =  gTempJumpCount++;

#030             S32 tjump2 =  gTempJumpCount++;

#031             if(mSequence)

#032                 mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#033  entry, entrycount, NULL);

#034             fprintf(fp, "LABEL ##Temp Jump %d##/n", tjump1);

#035             mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#036  NULL);

#037             fprintf(fp, "JUMPNIF ##Temp Jump %d##/n", tjump2);

#038             if(mStatement)

#039                 mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#040  entry, entrycount, NULL);

#041             if(mExpressionList)

#042                 mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#043  entry, entrycount, NULL);

#044             fprintf(fp, "JUMP ##Temp Jump %d##/n", tjump1);

#045             fprintf(fp, "LABEL ##Temp Jump %d##/n", tjump2);

#046         }

#047         break;

 

下面优化代码,如果代码不用运行,就可以删除。

#048     case LSCP_PRUNE:

#049         if (ptype == LSPRUNE_DEAD_CODE)

#050             prunearg = TRUE;

#051         else

#052             prunearg = FALSE;

#053         break;

 

下面进行for语句的类型检查。

#054     case LSCP_TYPE:

#055         if(mSequence)

#056             mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#057  NULL);

#058         mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);

#059         mType = type;

#060         if(mExpressionList)

#061             mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry,

#062  entrycount, NULL);

#063         if(mStatement)

#064             mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#065  NULL);

#066         break;

 

下面生成for语句的目标代码。

#067     case LSCP_EMIT_BYTE_CODE:

#068         {

#069             char jumpname1[32];        /*Flawfinder: ignore*/

#070             snprintf(jumpname1, sizeof(jumpname1), "##Temp Jump %d##", gTempJumpCount++);   /* Flawfinder: ignore */

#071             char jumpname2[32];            /*Flawfinder: ignore*/

#072             snprintf(jumpname2, sizeof(jumpname2), "##Temp Jump %d##", gTempJumpCount++);   /* Flawfinder: ignore */

#073 

#074             if(mSequence)

#075                 mSequence->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap,

#076  stacksize, entry, entrycount, NULL);

#077             chunk->addLabel(jumpname1);

#078             mExpression->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry,

#079  entrycount, NULL);

#080             chunk->addByte(LSCRIPTOpCodes[LOPC_JUMPNIF]);

#081             chunk->addByte(LSCRIPTTypeByte[mType]);

#082             chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);

#083             chunk->addJump(jumpname2);

#084             if(mStatement)

#085                 mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#086  entry, entrycount, NULL);

#087             if(mExpressionList)

#088                 mExpressionList->recurse(fp, tabs, tabsize, LSCP_TO_STACK, ptype, prunearg, scope, type, basetype, count, chunk,

#089  heap, stacksize, entry, entrycount, NULL);

#090             chunk->addByte(LSCRIPTOpCodes[LOPC_JUMP]);

#091             chunk->addBytes(LSCRIPTDataSize[LST_INTEGER]);

#092             chunk->addJump(jumpname1);

#093             chunk->addLabel(jumpname2);

#094         }

#095         break;

 

下面生成CIL的汇编代码。

#096     case LSCP_EMIT_CIL_ASSEMBLY:

#097         {

#098             S32 tjump1 =  gTempJumpCount++;

#099             S32 tjump2 =  gTempJumpCount++;

#100             if(mSequence)

#101                 mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#102  entry, entrycount, NULL);

#103             fprintf(fp, "LabelTempJump%d:/n", tjump1);

#104             mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#105  NULL);

#106             fprintf(fp, "brfalse LabelTempJump%d/n", tjump2);

#107             if(mStatement)

#108                 mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#109  entry, entrycount, NULL);

#110             if(mExpressionList)

#111                 mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize,

#112  entry, entrycount, NULL);

#113             fprintf(fp, "br LabelTempJump%d/n", tjump1);

#114             fprintf(fp, "LabelTempJump%d:/n", tjump2);

#115         }

#116         break;

 

下面进行递归处理for里出现的表达式。

#117     default:

#118         if(mSequence)

#119             mSequence->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#120  NULL);

#121         mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);

#122         if(mExpressionList)

#123             mExpressionList->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry,

#124  entrycount, NULL);

#125         if(mStatement)

#126             mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount,

#127  NULL);

#128         break;

#129     }

#130     gonext(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);

#131  }

 

在语法分析里,把所有合法的语句都生成一个合适的类对象,然后通过遍历所有类对象进行类型检查,或者生成代码。所有其它语句都是这样进行的,比如语句if就是使用类LLScriptIf来保存和分析的。当检查所有脚本都是合法的语法后,就生成了语法树,后面通过遍历语法树来生成代码。

 

 

 

第二人生开发包提供,价格198/套(含邮费)。

包括内容如下:

1.    《第二人生的源码分析》PDF文档。

2.    第二人生客户端源程序。

3.    2G U盘一个,主要用来拷贝源程序以及相关开发工具。

 

提供三个月的技术服务,

提供快速编译指导,比如通过QQ远程编译操作。

提供完整的书参考。

 

联系方式:

QQ:             9073204

MSN:            [email protected]

EMAIL:          [email protected]

 

你可能感兴趣的:(脚本,assembly,null,Integer,tabs,FP)