您的位置:首页 > 其它

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

2008-07-27 19:52 337 查看
在脚本里有很多语句组成的,那么对于语句又是怎么进行语法分析的呢?下面就来分析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. U盘一个,主要用来拷贝源程序以及相关开发工具。



提供三个月的技术服务,

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

提供完整的书参考。



联系方式:

QQ: 9073204

MSN: caimouse1976@sina.com

EMAIL: ccaimouse@gmail.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: