在脚本里有很多语句组成的,那么对于语句又是怎么进行语法分析的呢?下面就来分析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]