void CheckPromise(Promise *pp) { char output[CF_BUFSIZE]; if (strcmp(pp->agentsubtype, "vars") == 0) { char *data_type = NULL; Constraint *cp; for (cp = pp->conlist; cp != NULL; cp = cp->next) { if (IsDataType(cp->lval)) { if (data_type != NULL) { snprintf(output, CF_BUFSIZE, "Variable contains existing data type contstraint %s, tried to redefine with %s", data_type, cp->lval); ReportError(output); ERRORCOUNT++; } data_type = cp->lval; } } } }
bool asCParser::IsDeclaration() { sToken t1, t2; GetToken(&t1); if( t1.type == ttConst ) { RewindTo(&t1); return true; } if( !IsDataType(t1.type) ) { RewindTo(&t1); return false; } GetToken(&t2); if( t2.type == ttIdentifier ) { RewindTo(&t1); return true; } // The data type can be followed by handle and array brackets while( t2.type == ttHandle || t2.type == ttOpenBracket ) { if( t2.type == ttOpenBracket ) { GetToken(&t2); if( t2.type != ttCloseBracket ) { RewindTo(&t1); return false; } } GetToken(&t2); } if( t2.type == ttIdentifier ) { RewindTo(&t1); return true; } RewindTo(&t1); return false; }
asCScriptNode *asCParser::ParseDataType() { asCScriptNode *node = new asCScriptNode(snDataType); sToken t1; GetToken(&t1); if( !IsDataType(t1.type) ) { Error(TXT_EXPECTED_DATA_TYPE, &t1); return node; } node->SetToken(&t1); node->UpdateSourcePos(t1.pos, t1.length); return node; }
bool Disasm::ParsePCL6() { uint8 byte; while (fStream->ReadUByte(byte)) { if (IsOperator(byte)) { if (!DecodeOperator(byte)) return false; } else if (IsDataType(byte)) { if (!PushData(byte)) return false; } else if (IsAttribute(byte)) { bool ok = DecodeAttribute(byte); ClearAttrs(); if (!ok) return false; } else if (IsEmbedData(byte)) { if (!DecodeEmbedData(byte)) return false; } else if (IsWhiteSpace(byte)) { // nothing to do } else if (IsEsc(byte)) { return true; } else { Error("Unknown byte in input stream"); return false; } } return true; }
/** * @brief Collects variable constraints controlling how the promise should be converged */ static ConvergeVariableOptions CollectConvergeVariableOptions(EvalContext *ctx, const Promise *pp, bool allow_redefine) { ConvergeVariableOptions opts = { 0 }; opts.should_converge = false; opts.drop_undefined = false; opts.ok_redefine = allow_redefine; opts.cp_save = NULL; if (EvalContextPromiseIsDone(ctx, pp)) { return opts; } if (!IsDefinedClass(ctx, pp->classes, PromiseGetNamespace(pp))) { return opts; } int num_values = 0; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (strcmp(cp->lval, "comment") == 0) { continue; } if (cp->rval.item == NULL) { continue; } if (strcmp(cp->lval, "ifvarclass") == 0) { Rval res; switch (cp->rval.type) { case RVAL_TYPE_SCALAR: if (!IsDefinedClass(ctx, cp->rval.item, PromiseGetNamespace(pp))) { return opts; } break; case RVAL_TYPE_FNCALL: { bool excluded = false; /* eval it: e.g. ifvarclass => not("a_class") */ res = FnCallEvaluate(ctx, cp->rval.item, NULL).rval; /* Don't continue unless function was evaluated properly */ if (res.type != RVAL_TYPE_SCALAR) { RvalDestroy(res); return opts; } excluded = !IsDefinedClass(ctx, res.item, PromiseGetNamespace(pp)); RvalDestroy(res); if (excluded) { return opts; } } break; default: Log(LOG_LEVEL_ERR, "Invalid ifvarclass type '%c': should be string or function", cp->rval.type); continue; } continue; } if (strcmp(cp->lval, "policy") == 0) { if (strcmp(cp->rval.item, "ifdefined") == 0) { opts.drop_undefined = true; opts.ok_redefine = false; } else if (strcmp(cp->rval.item, "constant") == 0) { opts.ok_redefine = false; } else { opts.ok_redefine |= true; } } else if (IsDataType(cp->lval)) { num_values++; opts.cp_save = cp; } } if (opts.cp_save == NULL) { Log(LOG_LEVEL_INFO, "Warning: Variable body for \"%s\" seems incomplete", pp->promiser); PromiseRef(LOG_LEVEL_INFO, pp); return opts; } if (num_values > 2) { Log(LOG_LEVEL_ERR, "Variable \"%s\" breaks its own promise with multiple values (code %d)", pp->promiser, num_values); PromiseRef(LOG_LEVEL_ERR, pp); return opts; } opts.should_converge = true; return opts; }
bool asCParser::IsFuncDecl(bool isMethod) { // Set start point so that we can rewind sToken t; GetToken(&t); RewindTo(&t); // A class constructor can start with identifier followed by parenthesis if( isMethod ) { sToken t1, t2; GetToken(&t1); GetToken(&t2); RewindTo(&t); if( t1.type == ttIdentifier && t2.type == ttOpenParanthesis ) return true; } // A function decl can start with a const sToken t1; GetToken(&t1); if( t1.type == ttConst ) GetToken(&t1); if( !IsDataType(t1.type) ) { RewindTo(&t); return false; } // Object handles can be interleaved with the array brackets sToken t2; GetToken(&t2); while( t2.type == ttHandle || t2.type == ttOpenBracket ) { if( t2.type == ttOpenBracket ) { GetToken(&t2); if( t2.type != ttCloseBracket ) { RewindTo(&t); return false; } } GetToken(&t2); } if( t2.type != ttIdentifier ) { RewindTo(&t); return false; } GetToken(&t2); if( t2.type == ttOpenParanthesis ) { // If the closing paranthesis is not followed by a // statement block then it is not a function. while( t2.type != ttCloseParanthesis && t2.type != ttEnd ) GetToken(&t2); if( t2.type == ttEnd ) return false; else { GetToken(&t1); RewindTo(&t); if( t1.type == ttStartStatementBlock ) return true; } RewindTo(&t); return false; } RewindTo(&t); return false; }
bool asCParser::IsVarDecl() { // Set start point so that we can rewind sToken t; GetToken(&t); RewindTo(&t); // A variable decl can start with a const sToken t1; GetToken(&t1); if( t1.type == ttConst ) GetToken(&t1); if( !IsDataType(t1.type) ) { RewindTo(&t); return false; } // Object handles can be interleaved with the array brackets sToken t2; GetToken(&t2); while( t2.type == ttHandle || t2.type == ttOpenBracket ) { if( t2.type == ttOpenBracket ) { GetToken(&t2); if( t2.type != ttCloseBracket ) { RewindTo(&t); return false; } } GetToken(&t2); } if( t2.type != ttIdentifier ) { RewindTo(&t); return false; } GetToken(&t2); if( t2.type == ttEndStatement || t2.type == ttAssignment || t2.type == ttListSeparator ) { RewindTo(&t); return true; } if( t2.type == ttOpenParanthesis ) { // If the closing paranthesis is followed by a statement // block or end-of-file, then treat it as a function. while( t2.type != ttCloseParanthesis && t2.type != ttEnd ) GetToken(&t2); if( t2.type == ttEnd ) return false; else { GetToken(&t1); RewindTo(&t); if( t1.type == ttStartStatementBlock || t1.type == ttEnd ) return false; } RewindTo(&t); return true; } RewindTo(&t); return false; }
asCScriptNode *asCParser::ParseScript() { asCScriptNode *node = new asCScriptNode(snScript); // Determine type of node sToken t1; for(;;) { while( !isSyntaxError ) { GetToken(&t1); RewindTo(&t1); if( t1.type == ttImport ) node->AddChildLast(ParseImport()); else if( t1.type == ttClass ) node->AddChildLast(ParseClass()); else if( t1.type == ttInterface ) node->AddChildLast(ParseInterface()); else if( t1.type == ttConst ) node->AddChildLast(ParseGlobalVar()); else if( IsDataType(t1.type) ) { if( IsVarDecl() ) node->AddChildLast(ParseGlobalVar()); else node->AddChildLast(ParseFunction()); } else if( t1.type == ttEndStatement ) { // Ignore a semicolon by itself GetToken(&t1); } else if( t1.type == ttEnd ) return node; else { asCString str; const char *t = asGetTokenDefinition(t1.type); if( t == 0 ) t = "<unknown token>"; str.Format(TXT_UNEXPECTED_TOKEN_s, t); Error(str.AddressOf(), &t1); } } if( isSyntaxError ) { // Search for either ';' or '{' or end GetToken(&t1); while( t1.type != ttEndStatement && t1.type != ttEnd && t1.type != ttStartStatementBlock ) GetToken(&t1); if( t1.type == ttStartStatementBlock ) { // Find the end of the block and skip nested blocks int level = 1; while( level > 0 ) { GetToken(&t1); if( t1.type == ttStartStatementBlock ) level++; if( t1.type == ttEndStatementBlock ) level--; if( t1.type == ttEnd ) break; } } isSyntaxError = false; } } return 0; }
/* 流式的处理特定CLinkerPipe接收到的信息,此函数对于理解本类非常重要, s为接收到的字节,或多或少 */ void CLinkerPipe::CompileMsg(const char* s, int32 size) { if(m_RecoType == LINKER_BAN)return; CLinkerPipe::RevContextInfo* Info = NULL; if( m_ContextStack.size() > 0 ){ Info = m_ContextStack.front(); //取出之前数据的处理信息 } else{ Info = new CLinkerPipe::RevContextInfo(&m_CurRevMsg); m_ContextStack.push_front(Info); } assert(Info != NULL); bool bCompleteOneData = FALSE; int i=0; while(i<size) { char ch = s[i++]; Info->InfoLen++; //在错误状态下将只关心是否有空管道出现 //在检测到空管道之前,根据要求,即使是出错的数据也将可能被保存起来,以便分析错误原因 if(m_bRevError) { if (Info->Buffer.size() < m_ErrorSaveLen) { Info->Buffer += ch; } if (ch == '@') { Info->DataLen ++; if (Info->DataLen ==ERROR_RESUME_LENGTH) { EndErrorState(Info); } }else{ Info->DataLen =0; } continue; } //正常状态 switch(Info->State){ case TYPE_PART: { Info->HeaderStr += ch; if( IsDataType(ch) && Info->DataType == -1){ Info->DataType = CHAR_TO_TYPE(ch); if(Info->DataType == TYPE_PIPELINE){ Info->Data = new ePipeline(); Info->ParentPipe->Push_Directly(Info->Data); } //不是PIPELINE但是第一个数据则报错,因为信息的第一个数据类型肯定是TYPE_PIPELINE else if(Info->ParentPipe == this ){ BeginErrorState(Info,ERROR_TYPE_PART); } else{ //其他类型则预先生成一个空数据 Info->Data = CreateEmptyData(Info->DataType); Info->ParentPipe->Push_Directly(Info->Data); } } //确定类型后,改变数据处理状态 else if(ch == '@' && Info->DataType != -1) { Info->State = (Info->DataType == TYPE_PIPELINE)?ID_PART : LENGTH_PART; Info->Buffer=""; Info->DataLen = NUMBER_LENGTH_LIMIT; } else{ BeginErrorState(Info,ERROR_TYPE_PART); } } break; case LENGTH_PART: { Info->HeaderStr += ch; // ch ->[0-9] 并且 单个数据长度不能超过10位整数 if(isdigit(ch) && Info->Buffer.size() < Info->DataLen) { Info->Buffer += ch; } else if(ch == '@' && Info->Buffer.size() >0) { Info->DataLen = atol(Info->Buffer.c_str()); Info->Buffer = ""; //初步检查长度的合理性 if(Info->DataType == TYPE_PIPELINE) { if (Info->ParentPipe == this) { } if(Info->DataLen == 0){ bCompleteOneData = TRUE; }else{ ePipeline NotifData; NotifData.PushInt(Info->DataLen); //总长度 NotifData.PushInt(0); //相对于Parent的完成进度,0则表示本Pipe刚开始 NotifData.Push_Directly(Info->Data->Clone()); m_Parent->NotifyLinkerState(this,LINKER_RECEIVE_STEP,NotifData); //对于管道,得到长度以后即压入堆栈,因为它的数据其实是其它数据的集合 Info->HeaderStr=""; ePipeline* Parent = (ePipeline*)Info->Data; assert(Parent); RevContextInfo* NewInfo = new RevContextInfo(Parent); m_ContextStack.push_front(NewInfo); Info = NewInfo; } break; }else if(Info->DataType == TYPE_NULL) { if(Info->DataLen != 0){ BeginErrorState(Info,ERROR_LENGTH_PART); }else{ bCompleteOneData = TRUE; } } else if(Info->DataLen ==0 ) { if(Info->DataType == TYPE_STRING){ //允许为0 bCompleteOneData = TRUE; } else{// 其他数据不能为0 error BeginErrorState(Info,ERROR_LENGTH_PART); } }else if ((Info->DataType==TYPE_INT || Info->DataType==TYPE_FLOAT) && Info->DataLen>20) { BeginErrorState(Info,ERROR_LENGTH_PART); } else{ Info->State = DATA_PART; //一切OK,准备开始处理数据本身 } } else{ BeginErrorState(Info,ERROR_LENGTH_PART); } } break; case DATA_PART: { Info->Buffer += ch; if( Info->Buffer.size() == Info->DataLen ){ Info->HeaderStr+=Info->Buffer; int32 n = Info->Data->FromString(Info->HeaderStr,0); assert(n!=0); bCompleteOneData = TRUE; } } break; case ID_PART: { // Info->HeaderStr += ch; // ch ->[0-9] 并且数据ID不能超过20位整数 if(isdigit(ch) && Info->Buffer.size() < Info->DataLen) { Info->Buffer += ch; } else if(ch == '@' && Info->Buffer.size() >0) { int64 ID = atoint64(Info->Buffer.c_str()); assert(Info->DataType == TYPE_PIPELINE); ePipeline* Data = (ePipeline*)Info->Data; Data->SetID(ID); Info->State = NAMELEN_PART; Info->Buffer = ""; Info->DataLen = DATA_LENGTH_LIMIT; } else{ BeginErrorState(Info,ERROR_ID_PART); } } break; case NAMELEN_PART: { // Info->HeaderStr += ch; // ch ->[0-9] 并且 不能超过10位整数 if(isdigit(ch) && Info->Buffer.size() < Info->DataLen) { Info->Buffer += ch; } else if(ch == '@' && Info->Buffer.size() >0) { uint32 len = atol(Info->Buffer.c_str()); Info->DataLen = len; Info->Buffer = ""; assert(Info->Buffer.size()==0); Info->State = NAME_PART; } else{ BeginErrorState(Info,ERROR_NAMELEN_PART); } } break; case NAME_PART: { // Info->HeaderStr += ch; // ch ->[0-9] 并且 不能超过约定位数 if(Info->Buffer.size() < Info->DataLen) { Info->Buffer += ch; } else if(ch == '@'){ eSTRING s; s.FromString(Info->Buffer,0); tstring Name = s; assert(Info->DataType == TYPE_PIPELINE); ePipeline* Data = (ePipeline*)Info->Data; Data->SetLabel(Name.c_str()); Info->Buffer = ""; Info->State = LENGTH_PART; Info->DataLen = DATA_LENGTH_LIMIT; } else{ BeginErrorState(Info,ERROR_NAME_PART); } } break; default: assert(0); break; } if(bCompleteOneData){ bCompleteOneData = FALSE; //处理得到的实际数据 while(m_ContextStack.size()){ //Info->ParentPipe->Push_Directly(Info->Data); int32 Len = Info->InfoLen; Energy* Data = Info->Data; if (m_ContextStack.size()>1) { RevContextInfo* PreInfo = m_ContextStack[1]; PreInfo->InfoLen += Len; PreInfo->DataLen -= Len; if (PreInfo->DataLen == 0) //已经完成一个嵌套Pipe,重复上述步骤 { ePipeline NotifData; NotifData.PushInt(Len); //总长度 NotifData.PushInt(PreInfo->InfoLen); //Parent Pipe已经完成的 NotifData.Push_Directly(Data->Clone()); m_Parent->NotifyLinkerState(this,LINKER_RECEIVE_STEP,NotifData); delete Info; m_ContextStack.pop_front(); Info = m_ContextStack.front(); assert(PreInfo == Info); }else if (PreInfo->DataLen > 0) //继续接收下一个数据 { Info->Reset(); break; }else{ //错误 BeginErrorState(Info,ERROR_OTHER_PARNT); Info->Reset(); } }else{ //已经完成一个完整信息的组装 assert(m_ContextStack.size()==1); assert(m_CurRevMsg.Size()==1); eElectron E; m_CurRevMsg.Pop(&E); RevOneMsg(E); assert(Info->ParentPipe == &m_CurRevMsg); Info->Reset(); break; } }//while } }//while }
HCC_TOKEN* icode_generator::getToken(void) { check_bounds(0); HCC_TOKEN* token_ptr = new HCC_TOKEN; //do loop to extract the line markers HCC_TOKEN_TYPE token_type = HCC_TOKEN_ERROR; do{ memcpy((void*)&token_type, cursor, sizeof(wchar_t)); cursor += sizeof(wchar_t); if(token_type==HCC_LINE_MARKER){ memcpy(&line_number, cursor, sizeof(int)); cursor += sizeof(int); } }while(token_type==HCC_LINE_MARKER || IsDataType(token_type) || IsStorageSpec(token_type)); // token_ptr->tokenType = token_type; switch(token_type) { case HCC_NUMBER: case HCC_STRING_LITERAL: case HCC_CHARACTER: case HCC_CONTROL_CHAR: case HCC_IDENTIFIER: case HCC_SIZEOF: case HCC_TRUE: case HCC_FALSE: case HCC_NULL: { symbol_ptr = get_symbol(); _tcsncpy(token_ptr->token, symbol_ptr->String().c_str(), symbol_ptr->String().length()); token_ptr->token[symbol_ptr->String().length()] = _T('\0'); token_ptr->dataType = symbol_ptr->getDataType(); //must set the data type for the internal representation of data //and for correct evaluation by the H++ interpreter... switch(token_type) { case HCC_NUMBER: { if(symbol_ptr->getDataType()==HCC_INTEGER) token_ptr->value.Integer = symbol_ptr->getDeclDefinition().constant.value.Integer; // (int)symbol_ptr->getValue(); else if(symbol_ptr->getDataType()==HCC_FLOATING_POINT) token_ptr->value.Double = symbol_ptr->getDeclDefinition().constant.value.Double; //symbol_ptr->getValue(); } break; case HCC_CHARACTER: case HCC_CONTROL_CHAR: token_ptr->value.Character = symbol_ptr->getDeclDefinition().constant.value.Character; break; case HCC_BOOLEAN: token_ptr->value.Boolean = symbol_ptr->getDeclDefinition().constant.value.Boolean; break; default: //for all other types... token_ptr->value.Integer = symbol_ptr->getDeclDefinition().constant.value.Integer; break; } } break; default: { symbol_ptr = NULL; if(token_type>HCC_LINE_MARKER && token_type<=HCC_WITH) _tcscpy(token_ptr->token, symbolStrings[token_type]); else if(token_type < HCC_TOKEN_ERROR || token_type > HCC_WITH) token_ptr->tokenType = HCC_EOF; } break; }; return token_ptr; }