在脚本里有很多语句组成的,那么对于语句又是怎么进行语法分析的呢?下面就来分析
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.
提供三个月的技术服务,
提供快速编译指导,比如通过
QQ
远程编译操作。
提供完整的书参考。
联系方式:
QQ:
9073204
MSN:
caimouse1976@sina.com
EMAIL:
ccaimouse@gmail.com