void Resource::Comment() { Match(';'); while (!Is('\n') && !Is(EOF)) { Lex(); } if (Is(';')) { Comment(); } }
Parser::ExprResult Parser::ParseEquivOperand() { ExprResult E = ParseOrOperand(); if (E.isInvalid()) return E; while (Tok.getKind() == tok::kw_OR) { SourceLocation OpLoc = Tok.getLocation(); Lex(); ExprResult OrOp = ParseOrOperand(); if (OrOp.isInvalid()) return OrOp; E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::Or, E, OrOp); } return E; }
Parser::ExprResult Parser::ParseLevel5Expr() { ExprResult E = ParseEquivOperand(); if (E.isInvalid()) return E; while (true) { SourceLocation OpLoc = Tok.getLocation(); switch (Tok.getKind()) { default: return E; case tok::kw_EQV: Lex(); E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::Eqv, E, ParseEquivOperand()); break; case tok::kw_NEQV: Lex(); E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::Neqv, E, ParseEquivOperand()); break; } } return E; }
Parser::ExprResult Parser::ParseOrOperand() { ExprResult E = ParseAndOperand(); if (E.isInvalid()) return E; while (Tok.getKind() == tok::kw_AND) { SourceLocation OpLoc = Tok.getLocation(); Lex(); ExprResult AndOp = ParseAndOperand(); if (AndOp.isInvalid()) return AndOp; E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::And, E, AndOp); } return E; }
// ParseLevel3Expr - Level-3 expressions are level-2 expressions optionally // involving the character operator concat-op. // // R710: // level-3-expr := // [ level-3-expr concat-op ] level-2-expr // R711: // concat-op := // // Parser::ExprResult Parser::ParseLevel3Expr() { ExprResult E = ParseLevel2Expr(); if (E.isInvalid()) return E; while (Tok.getKind() == tok::slashslash) { SourceLocation OpLoc = Tok.getLocation(); Lex(); ExprResult Lvl2Expr = ParseLevel2Expr(); if (Lvl2Expr.isInvalid()) return Lvl2Expr; E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::Concat, E, Lvl2Expr); } return E; }
// ParseLevel2Expr - Level-2 expressions are level-1 expressions optionally // involving the numeric operators power-op, mult-op, and add-op. // // R706: // level-2-expr := // [ [ level-2-expr ] add-op ] add-operand // R705: // add-operand := // [ add-operand mult-op ] mult-operand // R704: // mult-operand := // level-1-expr [ power-op mult-operand ] // R707: // power-op := // ** // R708: // mult-op := // * // or / // R709: // add-op := // + // or - Parser::ExprResult Parser::ParseMultOperand() { ExprResult E = ParseLevel1Expr(); if (E.isInvalid()) return E; if (Tok.getKind() == tok::starstar) { SourceLocation OpLoc = Tok.getLocation(); Lex(); ExprResult MulOp = ParseMultOperand(); if (MulOp.isInvalid()) return MulOp; E = Actions.ActOnBinaryExpr(Context, OpLoc, BinaryExpr::Power, E, MulOp); } return E; }
F64 CompileDemo(U8 *st) { I64 type; U8 *ex; CLex *lx=LexNew(st,LF_DONT_FREE_BUF); F64 result=0; Lex(lx); //Gotta get it started "Compile \"%s\"\n",st; do { if (ex=LexExpression2Bin(lx,&type)) { if (type!=IT_F64) result=ToF64(Call(ex)); else result=Call(ex)(F64); ExpressionBinDel(ex); } "result=%9.4f\n",result; if (lx->token==';') Lex(lx); } while (lx->token!=TK_EOF); //end of file? LexDel(lx); return result; }
bool Resource::Match(char c) { bool r = Is(c); if (!r) { Expected(c); } Lex(); return r; }
bool Scanner:: state_DELIM (int c) { int i; if ( (i = look (buffer->get (), table->delim)) != 0 ) { CS = H; save_c = c; save_lex = Lex (count_str, table->lex_delim [i], i); return true; } else { printf ("%dbuf[%s]\n", i, buffer->get ()); throw SymbolException ( "Not found delim (state DELIM).", c, count_str); } }
bool Scanner:: state_LABEL (int c) { if ( isalpha (c) || isdigit (c) || ( c == '_') ) { buffer->add (c); return false; } else { int i = table->label.put (buffer->get ()); CS = H; save_c = c; save_lex = Lex (count_str, LEX_LABEL, i); return true; } }
// ParseExpression - Expressions are level-5 expressions optionally involving // defined binary operators. // // R722: // expr := // [ expr defined-binary-op ] level-5-expr // // R723: // defined-binary-op := // . letter [ letter ] ... . Parser::ExprResult Parser::ParseExpression() { ExprResult LHS = ParseLevel5Expr(); if (LHS.isInvalid()) return LHS; if (!IsPresent(tok::defined_operator)) return LHS; SourceLocation OpLoc = Tok.getLocation(); IdentifierInfo *II = Tok.getIdentifierInfo(); Lex(); ExprResult RHS = ParseLevel5Expr(); if (RHS.isInvalid()) return RHS; return DefinedBinaryOperatorExpr::Create(Context, OpLoc, LHS.take(), RHS.take(), II); }
// ParseLevel1Expr - Level-1 expressions are primaries optionally operated on by // defined unary operators. // // R702: // level-1-expr := // [ defined-unary-op ] primary // R703: // defined-unary-op := // . letter [ letter ] ... . Parser::ExprResult Parser::ParseLevel1Expr() { SourceLocation OpLoc = Tok.getLocation(); IdentifierInfo *II = 0; if (IsPresent(tok::defined_operator) && !IsNextToken(tok::l_paren)) { II = Tok.getIdentifierInfo(); Lex(); } ExprResult E = ParsePrimaryExpr(); if (E.isInvalid()) return E; if (II) E = DefinedUnaryOperatorExpr::Create(Context, OpLoc, E.take(), II); return E; }
std::string format(llvm::StringRef Code, unsigned Offset, unsigned Length, const FormatStyle &Style) { RewriterTestContext Context; FileID ID = Context.createInMemoryFile("input.cc", Code); SourceLocation Start = Context.Sources.getLocForStartOfFile(ID).getLocWithOffset(Offset); std::vector<CharSourceRange> Ranges( 1, CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length))); LangOptions LangOpts; LangOpts.CPlusPlus = 1; Lexer Lex(ID, Context.Sources.getBuffer(ID), Context.Sources, LangOpts); tooling::Replacements Replace = reformat(Style, Lex, Context.Sources, Ranges); EXPECT_TRUE(applyAllReplacements(Replace, Context.Rewrite)); return Context.getRewrittenText(ID); }
bool Scanner:: state_LEG (int c) { int i; if ( look (c, table->compare) != 0 ) { buffer->add (c); return false; } else if ( (i = look (buffer->get (), table->compare)) != 0 ) { CS = H; save_c = c; save_lex = Lex (count_str, table->lex_compare [i], i); return true; } else { printf ("%dbuf[%s]\n", i, buffer->get ()); throw SymbolException ( "Not found delim (state LEG).", c, count_str); } }
Expr *Expr::From(const char *in, bool popUpError) { UnparsedCnt = 0; UnparsedP = 0; OperandsP = 0; OperatorsP = 0; Expr *r; try { Lex(in); Parse(); r = PopOperand(); } catch (const char *e) { dbp("exception: parse/lex error: %s", e); if(popUpError) { Error("Not a valid number or expression: '%s'", in); } return NULL; } return r; }
// Looks for the token matching the predicate and returns the range of the found // token including trailing whitespace. static SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts, SourceLocation StartLoc, SourceLocation EndLoc, bool (*Pred)(const Token &)) { if (StartLoc.isMacroID() || EndLoc.isMacroID()) return SourceRange(); FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc)); StringRef Buf = Sources.getBufferData(File); const char *StartChar = Sources.getCharacterData(StartLoc); Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end()); Lex.SetCommentRetentionState(true); Token Tok; do { Lex.LexFromRawLexer(Tok); if (Pred(Tok)) { Token NextTok; Lex.LexFromRawLexer(NextTok); return SourceRange(Tok.getLocation(), NextTok.getLocation()); } } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc); return SourceRange(); }
bool Scanner:: state_FN (int c) { if ( isalpha (c) || isdigit (c) || (c == '_') ) { buffer->add (c); // return false; } else { int i; if ( (i = look (buffer->get (), table->function)) != 0 ) { CS = H; save_c = c; save_lex = Lex (count_str, table->lex_function [i], i); return true; } else { perror ("Not found function.\n"); throw SymbolException ("Not found function.", c, count_str); } } }
// ParseLevel4Expr - Level-4 expressions are level-3 expressions optionally // involving the relational operators. // // R712: // level-4-expr := // [ level-3-expr rel-op ] level-3-expr // R713: // rel-op := // .EQ. // or .NE. // or .LT. // or .LE. // or .GT. // or .GE. // or == // or /= // or < // or <= // or > // or >= Parser::ExprResult Parser::ParseLevel4Expr() { ExprResult E = ParseLevel3Expr(); if (E.isInvalid()) return E; while (true) { SourceLocation OpLoc = Tok.getLocation(); BinaryExpr::Operator Op = BinaryExpr::None; switch (Tok.getKind()) { default: return E; case tok::kw_EQ: case tok::equalequal: Op = BinaryExpr::Equal; break; case tok::kw_NE: case tok::slashequal: Op = BinaryExpr::NotEqual; break; case tok::kw_LT: case tok::less: Op = BinaryExpr::LessThan; break; case tok::kw_LE: case tok::lessequal: Op = BinaryExpr::LessThanEqual; break; case tok::kw_GT: case tok::greater: Op = BinaryExpr::GreaterThan; break; case tok::kw_GE: case tok::greaterequal: Op = BinaryExpr::GreaterThanEqual; break; } Lex(); ExprResult Lvl3Expr = ParseLevel3Expr(); if (Lvl3Expr.isInvalid()) return Lvl3Expr; E = Actions.ActOnBinaryExpr(Context, OpLoc, Op, E, Lvl3Expr); } return E; }
CQueVectU8 *EdRICode(CDoc *doc) { CQueVectU8 *result; CRILex *rx=CAlloc(sizeof(CRILex)); rx->lx1=LexNew(NULL,LF_KEEP_NEW_LINES|LF_DONT_FREE_BUF,doc->filename.name); Free(rx->lx1->lfns[0].name); LexAttachDoc(rx->lx1,&rx->lx1->lfns[0],doc,,doc->cur_entry,doc->cur_data_col); rx->lx2=LexNew(NULL,LF_KEEP_NEW_LINES|LF_DONT_FREE_BUF,doc->filename.name); Free(rx->lx2->lfns[0].name); LexAttachDoc(rx->lx2,&rx->lx2->lfns[0],doc,,doc->cur_entry,doc->cur_data_col); rx->indent=QueVectU8New(doc->cur_entry->y); Lex(rx->lx1); EdRIStmt(rx,FALSE); LexDel(rx->lx1); LexDel(rx->lx2); result=rx->indent; Free(rx); return result; }
// Returns true on error. static bool format(std::string FileName) { FileManager Files((FileSystemOptions())); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); SourceManager Sources(Diagnostics, Files); OwningPtr<MemoryBuffer> Code; if (error_code ec = MemoryBuffer::getFileOrSTDIN(FileName, Code)) { llvm::errs() << ec.message() << "\n"; return true; } FileID ID = createInMemoryFile(FileName, Code.get(), Sources, Files); Lexer Lex(ID, Sources.getBuffer(ID), Sources, getFormattingLangOpts()); if (Offsets.empty()) Offsets.push_back(0); if (Offsets.size() != Lengths.size() && !(Offsets.size() == 1 && Lengths.empty())) { llvm::errs() << "error: number of -offset and -length arguments must match.\n"; return true; } std::vector<CharSourceRange> Ranges; for (unsigned i = 0, e = Offsets.size(); i != e; ++i) { if (Offsets[i] >= Code->getBufferSize()) { llvm::errs() << "error: offset " << Offsets[i] << " is outside the file\n"; return true; } SourceLocation Start = Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]); SourceLocation End; if (i < Lengths.size()) { if (Offsets[i] + Lengths[i] > Code->getBufferSize()) { llvm::errs() << "error: invalid length " << Lengths[i] << ", offset + length (" << Offsets[i] + Lengths[i] << ") is outside the file.\n"; return true; } End = Start.getLocWithOffset(Lengths[i]); } else { End = Sources.getLocForEndOfFile(ID); } Ranges.push_back(CharSourceRange::getCharRange(Start, End)); } tooling::Replacements Replaces = reformat(getStyle(), Lex, Sources, Ranges); if (OutputXML) { llvm::outs() << "<?xml version='1.0'?>\n<replacements xml:space='preserve'>\n"; for (tooling::Replacements::const_iterator I = Replaces.begin(), E = Replaces.end(); I != E; ++I) { llvm::outs() << "<replacement " << "offset='" << I->getOffset() << "' " << "length='" << I->getLength() << "'>" << I->getReplacementText() << "</replacement>\n"; } llvm::outs() << "</replacements>\n"; } else { Rewriter Rewrite(Sources, LangOptions()); tooling::applyAllReplacements(Replaces, Rewrite); if (Inplace) { if (Replaces.size() == 0) return false; // Nothing changed, don't touch the file. std::string ErrorInfo; llvm::raw_fd_ostream FileStream(FileName.c_str(), ErrorInfo, llvm::raw_fd_ostream::F_Binary); if (!ErrorInfo.empty()) { llvm::errs() << "Error while writing file: " << ErrorInfo << "\n"; return true; } Rewrite.getEditBuffer(ID).write(FileStream); FileStream.flush(); } else { Rewrite.getEditBuffer(ID).write(outs()); } } return false; }
clang::NamedDecl *parseDeclarationReference(llvm::StringRef Text, clang::Sema &Sema, bool isFunction) { clang::Preprocessor &PP = Sema.getPreprocessor(); llvm::MemoryBuffer* Buf = llvm::MemoryBuffer::getMemBufferCopy(Text); #if CLANG_VERSION_MAJOR == 3 && CLANG_VERSION_MINOR <= 4 auto FID = PP.getSourceManager().createFileIDForMemBuffer(Buf); #else auto FID = PP.getSourceManager().createFileID(Buf); #endif clang::Lexer Lex(FID, Buf, PP.getSourceManager(), PP.getLangOpts()); auto TuDecl = Sema.getASTContext().getTranslationUnitDecl(); clang::CXXScopeSpec SS; clang::Token Tok, Next; Lex.LexFromRawLexer(Tok); for (; !Tok.is(clang::tok::eof); Tok = Next) { Lex.LexFromRawLexer(Next); clang::IdentifierInfo* II = nullptr; if (Tok.is(clang::tok::raw_identifier)) { II = PP.LookUpIdentifierInfo(Tok); } if (Tok.is(clang::tok::coloncolon)) { SS.MakeGlobal(Sema.getASTContext(), Tok.getLocation()); continue; } else if (Tok.is(clang::tok::identifier)) { if (Next.is(clang::tok::coloncolon)) { clang::Sema::TemplateTy Template; clang::UnqualifiedId Name; Name.setIdentifier(II, Tok.getLocation()); bool dummy; auto TemplateKind = Sema.isTemplateName(Sema.getScopeForContext(TuDecl), SS, false, Name, {}, false, Template, dummy); if (TemplateKind == clang::TNK_Non_template) { if (Sema.ActOnCXXNestedNameSpecifier(Sema.getScopeForContext(TuDecl), *II, Tok.getLocation(), Next.getLocation(), {}, false, SS)) SS.SetInvalid(Tok.getLocation()); } else if (auto T = Template.get().getAsTemplateDecl()) { // FIXME: For template, it is a bit tricky // It is still a bit broken but works in some cases for most normal functions auto T2 = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(T->getTemplatedDecl()); if (T2) { Lex.LexFromRawLexer(Tok); if (!Tok.is(clang::tok::raw_identifier)) return nullptr; II = PP.LookUpIdentifierInfo(Tok); Lex.LexFromRawLexer(Next); if (!Next.is(clang::tok::eof) && !Next.is(clang::tok::l_paren)) return nullptr; auto Result = T2->lookup(II); if (Result.size() != 1) return nullptr; auto D = Result.front(); if (isFunction && (llvm::isa<clang::RecordDecl>(D) || llvm::isa<clang::ClassTemplateDecl>(D))) { // TODO constructor return nullptr; } return D; } } Lex.LexFromRawLexer(Next); continue; } if (Next.is(clang::tok::eof) || Next.is(clang::tok::l_paren)) { clang::LookupResult Found(Sema, II, Tok.getLocation(), clang::Sema::LookupOrdinaryName); Found.suppressDiagnostics(); if (SS.isEmpty()) Sema.LookupQualifiedName(Found, TuDecl); else { clang::DeclContext* DC = Sema.computeDeclContext(SS); Sema.LookupQualifiedName(Found, DC ? DC : TuDecl); } if (Found.isSingleResult()) { auto Decl = Found.getFoundDecl(); if (isFunction && (llvm::isa<clang::RecordDecl>(Decl) || llvm::isa<clang::ClassTemplateDecl>(Decl))) { // TODO handle constructors. return nullptr; } return Decl; } if (Found.isOverloadedResult() && Next.is(clang::tok::l_paren)) { // TODO } return nullptr; } } if (Tok.is(clang::tok::tilde) || Tok.is(clang::tok::kw_operator)) { //TODO return nullptr; } if (!isFunction) return nullptr; SS = {}; // Then it is probably the return type, just skip it. } return nullptr; }
// ParsePrimaryExpr - Parse a primary expression. // // [R701]: // primary := // constant // or designator // or array-constructor // or structure-constructor // or function-reference // or type-param-inquiry // or type-param-name // or ( expr ) Parser::ExprResult Parser::ParsePrimaryExpr(bool IsLvalue) { ExprResult E; SourceLocation Loc = Tok.getLocation(); // FIXME: Add rest of the primary expressions. switch (Tok.getKind()) { default: if (isTokenIdentifier()) goto possible_keyword_as_ident; Diag.Report(getExpectedLoc(), diag::err_expected_expression); return ExprError(); case tok::error: Lex(); return ExprError(); case tok::l_paren: { ConsumeParen(); E = ParseExpression(); // complex constant. if(ConsumeIfPresent(tok::comma)) { if(E.isInvalid()) return E; auto ImPart = ParseExpectedFollowupExpression(","); if(ImPart.isInvalid()) return ImPart; E = Actions.ActOnComplexConstantExpr(Context, Loc, getMaxLocationOfCurrentToken(), E, ImPart); } ExpectAndConsume(tok::r_paren, 0, "", tok::r_paren); break; } case tok::l_parenslash : { return ParseArrayConstructor(); break; } case tok::logical_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = LogicalConstantExpr::Create(Context, getTokenRange(), StrPair.first, Context.LogicalTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::binary_boz_constant: case tok::octal_boz_constant: case tok::hex_boz_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = BOZConstantExpr::Create(Context, Loc, getMaxLocationOfCurrentToken(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::char_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); E = CharacterConstantExpr::Create(Context, getTokenRange(), StringRef(NumStr), Context.CharacterTy); ConsumeToken(); // Possible substring if(IsPresent(tok::l_paren)) return ParseSubstring(E); break; } case tok::int_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = IntegerConstantExpr::Create(Context, getTokenRange(), StrPair.first); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); Lex(); break; } case tok::real_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.RealTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::double_precision_literal_constant: { std::string NumStr; CleanLiteral(Tok, NumStr); // Replace the d/D exponent into e exponent for(size_t I = 0, Len = NumStr.length(); I < Len; ++I) { if(NumStr[I] == 'd' || NumStr[I] == 'D') { NumStr[I] = 'e'; break; } else if(NumStr[I] == '_') break; } StringRef Data(NumStr); std::pair<StringRef, StringRef> StrPair = Data.split('_'); E = RealConstantExpr::Create(Context, getTokenRange(), NumStr, Context.DoublePrecisionTy); SetKindSelector(cast<ConstantExpr>(E.get()), StrPair.second); ConsumeToken(); break; } case tok::identifier: possible_keyword_as_ident: E = Parser::ParseDesignator(IsLvalue); if (E.isInvalid()) return E; break; case tok::minus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Minus, E); break; case tok::plus: Lex(); E = Parser::ParsePrimaryExpr(); if (E.isInvalid()) return E; E = Actions.ActOnUnaryExpr(Context, Loc, UnaryExpr::Plus, E); break; } return E; }
void Preprocessor::RecursivePreprocess( std::string filename, FileLoader& file_source, LexemList& lexems, DefineTable& define_table ) { unsigned int start_line = CurrentLine; LinesThisFile = 0; CurrentFile = filename; SetFileMacro( define_table, CurrentFile ); SetLineMacro( define_table, LinesThisFile ); // Path formatting must be done in main application std::string CurrentFileRoot = RootPath + CurrentFile; if( std::find( FilesPreprocessed.begin(), FilesPreprocessed.end(), CurrentFileRoot ) == FilesPreprocessed.end() ) FilesPreprocessed.push_back( CurrentFileRoot ); std::vector<char> data; bool loaded = file_source.LoadFile( RootPath, filename, data ); if( !loaded ) { PrintErrorMessage( std::string( "Could not open file " ) + RootPath + filename ); return; } if( data.size() == 0 ) return; char* d_end = &data[data.size() - 1]; ++d_end; Lex( &data[0], d_end, lexems ); LexemList::iterator itr = lexems.begin(); LexemList::iterator end = lexems.end(); LLITR old = end; while( itr != end ) { if( itr->Type == Lexem::NEWLINE ) { if( itr != old ) { CurrentLine++; LinesThisFile++; SetLineMacro( define_table, LinesThisFile ); } old = itr; ++itr; } else if( itr->Type == Lexem::PREPROCESSOR ) { LLITR start_of_line = itr; LLITR end_of_line = ParsePreprocessor( lexems, itr, end ); LexemList directive( start_of_line, end_of_line ); if( SkipPragmas && directive.begin()->Value == "#pragma" ) { itr = end_of_line; Lexem wspace; wspace.Type = Lexem::WHITESPACE; wspace.Value = " "; for( LLITR it = start_of_line; it != end_of_line;) { ++it; it = lexems.insert( it, wspace ); ++it; } continue; } itr = lexems.erase( start_of_line, end_of_line ); std::string value = directive.begin()->Value; if( value == "#define" ) { ParseDefine( define_table, directive ); } else if( value == "#ifdef" ) { std::string def_name; ParseIf( directive, def_name ); DefineTable::iterator dti = define_table.find( def_name ); if( dti == define_table.end() ) { LLITR splice_to = ParseIfDef( itr, end ); itr = lexems.erase( itr, splice_to ); } } else if( value == "#ifndef" ) { std::string def_name; ParseIf( directive, def_name ); DefineTable::iterator dti = define_table.find( def_name ); if( dti != define_table.end() ) { LLITR splice_to = ParseIfDef( itr, end ); itr = lexems.erase( itr, splice_to ); } } else if( value == "#if" ) { bool satisfied = EvaluateExpression( define_table, directive ) != 0; if( !satisfied ) { LLITR splice_to = ParseIfDef( itr, end ); itr = lexems.erase( itr, splice_to ); } } else if( value == "#endif" ) { // ignore } else if( value == "#include" ) { if( LNT ) LNT->AddLineRange( PrependRootPath( filename ), start_line, CurrentLine - LinesThisFile ); unsigned int save_lines_this_file = LinesThisFile; std::string file_name; ParseIf( directive, file_name ); std::string file_name_ = RemoveQuotes( file_name ); if( IncludeTranslator ) IncludeTranslator->Call( file_name_ ); if( std::find( FileDependencies.begin(), FileDependencies.end(), file_name_ ) == FileDependencies.end() ) FileDependencies.push_back( file_name_ ); LexemList next_file; RecursivePreprocess( AddPaths( filename, file_name_ ), file_source, next_file, define_table ); lexems.splice( itr, next_file ); start_line = CurrentLine; LinesThisFile = save_lines_this_file; CurrentFile = filename; SetFileMacro( define_table, CurrentFile ); SetLineMacro( define_table, LinesThisFile ); } else if( value == "#pragma" ) { ParsePragma( directive ); } else if( value == "#message" ) { std::string message; ParseTextLine( directive, message ); PrintMessage( message ); } else if( value == "#warning" ) { std::string warning; ParseTextLine( directive, warning ); PrintWarningMessage( warning ); } else if( value == "#error" ) { std::string error; ParseTextLine( directive, error ); PrintErrorMessage( error ); } else { PrintErrorMessage( "Unknown directive '" + value + "'." ); } } else if( itr->Type == Lexem::IDENTIFIER ) { itr = ExpandDefine( itr, end, lexems, define_table ); } else { ++itr; } } if( LNT ) LNT->AddLineRange( PrependRootPath( filename ), start_line, CurrentLine - LinesThisFile ); }
static void parsePluginMetaData(ClassDef &Def, clang::Expr *Content, clang::Sema &Sema) { clang::Preprocessor &PP = Sema.getPreprocessor(); clang::StringLiteral *Val = llvm::dyn_cast<clang::StringLiteral>(Content); if (!Val) { PP.getDiagnostics().Report(Content->getExprLoc(), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid Q_PLUGIN_METADATA annotation")); return; } llvm::MemoryBuffer* Buf = maybe_unique(llvm::MemoryBuffer::getMemBufferCopy(Val->getString(), "Q_PLUGIN_METADATA")); clang::Lexer Lex(CreateFileIDForMemBuffer(PP, Buf, Content->getExprLoc()), Buf, PP.getSourceManager(), PP.getLangOpts()); clang::Token Tok; Lex.LexFromRawLexer(Tok); while (Tok.is(clang::tok::raw_identifier)) { clang::IdentifierInfo *II = PP.LookUpIdentifierInfo(Tok); if (II->getName() != "IID" && II->getName() != "FILE") { Lex.LexFromRawLexer(Tok); continue; } Lex.LexFromRawLexer(Tok); if (!Tok.is(clang::tok::string_literal)) { PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Expected string literal")); return; } llvm::SmallVector<clang::Token, 4> StrToks; do { StrToks.push_back(Tok); Lex.LexFromRawLexer(Tok); } while (Tok.is(clang::tok::string_literal)); #if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>4 clang::StringLiteralParser Literal(StrToks, PP); #else clang::StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP); #endif if (Literal.hadError) return; if (II->getName() == "IID") Def.Plugin.IID = Literal.GetString(); else { llvm::StringRef Filename = Literal.GetString(); const clang::DirectoryLookup *CurDir; const clang::FileEntry *File = PP.LookupFile( #if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>3 Val->getLocStart(), #endif Filename, false, nullptr, #if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>5 nullptr, #endif CurDir, nullptr, nullptr, nullptr); if (!File) { PP.getDiagnostics().Report(GetFromLiteral(StrToks.front(), Val, PP), clang::diag::err_pp_file_not_found) << Filename; return; } const llvm::MemoryBuffer* JSonBuf = PP.getSourceManager().getMemoryBufferForFile(File); llvm::SourceMgr SM; llvm::yaml::Stream YAMLStream(JSonBuf->getBuffer(), SM); llvm::yaml::document_iterator I = YAMLStream.begin(); if (I == YAMLStream.end() || !I->getRoot() || !QBJS::Parse(I->getRoot(), Def.Plugin.MetaData)) { // FIXME PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Error pwhile parsing JSON")); return; } } } if (!Tok.is(clang::tok::eof)) { PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Parse error: Expected 'IID' or 'FILE'")); return; } }
static void parseEnums(ClassDef &Def, bool isFlag, clang::Expr *Content, clang::Sema &Sema) { clang::Preprocessor &PP = Sema.getPreprocessor(); clang::StringLiteral *Val = llvm::dyn_cast<clang::StringLiteral>(Content); if (!Val) { PP.getDiagnostics().Report(Content->getExprLoc(), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid Q_ENUMS annotation")); return; } llvm::MemoryBuffer* Buf = maybe_unique(llvm::MemoryBuffer::getMemBufferCopy(Val->getString(), "Q_ENUMS")); clang::Lexer Lex(CreateFileIDForMemBuffer(PP, Buf, Content->getExprLoc()), Buf, PP.getSourceManager(), PP.getLangOpts()); clang::CXXScopeSpec SS; clang::Token Tok, Next; Lex.LexFromRawLexer(Tok); for (; !Tok.is(clang::tok::eof); Tok = Next) { Lex.LexFromRawLexer(Next); clang::IdentifierInfo* II = nullptr; if (Tok.is(clang::tok::raw_identifier)) II = PP.LookUpIdentifierInfo(Tok); if (Tok.is(clang::tok::identifier)) { if (Next.is(clang::tok::coloncolon)) { if (Sema.ActOnCXXNestedNameSpecifier(Sema.getScopeForContext(Def.Record), *II, GetFromLiteral(Tok, Val, PP), GetFromLiteral(Next, Val, PP), {}, false, SS)) SS.SetInvalid({GetFromLiteral(Tok, Val, PP), GetFromLiteral(Next, Val, PP)}); Lex.LexFromRawLexer(Next); continue; } clang::LookupResult Found(Sema, II, GetFromLiteral(Tok, Val, PP), clang::Sema::LookupNestedNameSpecifierName); if (SS.isEmpty()) Sema.LookupQualifiedName(Found, Def.Record); else { clang::DeclContext* DC = Sema.computeDeclContext(SS); Sema.LookupQualifiedName(Found, DC ? DC : Def.Record); } llvm::StringRef Alias; clang::EnumDecl* R = Found.getAsSingle<clang::EnumDecl>(); if (!R) { if (clang::TypedefDecl *TD = Found.getAsSingle<clang::TypedefDecl>()) { const clang::EnumType* ET = TD->getUnderlyingType()->getAs<clang::EnumType>(); const clang::TemplateSpecializationType* TDR = TD->getUnderlyingType()->getAs<clang::TemplateSpecializationType>(); if(TDR && TDR->getNumArgs() == 1 && TDR->getTemplateName().getAsTemplateDecl()->getName() == "QFlags") ET = TDR->getArg(0).getAsType()->getAs<clang::EnumType>(); if (ET) { R = ET->getDecl(); if (TD->getIdentifier()) Alias = TD->getName(); } } } if (Found.empty() || !R) { // TODO: typo correction // This should be an error, but the official moc do not understand that as an error. PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Warning, "no enum names %0")) << Found.getLookupName(); break; } if (R->getDeclContext() == Def.Record) { if (Alias.empty() && R->getIdentifier()) Alias = R->getName(); Def.addEnum(R, Alias.empty() ? R->getNameAsString() : std::string(Alias), isFlag); } else if (R->getDeclContext()->isRecord() && llvm::isa<clang::CXXRecordDecl>(R->getDeclContext())) { // TODO: check it is a QObject Def.addExtra(llvm::cast<clang::CXXRecordDecl>(R->getDeclContext())); } SS.clear(); continue; } else if (Tok.is(clang::tok::coloncolon)) { if (SS.isEmpty()) { SS.MakeGlobal(Sema.getASTContext(), GetFromLiteral(Tok, Val, PP)); continue; } } PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid token in Q_ENUMS")); break; } }
arg_list_t *Resource::Symbol() { int i = 0, j; arg_list_t *a; bool string = false; bool fp = false; float f; arg_list_t *adt; _symbol[0] = 0; if (Is('"')) { Lex(); string = true; } // Mongoose 2001.11.09: Best handle for? grouped (func (func if (Is('(')) { return Function(arg_peek(&_stack)); } while (string || (i == 0 && _look == '-') || isatoz(_look) || isAtoZ(_look) || isdigit(_look) || ismisc(_look)) { if (i < (int)_symbol_len) { _symbol[i++] = _look; _symbol[i] = 0; } if (string && Is('"')) { i--; _symbol[i] = 0; Lex(); break; } Lex(); if (string) { continue; } if (Is('.')) { fp = true; for (j = 0; j < i; j++) { if (!j && _symbol[j] == '-') continue; if (!isdigit(_symbol[j])) break; } if (i == j) { _symbol[i++] = _look; _symbol[i] = 0; Lex(); } } // Mongoose 2002.01.23, Hhhmm... fixes -100.00 and -100, // but is it 'good idea'? if (Is('-') && i == 0) { _symbol[i++] = _look; _symbol[i] = 0; Lex(); } } #ifdef DEBUG_RESOURCE_SYMBOL printf("%s\n", _symbol); #endif if (isnumeric(_symbol, &f)) { if (fp) { new_float(&a, f); } else { new_int(&a, (int)f); } } else { // Mongoose 2002.01.21, FIXME support ADTs and etc too if (Lookup(_symbol, &i)) { new_int(&a, i); } else if (Lookup(_symbol, &f)) { new_float(&a, f); } else if (string) { mlisp_new_string(&a, _symbol); } else if (Lookup(_symbol, &adt)) { mlisp_new_adt(&a, adt->type, adt->data); } else { // Mongoose 2002.01.21, FIXME: hack to handle old string // use for def symbols mlisp_new_string(&a, _symbol); } } return a; }
int Resource::Eval(char *buffer) { arg_list_t *a, *b, *c; if (!buffer || !buffer[0]) { return -1; } // Mongoose: Start counting lines at 1, errors at 0 _line = 1; _error = 0; #ifdef MULTI_EVAL _top = 0; _string = 0; while (_stack) { arg_pop(&_stack); } _stack = NULL; #endif Lex(); Seperator(); while (Is('#')) { printf("Resource::Eval> Preprocessor not implemented yet.\n"); Lex(); a = Symbol(); Seperator(); b = Symbol(); Seperator(); c = Symbol(); Seperator(); // #func arg1 arg2 ( eg #define FOOBAR 1 ) // Preprocessor function delete_arg(&a); // Arg 1 delete_arg(&b); // Arg 2 delete_arg(&c); } a = NULL; while (Is('(')) { // FIXME: Handle scope with paren counter and appending to list a a = Function(a); Seperator(); } if (_error) printf("\n\nEval> Encountered %i Errors\n\n", _error); return 0; }
Lex Scanner::get_lex() { int d = 0, j, n = 1; double r = 0; CS = H; do { switch (CS) { case H: if (c == ' ' || c == '\n' || c == '\r' || c == '\t') gc(); else if (isalpha(c)) { clear(); add(); gc(); CS = IDENT; //cout << "H IDENT" << endl; } else if (isdigit(c)) { d = c - '0'; gc(); CS = NUM; //cout << "H NUM" << endl; } else if (c == '{') { gc(); CS = COM; //cout << "H COM" << endl; } else if (c == ':' || c == '<' || c == '>') { clear(); add(); gc(); CS = ALE; //cout << "H ALE" << endl; } else if (c == '@') { //cout << "H return" << endl; return Lex(LEX_FIN); } else if (c == '!') { clear(); add(); gc(); CS = NEQ; //cout << "H NEQ" << endl; } else if (c == '&') { clear(); add(); gc(); CS = UNMINUS; //cout << "H NEQ" << endl; } else { CS = DELIM; //cout << "H DELIM" << endl; } break; case IDENT: if (isalpha(c) || isdigit(c)) { //cout << "IDENT here1" << endl; add(); gc(); } else if (j = look(buf, TW)) { //cout << "IDENT here2" << endl; cout << "buf " << buf << endl; return Lex(words[j], j); } else { //cout << "IDENT here3" << endl; //cout << "buf " << buf << endl; j = TID.put(buf); return Lex(LEX_ID, j); } break; case NUM: if (isdigit(c)) { d = d * 10 + (c - '0'); gc(); } else if (c == '.') { gc(); CS = REAL; } else return Lex(LEX_NUM, d); break; case REAL: if (isdigit(c)) { r = r * 10 + (c - '0'); n *= 10; gc(); } else return Lex(LEX_NUM, d + r / n); break; case COM: if (c == '}') { gc(); CS = H; } else if (c == '@' || c == '{') throw c; else { gc(); } break; case ALE: if (c == '=') { add(); gc(); j = look(buf, TD); cout << "buf " << buf << endl; return Lex(dlms[j], j); } else { j = look(buf, TD); return Lex(dlms[j], j); } break; case NEQ: if (c == '=') { add(); gc(); j = look(buf, TD); return Lex(LEX_NEQ, j); } else throw '!'; break; case UNMINUS: j = look(buf, TD); return Lex(LEX_UN_MINUS, j); break; case DELIM: clear(); add(); if (j = look(buf, TD)) { gc(); return Lex(dlms[j], j); } else throw c; break; } // end switch } while (true); }
InputValidator::ValidationResult InputValidator::validate(llvm::StringRef line) { ValidationResult Res = kComplete; Token Tok; const char* curPos = line.data(); bool multilineComment = inBlockComment(); int commentTok = multilineComment ? tok::asterik : tok::slash; if (!multilineComment && m_ParenStack.empty()) { // Only check for 'template' if we're not already indented MetaLexer Lex(curPos, true); Lex.Lex(Tok); curPos = Lex.getLocation(); if (Tok.is(tok::ident)) { if (Tok.getIdent()=="template") m_ParenStack.push_back(tok::greater); } else curPos -= Tok.getLength(); // Rewind buffer for LexPunctuatorAndAdvance } do { const char* prevStart = curPos; if (!MetaLexer::LexPunctuatorAndAdvance(curPos, Tok)) { // there were tokens between the previous and this Tok. commentTok = tok::slash; } const int kind = (int)Tok.getKind(); if (kind == commentTok) { if (kind == tok::slash) { if (multilineComment) { // exiting a comment, unwind the stack multilineComment = false; commentTok = tok::slash; unwindTokens(m_ParenStack, tok::slash); } // If we have a closing comment without a start it will be transformed // to */; and clang reports an error for both the */ and the ; // If we return kIncomplete, then just one error is printed, but too // late: after the user has another expression which will always fail. // So just deal with two errors for now // else if (prevKind == tok::asterik) { // Res = kIncomplete; // break; // } else // wait for an asterik commentTok = tok::asterik; } else { assert(commentTok == tok::asterik && "Comment token not / or *"); if (!multilineComment) { // entering a new comment multilineComment = true; m_ParenStack.push_back(tok::slash); } else // wait for closing / (must be next token) commentTok = tok::slash; } } else { // If we're in a multiline, and waiting for the closing slash // we gonna have to wait for another asterik first if (multilineComment) { if (kind == tok::eof) { switch (findNestedBlockComments(prevStart, curPos)) { case -1: unwindTokens(m_ParenStack, tok::slash); case 1: case 0: break; default: assert(0 && "Nested block comment count"); break; } // eof, were done anyway break; } else if (commentTok == tok::slash) { // Cancel the wait for a slash, but only if current token isn't // also an asterik. if (kind != tok::asterik) commentTok = tok::asterik; } } if (kind >= (int)tok::l_square && kind <= (int)tok::r_brace) { // The closing paren kind is open paren kind + 1 (i.e odd number) if (kind % 2) { int prev = m_ParenStack.empty() ? -1: m_ParenStack.back(); // closing the right one? if (prev != kind - 1) { if (multilineComment) continue; Res = kMismatch; break; } m_ParenStack.pop_back(); // Right brace will pop a template if their is one if (kind == tok::r_brace && m_ParenStack.size() == 1 ) { if (m_ParenStack.back() == tok::greater) m_ParenStack.pop_back(); } } else m_ParenStack.push_back(kind); } else if (kind == tok::hash) { MetaLexer Lex(curPos); Lex.SkipWhitespace(); Lex.LexAnyString(Tok); const llvm::StringRef PPtk = Tok.getIdent(); if (PPtk.startswith("endif") && (PPtk.size() > 5 ? PPtk[5]=='/' || isspace(PPtk[5]) : true)) { if (m_ParenStack.empty() || m_ParenStack.back() != tok::hash) { Res = kMismatch; break; } m_ParenStack.pop_back(); } else if (PPtk.startswith("if")) { m_ParenStack.push_back(tok::hash); } } else if (kind == tok::semicolon) { // Template forward declatation if (m_ParenStack.size() == 1 && m_ParenStack.back()==tok::greater) m_ParenStack.pop_back(); } else if (kind >= (int)tok::stringlit && kind <= (int)tok::charlit) { MetaLexer::LexQuotedStringAndAdvance(curPos, Tok); } } } while (Tok.isNot(tok::eof)); if (!m_ParenStack.empty() && Res != kMismatch) Res = kIncomplete; if (!m_Input.empty()) { if (!m_ParenStack.empty() && (m_ParenStack.back() == tok::stringlit || m_ParenStack.back() == tok::charlit)) m_Input.append("\\n"); else m_Input.append("\n"); } else m_Input = ""; m_Input.append(line); return Res; }
/// ParseTypeDeclarationStmt - Parse a type-declaration-stmt construct. /// /// [R501]: /// type-declaration-stmt := /// declaration-type-spec [ [ , attr-spec ] ... :: ] entity-decl-list bool Parser::ParseTypeDeclarationStmt(SmallVectorImpl<DeclResult> &Decls) { DeclSpec DS; if (ParseDeclarationTypeSpec(DS)) return true; while (ConsumeIfPresent(tok::comma)) { // [R502]: // attr-spec := // access-spec // or ALLOCATABLE // or ASYNCHRONOUS // or CODIMENSION lbracket coarray-spec rbracket // or CONTIGUOUS // or DIMENSION ( array-spec ) // or EXTERNAL // or INTENT ( intent-spec ) // or INTRINSIC // or language-binding-spec // TODO! // or OPTIONAL // or PARAMETER // or POINTER // or PROTECTED // or SAVE // or TARGET // or VALUE // or VOLATILE auto Kind = Tok.getKind(); auto Loc = Tok.getLocation(); if(!ExpectAndConsume(tok::identifier)) { goto error; } switch (Kind) { default: Diag.ReportError(Loc, "unknown attribute specification"); goto error; case tok::kw_ALLOCATABLE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_allocatable); break; case tok::kw_ASYNCHRONOUS: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_asynchronous); break; case tok::kw_CODIMENSION: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_codimension); // FIXME: Parse the coarray-spec. break; case tok::kw_CONTIGUOUS: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_contiguous); break; case tok::kw_DIMENSION: if (ParseDimensionAttributeSpec(Loc, DS)) goto error; break; case tok::kw_EXTERNAL: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_external); break; case tok::kw_INTENT: // FIXME: if(!ExpectAndConsume(tok::l_paren)) goto error; switch (Tok.getKind()) { default: Diag.ReportError(Tok.getLocation(), "invalid INTENT specifier"); goto error; case tok::kw_IN: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_in); break; case tok::kw_OUT: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_out); break; case tok::kw_INOUT: Actions.ActOnIntentSpec(Loc, DS, DeclSpec::IS_inout); break; } Lex(); if(!ExpectAndConsume(tok::r_paren)) goto error; break; case tok::kw_INTRINSIC: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_intrinsic); break; case tok::kw_OPTIONAL: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_optional); break; case tok::kw_PARAMETER: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_parameter); break; case tok::kw_POINTER: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_pointer); break; case tok::kw_PROTECTED: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_protected); break; case tok::kw_SAVE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_save); break; case tok::kw_TARGET: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_target); break; case tok::kw_VALUE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_value); break; case tok::kw_VOLATILE: Actions.ActOnAttrSpec(Loc, DS, DeclSpec::AS_volatile); break; // Access Control Specifiers case tok::kw_PUBLIC: Actions.ActOnAccessSpec(Loc, DS, DeclSpec::AC_public); break; case tok::kw_PRIVATE: Actions.ActOnAccessSpec(Loc, DS, DeclSpec::AC_private); break; } } ConsumeIfPresent(tok::coloncolon); if (ParseEntityDeclarationList(DS, Decls)) return true; return false; error: return true; }