void PHPSourceFile::ReadImplements(wxArrayString& impls) { wxString type; phpLexerToken token; while(NextToken(token)) { switch(token.type) { case kPHP_T_IDENTIFIER: case kPHP_T_NS_SEPARATOR: type << token.text; break; case ',': // More to come if(!type.IsEmpty()) { wxString fullyQualifiedType = MakeIdentifierAbsolute(type); if(impls.Index(fullyQualifiedType) == wxNOT_FOUND) { impls.Add(fullyQualifiedType); } type.clear(); } break; default: // unexpected token if(!type.IsEmpty()) { wxString fullyQualifiedType = MakeIdentifierAbsolute(type); if(impls.Index(fullyQualifiedType) == wxNOT_FOUND) { impls.Add(fullyQualifiedType); } type.clear(); } UngetToken(token); return; } } }
bool PHPSourceFile::ReadCommaSeparatedIdentifiers(int delim, wxArrayString& list) { phpLexerToken token; wxString temp; while(NextToken(token)) { if(token.IsAnyComment()) continue; if(token.type == delim) { if(!temp.IsEmpty() && list.Index(temp) == wxNOT_FOUND) { list.Add(MakeIdentifierAbsolute(temp)); } UngetToken(token); return true; } switch(token.type) { case ',': if(list.Index(temp) == wxNOT_FOUND) { list.Add(MakeIdentifierAbsolute(temp)); } temp.clear(); break; default: temp << token.text; break; } } return false; }
wxString PHPSourceFile::ReadType() { bool cont = true; wxString type; phpLexerToken token; while(cont && NextToken(token)) { switch(token.type) { case kPHP_T_IDENTIFIER: type << token.text; break; case kPHP_T_NS_SEPARATOR: type << token.text; break; default: // restore the token so next call to NextToken // will pick it up again UngetToken(token); cont = false; break; } } type = MakeIdentifierAbsolute(type); return type; }
/*foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement*/ void PHPSourceFile::OnForEach() { // read until the "as" keyword phpLexerToken token; if(!ReadUntilFound(kPHP_T_AS, token)) return; // Found the "as" key word and consumed it if(!NextToken(token)) return; phpLexerToken peekToken; if(!NextToken(peekToken)) return; // Ensure we got a variable if(token.type != kPHP_T_VARIABLE) return; // Check to see if we are using the syntax of: // foreach (array_expression as $key => $value) if(peekToken.type == kPHP_T_DOUBLE_ARROW) { if(!NextToken(token) || token.type != kPHP_T_VARIABLE) { return; } } else { UngetToken(peekToken); } // Create a new variable PHPEntityBase::Ptr_t var(new PHPEntityVariable()); var->SetFullName(token.text); var->SetFilename(m_filename.GetFullPath()); var->SetLine(token.lineNumber); if(!CurrentScope()->FindChild(var->GetFullName(), true)) { CurrentScope()->AddChild(var); } }
bool PHPSourceFile::ReadVariableInitialization(PHPEntityBase::Ptr_t var) { phpLexerToken token; if(!NextToken(token)) { return false; } if(token.type != '=') { // restore the token UngetToken(token); return false; } wxString expr; if(!ReadExpression(expr)) { return false; // EOF } // Optimize 'new ClassName(..)' expression if(expr.StartsWith("new")) { expr = expr.Mid(3); expr.Trim().Trim(false); expr = expr.BeforeFirst('('); expr.Trim().Trim(false); var->Cast<PHPEntityVariable>()->SetTypeHint(MakeIdentifierAbsolute(expr)); } else { // keep the expression var->Cast<PHPEntityVariable>()->SetExpressionHint(expr); } return true; }
Stmt *ParseIfStmt(int (*ParseDetails)(Stmt **stmt)) { Stmt *stmt; IfData *id; if((stmt = NewStmt()) != NULL) { if((id = (IfData *)calloc(1, sizeof(IfData))) != NULL) { stmt->procs = &if_stmt_procs; stmt->data = (void *)id; if((id->expr = ExprParse()) != NULL) { id->block = ParseBlock("if", ParseDetails); if(GetToken() == TK_ELSE) { id->elseblock = ParseBlock("else", ParseDetails); } else { UngetToken(); id->elseblock = NULL; } return stmt; } } else LogMemError("if"); } DeleteStmt(stmt); return NULL; }
static FORMAT_PTR Enum_Format(Format_Parse_Ptr parser, BOOLEAN *error) { TokenPtr Token; FORMAT_PTR Form, subform; LIST_PTR format_list; int num_formats, i, maxVal; num_formats = 0; Token = NextToken(parser); if (Token->Type == COLON_TOK) { Token = NextToken(parser); if (Token->Type != INT_TOK) { *error = TRUE; ParserError(Token, parser, "an integer"); return NULL; } else { maxVal = Token->value.num; } } else { format_list = x_ipc_listCreate(); do { if (num_formats > 0) Token = NextToken(parser); if (Token->Type != STR_TOK) { *error = TRUE; ParserError(Token, parser, "a string"); return NULL; } else { Form = new_n_formatter(Token->value.str); /* More efficient for Lisp if all enum format names are upper case */ LOCK_M_MUTEX; if (IS_LISP_MODULE()) { upcase(Form->formatter.name); } UNLOCK_M_MUTEX; x_ipc_listInsertItem((char *)Form, format_list); num_formats++; } Token = NextToken(parser); } while (Token->Type == COMMA_TOK); UngetToken(parser, Token); maxVal = num_formats - 1; } Form = new_a_formatter(EnumFMT, num_formats+2); Form->formatter.a[1].i = maxVal; if (num_formats > 0) { /* Index from high to low since "format_list" has formatters in reverse order */ subform = (FORMAT_PTR)x_ipc_listFirst(format_list); for(i=num_formats;i>0;i--) { Form->formatter.a[i+1].f = subform; subform = (FORMAT_PTR)x_ipc_listNext(format_list); } x_ipc_listFree(&format_list); } return Form; }
bool FBaseParser::PeekIdentifier( const TCHAR* Match ) { FToken Token; if (!GetToken(Token, true)) { return false; } UngetToken(Token); return Token.TokenType==TOKEN_Identifier && FCString::Stricmp(Token.Identifier,Match)==0; }
// // Peek ahead and see if an identifier follows in the stream. // bool FBaseParser::PeekIdentifier( FName Match ) { FToken Token; if (!GetToken(Token, true)) { return false; } UngetToken(Token); return Token.TokenType==TOKEN_Identifier && Token.TokenName==Match; }
//------------------------------------------------------------------------------ bool FBasicTokenParser::PeekSymbol(TCHAR const* Match) { FBasicToken Token; if (!GetToken(Token, true)) { return false; } UngetToken(Token); return Token.TokenType == FBasicToken::TOKEN_Symbol && FCString::Stricmp(Token.Identifier, Match) == 0; }
bool PHPSourceFile::ReadExpression(wxString& expression) { expression.clear(); phpLexerToken token; int depth(0); while(NextToken(token)) { if(token.type == ';') { return true; } else if(token.type == '{') { UngetToken(token); return true; } switch(token.type) { case kPHP_T_REQUIRE: case kPHP_T_REQUIRE_ONCE: expression.clear(); return false; case kPHP_T_STRING_CAST: case kPHP_T_CONSTANT_ENCAPSED_STRING: case kPHP_T_C_COMMENT: case kPHP_T_CXX_COMMENT: // skip comments and strings break; case '(': depth++; expression << "("; break; case ')': depth--; if(depth == 0) { expression << ")"; } break; case kPHP_T_NEW: if(depth == 0) { expression << token.text << " "; } break; default: if(depth == 0) { expression << token.text; } break; } } // reached EOF return false; }
wxString PHPSourceFile::ReadExtends() { wxString type; phpLexerToken token; while(NextToken(token)) { if(token.type == kPHP_T_IDENTIFIER || token.type == kPHP_T_NS_SEPARATOR) { type << token.text; } else { UngetToken(token); break; } } type = MakeIdentifierAbsolute(type); return type; }
/************************************************************************* * * ExprParse - Parses and contructs an expression parse tree. * * Returns a pointer to top of expr tree or NULL if there's no * expr or an error occurred. * *************************************************************************/ Expr *ExprParse(void) { Expr *expr; int errcnt = error_count; token = GetToken(); vector_closing = 0; expr = Term1(); UngetToken(); if(error_count > errcnt) { ExprDelete(expr); return NULL; } return expr; }
// // Get an identifier token, return 1 if gotten, 0 if not. // bool FBaseParser::GetIdentifier( FToken& Token, bool bNoConsts ) { if (!GetToken(Token, bNoConsts)) { return false; } if (Token.TokenType == TOKEN_Identifier) { return true; } UngetToken(Token); return false; }
// // Get a symbol token, return 1 if gotten, 0 if not. // bool FBaseParser::GetSymbol( FToken& Token ) { if (!GetToken(Token)) { return false; } if( Token.TokenType == TOKEN_Symbol ) { return true; } UngetToken(Token); return false; }
// // Get a specific identifier and return 1 if gotten, 0 if not. // This is used primarily for checking for required symbols during compilation. // bool FBaseParser::MatchIdentifier( FName Match ) { FToken Token; if (!GetToken(Token)) { return false; } if ((Token.TokenType == TOKEN_Identifier) && (Token.TokenName == Match)) { return true; } UngetToken(Token); return false; }
bool FBaseParser::MatchIdentifier( const TCHAR* Match ) { FToken Token; if (GetToken(Token)) { if( Token.TokenType==TOKEN_Identifier && FCString::Stricmp(Token.Identifier,Match)==0 ) { return true; } else { UngetToken(Token); } } return false; }
bool FBaseParser::MatchSymbol( const TCHAR* Match ) { FToken Token; if (GetToken(Token, /*bNoConsts=*/ true)) { if (Token.TokenType==TOKEN_Symbol && !FCString::Stricmp(Token.Identifier, Match)) { return true; } else { UngetToken(Token); } } return false; }
bool FBaseParser::MatchSymbol( const TCHAR* Match, ESymbolParseOption bParseTemplateClosingBracket/*=ESymbolParseOption::Normal*/ ) { FToken Token; if (GetToken(Token, /*bNoConsts=*/ true, bParseTemplateClosingBracket)) { if (Token.TokenType==TOKEN_Symbol && !FCString::Stricmp(Token.Identifier, Match)) { return true; } else { UngetToken(Token); } } return false; }
Stmt *ParseLoadImageMapStmt(void) { LoadImageMapStmtData *sd; int token; Stmt *stmt = NewStmt(); if(stmt == NULL) { LogMemError("load_image_map"); return NULL; } sd = (LoadImageMapStmtData *)calloc(1, sizeof(LoadImageMapStmtData)); if(sd == NULL) { DeleteStmt(stmt); LogMemError("load_image_map"); return NULL; } stmt->procs = &loadimagemap_stmt_procs; stmt->data = (void *)sd; token = GetNewIdentifier(); if(token == TK_UNKNOWN_ID) { sd->name = (char *)malloc(strlen(token_buffer) + 1); if(sd->name == NULL) { DeleteStmt(stmt); LogMemError("load_color_map"); return NULL; } strcpy(sd->name, token_buffer); } else { LogError("load_image_map: Expecting an unused identifier name."); LogError(" Found '%s'.", token_buffer); PrintFileAndLineNumber(); UngetToken(); DeleteStmt(stmt); return NULL; } return stmt; }
//------------------------------------------------------------------------------ bool FBasicTokenParser::GetConstInt(int32& Result, TCHAR const* ErrorContext) { FBasicToken Token; if (GetToken(Token)) { if (Token.GetConstInt(Result)) { return true; } else { UngetToken(Token); } } if (ErrorContext != NULL) { FText ErrorDesc = FText::Format(LOCTEXT("ContextualNoInt", "{0}: Missing expected integer constant"), FText::FromString(ErrorContext)); SetError(FErrorState::ParseError, ErrorDesc); } return false; }
bool FBaseParser::GetConstInt(int32& Result, const TCHAR* Tag) { FToken Token; if (GetToken(Token)) { if (Token.GetConstInt(Result)) { return true; } else { UngetToken(Token); } } if (Tag != NULL) { FError::Throwf(TEXT("%s: Missing constant integer"), Tag ); } return false; }
// // Check an identifier (atom) to see if it is a macro that should be expanded. // If it is, and defined, push a tInput that will produce the appropriate expansion // and return 1. // If it is, but undefined, and expandUndef is requested, push a tInput that will // expand to 0 and return -1. // Otherwise, return 0 to indicate no expansion, which is not necessarily an error. // int TPpContext::MacroExpand(int atom, TPpToken* ppToken, bool expandUndef, bool newLineOkay) { ppToken->space = false; switch (atom) { case PpAtomLineMacro: ppToken->ival = parseContext.getCurrentLoc().line; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; case PpAtomFileMacro: { if (parseContext.getCurrentLoc().name) parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); ppToken->ival = parseContext.getCurrentLoc().string; sprintf(ppToken->name, "%s", ppToken->loc.getStringNameOrNum().c_str()); UngetToken(PpAtomConstInt, ppToken); return 1; } case PpAtomVersionMacro: ppToken->ival = parseContext.version; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(PpAtomConstInt, ppToken); return 1; default: break; } Symbol *sym = LookUpSymbol(atom); int token; int depth = 0; // no recursive expansions if (sym && sym->mac.busy) return 0; // not expanding undefined macros if ((! sym || sym->mac.undef) && ! expandUndef) return 0; // 0 is the value of an undefined macro if ((! sym || sym->mac.undef) && expandUndef) { pushInput(new tZeroInput(this)); return -1; } tMacroInput *in = new tMacroInput(this); TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->mac = &sym->mac; if (sym->mac.args) { token = scanToken(ppToken); if (newLineOkay) { while (token == '\n') token = scanToken(ppToken); } if (token != '(') { parseContext.ppError(loc, "expected '(' following", "macro expansion", GetAtomString(atom)); UngetToken(token, ppToken); ppToken->atom = atom; delete in; return 0; } in->args.resize(in->mac->argc); for (int i = 0; i < in->mac->argc; i++) in->args[i] = new TokenStream; int arg = 0; bool tokenRecorded = false; do { depth = 0; while (1) { token = scanToken(ppToken); if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); delete in; return 0; } if (token == '\n') { if (! newLineOkay) { parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", GetAtomString(atom)); delete in; return 0; } continue; } if (token == '#') { parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); delete in; return 0; } if (in->mac->argc == 0 && token != ')') break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[arg], token, ppToken); tokenRecorded = true; } if (token == ')') { if (in->mac->argc == 1 && tokenRecorded == 0) break; arg++; break; } arg++; } while (arg < in->mac->argc); if (arg < in->mac->argc) parseContext.ppError(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); else if (token != ')') { depth=0; while (token != EndOfInput && (depth > 0 || token != ')')) { if (token == ')') depth--; token = scanToken(ppToken); if (token == '(') depth++; } if (token == EndOfInput) { parseContext.ppError(loc, "End of input in macro", "macro expansion", GetAtomString(atom)); delete in; return 0; } parseContext.ppError(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); } for (int i = 0; i < in->mac->argc; i++) in->args[i] = PrescanMacroArg(in->args[i], ppToken, newLineOkay); } pushInput(in); sym->mac.busy = 1; RewindTokenStream(sym->mac.body); return 1; }
int MacroExpand(int atom, yystypepp * yylvalpp) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i,j, token, depth=0; const char *message; if (atom == __LINE__Atom) { yylvalpp->sc_int = GetLineNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->sc_int = GetStringNumber(); snprintf(yylvalpp->symbol_name, MAX_SYMBOL_NAME_LEN+1, "%d", yylvalpp->sc_int); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { strcpy(yylvalpp->symbol_name,ESSL_VERSION_STRING); yylvalpp->sc_int = atoi(yylvalpp->symbol_name); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (!sym || sym->details.mac.undef) return 0; if (sym->details.mac.busy) return 0; // no recursive expansions in = malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.scan = (void *)macro_scan; in->base.line = cpp->currentInput->line; in->base.name = cpp->currentInput->name; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->sc_ident = atom; return 0; } in->args = malloc(in->mac->argc * sizeof(TokenStream *)); for (i=0; i<in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i=0;j=0; do{ depth = 0; while(1) { token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } if((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if((in->mac->argc==1) &&j==0) break; i++; break; } i++; }while(i < in->mac->argc); if (i < in->mac->argc) { StoreStr("Too few args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { StoreStr("EOF in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); return 1; } StoreStr("Too many args in Macro "); StoreStr(GetStringOfAtom(atable,atom)); message=GetStrfromTStr(); CPPShInfoLogMsg(message); ResetTString(); } for (i=0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i=0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = cpp->currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); cpp->currentInput = &in->base; return 1; } // MacroExpand
/* "within_struct_flag" is TRUE if the enclosing format is "{...}" */ static FORMAT_PTR Parse(Format_Parse_Ptr parser, int32 within_struct_flag, BOOLEAN *error) { TokenPtr Token; FORMAT_PTR ReturnForm=NULL; Token = NextToken(parser); switch(Token->Type) { case LBRACE_TOK: Token = NextToken(parser); if (Token->Type == STR_TOK && !strcmp(Token->value.str, "enum")) { ReturnForm = Enum_Format(parser, error); } else { UngetToken(parser, Token); ReturnForm = Struct_Format(parser, error); } Token = NextToken(parser); if (Token->Type != RBRACE_TOK) { ParserError(Token, parser, "'}'"); *error = TRUE; return NULL; } break; case LBRACK_TOK: ReturnForm = Fixed_Array_Format(parser, error); break; case LT_TOK: if (!within_struct_flag) { ParserError(Token, parser, "var array format '<..>' not embedded within a structure '{..}'"); *error = TRUE; return NULL; } else { ReturnForm = Var_Array_Format(parser, error); } break; case STAR_TOK: if (parser->TokenList->Type == BANG_TOK) { Token = NextToken(parser); /* eat BANG_TOK */ if (!within_struct_flag) { ParserError(Token, parser, "self pointer '*!' embedded within a structure '{..}'"); *error = TRUE; return NULL; } else { ReturnForm = SelfPtr_Format(); } } else ReturnForm = Ptr_Format(parser, error); break; case INT_TOK: ReturnForm = Length_Format(Token); break; case STR_TOK: ReturnForm = Named_Format(parser, Token); if (ReturnForm->type == BadFormatFMT) { *error = TRUE; return NULL; } break; case PRIMITIVE_TOK: ReturnForm = Primitive_Format(parser, Token); if (ReturnForm->type == BadFormatFMT) { *error = TRUE; return NULL; } break; case EOS_TOK: ParserError(Token, parser, "additional tokens; premature end of string encountered"); *error = TRUE; return NULL; break; default: ParserError(Token, parser, "a different token type"); *error = TRUE; return NULL; } cacheFormatterAttributes(ReturnForm); return ReturnForm; }
void PHPSourceFile::ParseFunctionBody() { m_lookBackTokens.clear(); // when we reach the current depth-1 -> leave int exitDepth = m_depth - 1; phpLexerToken token; PHPEntityBase::Ptr_t var(NULL); while(NextToken(token)) { switch(token.type) { case '{': m_lookBackTokens.clear(); break; case '}': m_lookBackTokens.clear(); if(m_depth == exitDepth) { return; } break; case ';': m_lookBackTokens.clear(); break; case kPHP_T_CATCH: OnCatch(); break; case kPHP_T_VARIABLE: { var.Reset(new PHPEntityVariable()); var->SetFullName(token.text); var->SetFilename(m_filename.GetFullPath()); var->SetLine(token.lineNumber); CurrentScope()->AddChild(var); // Peek at the next token if(!NextToken(token)) return; // EOF if(token.type != '=') { m_lookBackTokens.clear(); var.Reset(NULL); UngetToken(token); } else { wxString expr; if(!ReadExpression(expr)) return; // EOF // Optimize 'new ClassName(..)' expression if(expr.StartsWith("new")) { expr = expr.Mid(3); expr.Trim().Trim(false); expr = expr.BeforeFirst('('); expr.Trim().Trim(false); var->Cast<PHPEntityVariable>()->SetTypeHint(MakeIdentifierAbsolute(expr)); } else { // keep the expression var->Cast<PHPEntityVariable>()->SetExpressionHint(expr); } } } break; default: break; } } }
/* MacroExpand ** Check an identifier (atom) to see if it is a macro that should be expanded. ** If it is, push an InputSrc that will produce the appropriate expansion ** and return 1. ** If it is, but undefined, it should expand to 0, push an InputSrc that will ** expand to 0 and return -1. ** Otherwise, return 0. */ int TPpContext::MacroExpand(int atom, TPpToken* yylvalpp, int expandUndef) { Symbol *sym = LookUpSymbol(macros, atom); MacroInputSrc *in; int i, j, token; int depth = 0; if (atom == __LINE__Atom) { yylvalpp->ival = parseContext.currentLoc.line; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __FILE__Atom) { yylvalpp->ival = parseContext.currentLoc.string; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } if (atom == __VERSION__Atom) { yylvalpp->ival = parseContext.version; sprintf(yylvalpp->name, "%d", yylvalpp->ival); UngetToken(CPP_INTCONSTANT, yylvalpp); return 1; } // no recursive expansions if (sym && sym->details.mac.busy) return 0; // not expanding of undefined symbols if ((! sym || sym->details.mac.undef) && ! expandUndef) return 0; in = (MacroInputSrc*)malloc(sizeof(*in)); memset(in, 0, sizeof(*in)); in->base.line = currentInput->line; in->base.name = currentInput->name; if ((! sym || sym->details.mac.undef) && expandUndef) { // push input in->base.scan = zero_scan; in->base.prev = currentInput; currentInput = &in->base; return -1; } in->base.scan = macro_scan; in->mac = &sym->details.mac; if (sym->details.mac.args) { token = currentInput->scan(this, currentInput, yylvalpp); if (token != '(') { UngetToken(token, yylvalpp); yylvalpp->atom = atom; return 0; } in->args = (TokenStream**)malloc(in->mac->argc * sizeof(TokenStream *)); for (i = 0; i < in->mac->argc; i++) in->args[i] = NewTokenStream("macro arg", 0); i = 0; j = 0; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, yylvalpp); if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } if ((in->mac->argc==0) && (token!=')')) break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[i], token, yylvalpp); j=1; } if (token == ')') { if ((in->mac->argc==1) &&j==0) break; i++; break; } i++; } while (i < in->mac->argc); if (i < in->mac->argc) parseContext.error(yylvalpp->loc, "Too few args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = currentInput->scan(this, currentInput, yylvalpp); if (token == '(') depth++; } if (token <= 0) { parseContext.error(yylvalpp->loc, "EOF in macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); return 1; } parseContext.error(yylvalpp->loc, "Too many args in Macro", "preprocessor", GetStringOfAtom(&atomTable, atom)); } for (i = 0; i<in->mac->argc; i++) { in->args[i] = PrescanMacroArg(in->args[i], yylvalpp); } } #if 0 printf(" <%s:%d>found macro %s\n", GetAtomString(atable, loc.file), loc.line, GetAtomString(atable, atom)); for (i = 0; i<in->mac->argc; i++) { printf("\targ %s = '", GetAtomString(atable, in->mac->args[i])); DumpTokenStream(stdout, in->args[i]); printf("'\n"); } #endif /*retain the input source*/ in->base.prev = currentInput; sym->details.mac.busy = 1; RewindTokenStream(sym->details.mac.body); currentInput = &in->base; return 1; } // MacroExpand
void PHPSourceFile::Parse(int exitDepth) { int retDepth = exitDepth; phpLexerToken token; while(NextToken(token)) { switch(token.type) { case '=': m_lookBackTokens.clear(); break; case '{': m_lookBackTokens.clear(); break; case '}': m_lookBackTokens.clear(); if(m_depth == retDepth) { return; } break; case ';': m_lookBackTokens.clear(); break; case kPHP_T_VARIABLE: if(!CurrentScope()->Is(kEntityTypeClass)) { // A global variable OnVariable(token); } break; case kPHP_T_CATCH: // found 'catch (...)' OnCatch(); break; case kPHP_T_PUBLIC: case kPHP_T_PRIVATE: case kPHP_T_PROTECTED: { int visibility = token.type; PHPEntityClass* cls = CurrentScope()->Cast<PHPEntityClass>(); if(cls) { /// keep the current token m_lookBackTokens.push_back(token); // Now we have a small problem here: // public can be a start for a member or a function // we let the lexer run forward until it finds kPHP_T_VARIABLE (for variable) // or kPHP_T_IDENTIFIER int what = ReadUntilFoundOneOf(kPHP_T_VARIABLE, kPHP_T_FUNCTION, token); if(what == kPHP_T_VARIABLE) { // A variable PHPEntityBase::Ptr_t member(new PHPEntityVariable()); member->SetFilename(m_filename.GetFullPath()); member->Cast<PHPEntityVariable>()->SetVisibility(visibility); member->Cast<PHPEntityVariable>()->SetFullName(token.text); size_t flags = LookBackForVariablesFlags(); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Member); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Const, flags & kVar_Const); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Static, flags & kVar_Static); member->Cast<PHPEntityVariable>()->SetLine(token.lineNumber); CurrentScope()->AddChild(member); // Handle member assignment // public $memberVar = new Something(); // for such cases, assign $memberVar type of Something() phpLexerToken t; if(!NextToken(t)) { // EOF return; } if(t.type == '=') { // assignment wxString expr; if(!ReadExpression(expr)) { return; } // Optimize 'new ClassName(..)' expression if(expr.StartsWith("new")) { expr = expr.Mid(3); expr.Trim().Trim(false); expr = expr.BeforeFirst('('); expr.Trim().Trim(false); member->Cast<PHPEntityVariable>()->SetTypeHint(MakeIdentifierAbsolute(expr)); } else { // keep the expression member->Cast<PHPEntityVariable>()->SetExpressionHint(expr); } } else { // restore the token UngetToken(t); if(!ConsumeUntil(';')) return; } } else if(what == kPHP_T_FUNCTION) { // A function... OnFunction(); m_lookBackTokens.clear(); } } break; } case kPHP_T_DEFINE: // Define statement OnDefine(token); break; case kPHP_T_CONST: OnConstant(token); break; case kPHP_T_REQUIRE: case kPHP_T_REQUIRE_ONCE: case kPHP_T_INCLUDE: case kPHP_T_INCLUDE_ONCE: // Handle include files m_lookBackTokens.clear(); break; case kPHP_T_FOREACH: // found "foreach" statement OnForEach(); m_lookBackTokens.clear(); break; case kPHP_T_USE: // Found outer 'use' statement - construct the alias table if(Class()) { // inside a class, this means that this is a 'use <trait>;' OnUseTrait(); } else { // alias table OnUse(); } m_lookBackTokens.clear(); break; case kPHP_T_CLASS: case kPHP_T_INTERFACE: case kPHP_T_TRAIT: // Found class OnClass(token); m_lookBackTokens.clear(); break; case kPHP_T_NAMESPACE: // Found a namespace OnNamespace(); m_lookBackTokens.clear(); break; case kPHP_T_FUNCTION: // Found function OnFunction(); m_lookBackTokens.clear(); break; default: // Keep the token break; } } PhaseTwo(); }
/* ** Check an identifier (atom) to see if it is a macro that should be expanded. ** If it is, push an InputSrc that will produce the appropriate expansion ** and return 1. ** If it is, but undefined, it should expand to 0, push an InputSrc that will ** expand to 0 and return -1. ** Otherwise, return 0. */ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) { Symbol *sym = LookUpSymbol(atom); MacroInputSrc *in; int token; int depth = 0; if (atom == __LINE__Atom) { ppToken->ival = parseContext.getCurrentLoc().line; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } if (atom == __FILE__Atom) { ppToken->ival = parseContext.getCurrentLoc().string; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } if (atom == __VERSION__Atom) { ppToken->ival = parseContext.version; sprintf(ppToken->name, "%d", ppToken->ival); UngetToken(CPP_INTCONSTANT, ppToken); return 1; } // no recursive expansions if (sym && sym->mac.busy) return 0; // not expanding of undefined symbols if ((! sym || sym->mac.undef) && ! expandUndef) return 0; in = new MacroInputSrc; if ((! sym || sym->mac.undef) && expandUndef) { // push input in->scan = zero_scan; in->prev = currentInput; currentInput = in; return -1; } TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->scan = macro_scan; in->mac = &sym->mac; if (sym->mac.args) { token = currentInput->scan(this, currentInput, ppToken); if (token != '(') { UngetToken(token, ppToken); ppToken->atom = atom; return 0; } in->args.resize(in->mac->argc); for (int i = 0; i < in->mac->argc; i++) in->args[i] = new TokenStream; int arg = 0; bool tokenRecorded = false; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, ppToken); if (token <= 0) { parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } if (token == '\n') { // TODO: Preprocessor functionality: Correctly handle new line and escaped new line, for expansions that are both in and not in another preprocessor directive //if (in a pp line) { // parseContext.error(loc, "missing ')':", "macro expansion", GetAtomString(atom)); // return 1; //} continue; } if (token == '#') { parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); return 1; } if (in->mac->argc == 0 && token != ')') break; if (depth == 0 && (token == ',' || token == ')')) break; if (token == '(') depth++; if (token == ')') depth--; RecordToken(in->args[arg], token, ppToken); tokenRecorded = true; } if (token == ')') { if (in->mac->argc == 1 && tokenRecorded == 0) break; arg++; break; } arg++; } while (arg < in->mac->argc); if (arg < in->mac->argc) parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { if (token == ')') depth--; token = currentInput->scan(this, currentInput, ppToken); if (token == '(') depth++; } if (token <= 0) { parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } parseContext.error(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); } for (int i = 0; i < in->mac->argc; i++) in->args[i] = PrescanMacroArg(in->args[i], ppToken); } /*retain the input source*/ in->prev = currentInput; sym->mac.busy = 1; RewindTokenStream(sym->mac.body); currentInput = in; return 1; }
// // ======================================================================================================================= // Map_ImportFile Timo 09/01/99:: called by CXYWnd::Paste & Map_ImportFile if Map_ImportFile ( prefab ), the buffer // may contain brushes in old format ( conversion needed ) // ======================================================================================================================= // void Map_ImportBuffer(char *buf, bool renameEntities) { entity_t *ent; brush_t *b = NULL; CPtrArray ptrs; Select_Deselect(); Undo_Start("import buffer"); g_qeglobals.d_parsed_brushes = 0; if (buf) { CMapStringToString mapStr; StartTokenParsing(buf); g_qeglobals.d_num_entities = 0; // // Timo will be used in Entity_Parse to detect if a conversion between brush // formats is needed // g_qeglobals.bNeedConvert = false; g_qeglobals.bOldBrushes = false; g_qeglobals.bPrimitBrushes = false; g_qeglobals.mapVersion = 1.0; if (GetToken(true)) { if (stricmp(token, "Version") == 0) { GetToken(false); g_qeglobals.mapVersion = atof(token); common->Printf("Map version: %1.2f\n", g_qeglobals.mapVersion); } else { UngetToken(); } } idDict RemappedNames; // since I can't use "map <string, string>"... sigh. So much for STL... while (1) { // // use the selected brushes list as it's handy ent = Entity_Parse (false, // &selected_brushes); // ent = Entity_Parse(false, &active_brushes); if (!ent) { break; } // end entity for undo Undo_EndEntity(ent); // end brushes for undo for (b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext) { Undo_EndBrush(b); } if (!strcmp(ValueForKey(ent, "classname"), "worldspawn")) { // world brushes need to be added to the current world entity b = ent->brushes.onext; while (b && b != &ent->brushes) { brush_t *bNext = b->onext; Entity_UnlinkBrush(b); Entity_LinkBrush(world_entity, b); ptrs.Add(b); b = bNext; } } else { // the following bit remaps conflicting target/targetname key/value pairs CString str = ValueForKey(ent, "target"); CString strKey; CString strTarget(""); if (str.GetLength() > 0) { if (FindEntity("target", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { idStr key; UniqueTargetName(key); strKey = key; mapStr.SetAt(str, strKey); } strTarget = strKey; SetKeyValue(ent, "target", strTarget.GetBuffer(0)); } } /* * str = ValueForKey(ent, "name"); if (str.GetLength() > 0) { if * (FindEntity("name", str.GetBuffer(0))) { if (!mapStr.Lookup(str, strKey)) { * UniqueTargetName(strKey); mapStr.SetAt(str, strKey); } Entity_SetName(ent, * strKey.GetBuffer(0)); } } */ CString cstrNameOld = ValueForKey(ent, "name"); Entity_Name(ent, renameEntities); CString cstrNameNew = ValueForKey(ent, "name"); if (cstrNameOld != cstrNameNew) { RemappedNames.Set(cstrNameOld, cstrNameNew); } // // if (strTarget.GetLength() > 0) SetKeyValue(ent, "target", // strTarget.GetBuffer(0)); // add the entity to the end of the entity list // ent->next = &entities; ent->prev = entities.prev; entities.prev->next = ent; entities.prev = ent; g_qeglobals.d_num_entities++; for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) { ptrs.Add(b); } } } // now iterate through the remapped names, and see if there are any target-connections that need remaking... // // (I could probably write this in half the size with STL, but WTF, work with what we have...) // int iNumKeyVals = RemappedNames.GetNumKeyVals(); for (int iKeyVal=0; iKeyVal < iNumKeyVals; iKeyVal++) { const idKeyValue *pKeyVal = RemappedNames.GetKeyVal( iKeyVal ); LPCSTR psOldName = pKeyVal->GetKey().c_str(); LPCSTR psNewName = pKeyVal->GetValue().c_str(); entity_t *pEntOld = FindEntity("name", psOldName); // original ent we cloned from entity_t *pEntNew = FindEntity("name", psNewName); // cloned ent if (pEntOld && pEntNew) { CString cstrTargetNameOld = ValueForKey(pEntOld, "target"); if (!cstrTargetNameOld.IsEmpty()) { // ok, this ent was targeted at another ent, so it's clone needs updating to point to // the clone of that target, so... // entity_t *pEntOldTarget = FindEntity("name", cstrTargetNameOld); if ( pEntOldTarget ) { LPCSTR psNewTargetName = RemappedNames.GetString( cstrTargetNameOld ); if (psNewTargetName && psNewTargetName[0]) { SetKeyValue(pEntNew, "target", psNewTargetName); } } } } } } // // ::ShowWindow(g_qeglobals.d_hwndEntity, FALSE); // ::LockWindowUpdate(g_qeglobals.d_hwndEntity); // g_bScreenUpdates = false; for (int i = 0; i < ptrs.GetSize(); i++) { Brush_Build(reinterpret_cast < brush_t * > (ptrs[i]), true, false); Select_Brush(reinterpret_cast < brush_t * > (ptrs[i]), true, false); } // ::LockWindowUpdate(NULL); g_bScreenUpdates = true; ptrs.RemoveAll(); // // reset the "need conversion" flag conversion to the good format done in // Map_BuildBrushData // g_qeglobals.bNeedConvert = false; Sys_UpdateWindows(W_ALL); // Sys_MarkMapModified(); mapModified = 1; Undo_End(); }