RetType dispatchByItemKind_gen(Directive item,Visitor& vis) { using namespace Brig; switch(item.brig()->kind) { case BRIG_DIRECTIVE_LABEL: return vis(DirectiveLabel(item)); case BRIG_DIRECTIVE_BLOCK_END: return vis(BlockEnd(item)); case BRIG_DIRECTIVE_EXTENSION: return vis(DirectiveExtension(item)); case BRIG_DIRECTIVE_VARIABLE: return vis(DirectiveVariable(item)); case BRIG_DIRECTIVE_ARG_SCOPE_END: return vis(DirectiveArgScopeEnd(item)); case BRIG_DIRECTIVE_CONTROL: return vis(DirectiveControl(item)); case BRIG_DIRECTIVE_SAMPLER: return vis(DirectiveSampler(item)); case BRIG_DIRECTIVE_VARIABLE_INIT: return vis(DirectiveVariableInit(item)); case BRIG_DIRECTIVE_SIGNATURE: return vis(DirectiveSignature(item)); case BRIG_DIRECTIVE_BLOCK_STRING: return vis(BlockString(item)); case BRIG_DIRECTIVE_FILE: return vis(DirectiveFile(item)); case BRIG_DIRECTIVE_VERSION: return vis(DirectiveVersion(item)); case BRIG_DIRECTIVE_KERNEL: return vis(DirectiveKernel(item)); case BRIG_DIRECTIVE_IMAGE: return vis(DirectiveImage(item)); case BRIG_DIRECTIVE_LABEL_INIT: return vis(DirectiveLabelInit(item)); case BRIG_DIRECTIVE_LABEL_TARGETS: return vis(DirectiveLabelTargets(item)); case BRIG_DIRECTIVE_ARG_SCOPE_START: return vis(DirectiveArgScopeStart(item)); case BRIG_DIRECTIVE_BLOCK_START: return vis(BlockStart(item)); case BRIG_DIRECTIVE_IMAGE_INIT: return vis(DirectiveImageInit(item)); case BRIG_DIRECTIVE_SAMPLER_INIT: return vis(DirectiveSamplerInit(item)); case BRIG_DIRECTIVE_FUNCTION: return vis(DirectiveFunction(item)); case BRIG_DIRECTIVE_BLOCK_NUMERIC: return vis(BlockNumeric(item)); case BRIG_DIRECTIVE_LOC: return vis(DirectiveLoc(item)); case BRIG_DIRECTIVE_COMMENT: return vis(DirectiveComment(item)); case BRIG_DIRECTIVE_PRAGMA: return vis(DirectivePragma(item)); case BRIG_DIRECTIVE_FBARRIER: return vis(DirectiveFbarrier(item)); default: assert(false); break; } return RetType(); }
RetType dispatchByItemKind_gen(Directive item,Visitor& vis) { switch(item.kind()) { case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END: return vis(DirectiveArgBlockEnd(item)); case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START: return vis(DirectiveArgBlockStart(item)); case BRIG_KIND_DIRECTIVE_COMMENT: return vis(DirectiveComment(item)); case BRIG_KIND_DIRECTIVE_CONTROL: return vis(DirectiveControl(item)); case BRIG_KIND_DIRECTIVE_EXTENSION: return vis(DirectiveExtension(item)); case BRIG_KIND_DIRECTIVE_FBARRIER: return vis(DirectiveFbarrier(item)); case BRIG_KIND_DIRECTIVE_FUNCTION: return vis(DirectiveFunction(item)); case BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION: return vis(DirectiveIndirectFunction(item)); case BRIG_KIND_DIRECTIVE_KERNEL: return vis(DirectiveKernel(item)); case BRIG_KIND_DIRECTIVE_LABEL: return vis(DirectiveLabel(item)); case BRIG_KIND_DIRECTIVE_LOC: return vis(DirectiveLoc(item)); case BRIG_KIND_DIRECTIVE_MODULE: return vis(DirectiveModule(item)); case BRIG_KIND_DIRECTIVE_PRAGMA: return vis(DirectivePragma(item)); case BRIG_KIND_DIRECTIVE_SIGNATURE: return vis(DirectiveSignature(item)); case BRIG_KIND_DIRECTIVE_VARIABLE: return vis(DirectiveVariable(item)); case BRIG_KIND_NONE: return vis(DirectiveNone(item)); default: assert(false); break; } return RetType(); }
/// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// static void ParseDirective(const char *CommentStart, unsigned CommentLen, ExpectedData &ED, Preprocessor &PP, SourceLocation Pos) { // A single comment may contain multiple directives. for (ParseHelper PH(CommentStart, CommentStart+CommentLen); !PH.Done();) { // search for token: expected if (!PH.Search("expected")) break; PH.Advance(); // next token: - if (!PH.Next("-")) continue; PH.Advance(); // next token: { error | warning | note } DirectiveList* DL = NULL; if (PH.Next("error")) DL = &ED.Errors; else if (PH.Next("warning")) DL = &ED.Warnings; else if (PH.Next("note")) DL = &ED.Notes; else continue; PH.Advance(); // default directive kind bool RegexKind = false; const char* KindStr = "string"; // next optional token: - if (PH.Next("-re")) { PH.Advance(); RegexKind = true; KindStr = "regex"; } // skip optional whitespace PH.SkipWhitespace(); // next optional token: positive integer unsigned Count = 1; if (PH.Next(Count)) PH.Advance(); // skip optional whitespace PH.SkipWhitespace(); // next token: {{ if (!PH.Next("{{")) { PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_start) << KindStr; continue; } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin // search for token: }} if (!PH.Search("}}")) { PP.Diag(Pos.getFileLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_end) << KindStr; continue; } const char* const ContentEnd = PH.P; // mark content end PH.Advance(); // build directive text; convert \n to newlines std::string Text; llvm::StringRef NewlineStr = "\\n"; llvm::StringRef Content(ContentBegin, ContentEnd-ContentBegin); size_t CPos = 0; size_t FPos; while ((FPos = Content.find(NewlineStr, CPos)) != llvm::StringRef::npos) { Text += Content.substr(CPos, FPos-CPos); Text += '\n'; CPos = FPos + NewlineStr.size(); } if (Text.empty()) Text.assign(ContentBegin, ContentEnd); // construct new directive Directive *D = Directive::Create(RegexKind, Pos, Text, Count); std::string Error; if (D->isValid(Error)) DL->push_back(D); else { PP.Diag(Pos.getFileLocWithOffset(ContentBegin-PH.Begin), diag::err_verify_invalid_content) << KindStr << Error; } } }
/// Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// /// Returns true if any valid directives were found. static bool ParseDirective(StringRef S, ExpectedData *ED, const llvm::SourceMgr &SM, SourceLocation Pos, DiagnosticsEngine &Diags, VerifyDiagnosticConsumer::DirectiveStatus &Status) { // A single comment may contain multiple directives. bool FoundDirective = false; for (ParseHelper PH(S); !PH.Done();) { // Search for token: expected if (!PH.Search("expected", true)) break; PH.Advance(); // Next token: - if (!PH.Next("-")) continue; PH.Advance(); // Next token: { error | warning | note } DirectiveList* DL = NULL; if (PH.Next("diag")) DL = ED ? &ED->Errors : NULL; else if (PH.Next("note")) DL = ED ? &ED->Notes : NULL; else if (PH.Next("no-diagnostics")) { if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives) Diags.Report(Pos, diag::verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/true; else Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics; continue; } else continue; PH.Advance(); if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) { Diags.Report(Pos, diag::verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/false; continue; } Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives; // If a directive has been found but we're not interested // in storing the directive information, return now. if (!DL) return true; // Default directive kind. bool RegexKind = false; const char* KindStr = "string"; // Next optional token: - if (PH.Next("-re")) { PH.Advance(); RegexKind = true; KindStr = "regex"; } // Next optional token: @ SourceLocation ExpectedLoc; if (!PH.Next("@")) { ExpectedLoc = Pos; } else { PH.Advance(); unsigned Line = 0; bool FoundPlus = PH.Next("+"); if (FoundPlus || PH.Next("-")) { // Relative to current line. PH.Advance(); unsigned ExpectedLine = SM.getLineAndColumn(Pos).first; if (PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) { if (FoundPlus) ExpectedLine += Line; else ExpectedLine -= Line; ExpectedLoc = locForLine(SM, Pos, ExpectedLine); } } else { // Absolute line number. if (PH.Next(Line) && Line > 0) ExpectedLoc = locForLine(SM, Pos, Line); } if (!ExpectedLoc.isValid()) { Diags.Report(Pos, diag::verify_missing_line) << KindStr; continue; } PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next optional token: positive integer or a '+'. unsigned Min = 1; unsigned Max = 1; if (PH.Next(Min)) { PH.Advance(); // A positive integer can be followed by a '+' meaning min // or more, or by a '-' meaning a range from min to max. if (PH.Next("+")) { Max = Directive::MaxCount; PH.Advance(); } else if (PH.Next("-")) { PH.Advance(); if (!PH.Next(Max) || Max < Min) { Diags.Report(Pos, diag::verify_invalid_range) << KindStr; continue; } PH.Advance(); } else { Max = Min; } } else if (PH.Next("+")) { // '+' on its own means "1 or more". Max = Directive::MaxCount; PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next token: {{ if (!PH.Next("{{")) { Diags.Report(Pos, diag::verify_missing_start) << KindStr; continue; } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin // Search for token: }} if (!PH.Search("}}")) { Diags.Report(Pos, diag::verify_missing_end) << KindStr; continue; } const char* const ContentEnd = PH.P; // mark content end PH.Advance(); // Build directive text; convert \n to newlines. std::string Text; StringRef NewlineStr = "\\n"; StringRef Content(ContentBegin, ContentEnd-ContentBegin); size_t CPos = 0; size_t FPos; while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) { Text += Content.substr(CPos, FPos-CPos); Text += '\n'; CPos = FPos + NewlineStr.size(); } if (Text.empty()) Text.assign(ContentBegin, ContentEnd); // Construct new directive. Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max); std::string Error; if (D->isValid(Error)) { DL->push_back(D); FoundDirective = true; } else { Diags.Report(Pos, diag::verify_invalid_content) << KindStr << Error; } } return FoundDirective; }
bool CheckNesting::is_charset(Statement* n) { Directive* d = dynamic_cast<Directive*>(n); return d && d->keyword() == "charset"; }
bool ValidatorImpl::ValidateBrigDirectiveFields(Directive item) const { unsigned kind = item.kind(); switch (kind) { case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END: { DirectiveArgBlockEnd it = item; } break; case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START: { DirectiveArgBlockStart it = item; } break; case BRIG_KIND_DIRECTIVE_COMMENT: { DirectiveComment it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveComment", "name"); } break; case BRIG_KIND_DIRECTIVE_CONTROL: { DirectiveControl it = item; validate_BrigControlDirective(item, it.brig()->control, "DirectiveControl", "control"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveControl", "reserved"); validate_BrigDataOffsetOperandList(item, it.brig()->operands, "DirectiveControl", "operands"); } break; case BRIG_KIND_DIRECTIVE_FUNCTION: { DirectiveFunction it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveFunction", "name"); validate_fld_OutArgCount(item, it.brig()->outArgCount, "DirectiveFunction", "outArgCount"); validate_fld_InArgCount(item, it.brig()->inArgCount, "DirectiveFunction", "inArgCount"); validate_BrigCodeOffset(item, it.brig()->firstInArg, "DirectiveFunction", "firstInArg"); validate_BrigCodeOffset(item, it.brig()->firstCodeBlockEntry, "DirectiveFunction", "firstCodeBlockEntry"); validate_BrigCodeOffset(item, it.brig()->nextModuleEntry, "DirectiveFunction", "nextModuleEntry"); validate_BrigExecutableModifier(item, it.brig()->modifier, "DirectiveFunction", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveFunction", "linkage"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveFunction", "reserved"); } break; case BRIG_KIND_DIRECTIVE_INDIRECT_FUNCTION: { DirectiveIndirectFunction it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveIndirectFunction", "name"); validate_fld_OutArgCount(item, it.brig()->outArgCount, "DirectiveIndirectFunction", "outArgCount"); validate_fld_InArgCount(item, it.brig()->inArgCount, "DirectiveIndirectFunction", "inArgCount"); validate_BrigCodeOffset(item, it.brig()->firstInArg, "DirectiveIndirectFunction", "firstInArg"); validate_BrigCodeOffset(item, it.brig()->firstCodeBlockEntry, "DirectiveIndirectFunction", "firstCodeBlockEntry"); validate_BrigCodeOffset(item, it.brig()->nextModuleEntry, "DirectiveIndirectFunction", "nextModuleEntry"); validate_BrigExecutableModifier(item, it.brig()->modifier, "DirectiveIndirectFunction", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveIndirectFunction", "linkage"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveIndirectFunction", "reserved"); } break; case BRIG_KIND_DIRECTIVE_KERNEL: { DirectiveKernel it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveKernel", "name"); validate_fld_OutArgCount(item, it.brig()->outArgCount, "DirectiveKernel", "outArgCount"); validate_fld_InArgCount(item, it.brig()->inArgCount, "DirectiveKernel", "inArgCount"); validate_BrigCodeOffset(item, it.brig()->firstInArg, "DirectiveKernel", "firstInArg"); validate_BrigCodeOffset(item, it.brig()->firstCodeBlockEntry, "DirectiveKernel", "firstCodeBlockEntry"); validate_BrigCodeOffset(item, it.brig()->nextModuleEntry, "DirectiveKernel", "nextModuleEntry"); validate_BrigExecutableModifier(item, it.brig()->modifier, "DirectiveKernel", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveKernel", "linkage"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveKernel", "reserved"); } break; case BRIG_KIND_DIRECTIVE_SIGNATURE: { DirectiveSignature it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveSignature", "name"); validate_fld_OutArgCount(item, it.brig()->outArgCount, "DirectiveSignature", "outArgCount"); validate_fld_InArgCount(item, it.brig()->inArgCount, "DirectiveSignature", "inArgCount"); validate_BrigCodeOffset(item, it.brig()->firstInArg, "DirectiveSignature", "firstInArg"); validate_BrigCodeOffset(item, it.brig()->firstCodeBlockEntry, "DirectiveSignature", "firstCodeBlockEntry"); validate_BrigCodeOffset(item, it.brig()->nextModuleEntry, "DirectiveSignature", "nextModuleEntry"); validate_BrigExecutableModifier(item, it.brig()->modifier, "DirectiveSignature", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveSignature", "linkage"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveSignature", "reserved"); } break; case BRIG_KIND_DIRECTIVE_EXTENSION: { DirectiveExtension it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveExtension", "name"); } break; case BRIG_KIND_DIRECTIVE_FBARRIER: { DirectiveFbarrier it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveFbarrier", "name"); validate_BrigVariableModifier(item, it.brig()->modifier, "DirectiveFbarrier", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveFbarrier", "linkage"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveFbarrier", "reserved"); } break; case BRIG_KIND_DIRECTIVE_LABEL: { DirectiveLabel it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveLabel", "name"); } break; case BRIG_KIND_DIRECTIVE_LOC: { DirectiveLoc it = item; validate_BrigDataOffsetString(item, it.brig()->filename, "DirectiveLoc", "filename"); validate_fld_Line(item, it.brig()->line, "DirectiveLoc", "line"); validate_fld_Column(item, it.brig()->column, "DirectiveLoc", "column"); } break; case BRIG_KIND_DIRECTIVE_MODULE: { DirectiveModule it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveModule", "name"); validate_BrigVersion(item, it.brig()->hsailMajor, "DirectiveModule", "hsailMajor"); validate_BrigVersion(item, it.brig()->hsailMinor, "DirectiveModule", "hsailMinor"); validate_BrigProfile(item, it.brig()->profile, "DirectiveModule", "profile"); validate_BrigMachineModel(item, it.brig()->machineModel, "DirectiveModule", "machineModel"); validate_BrigRound(item, it.brig()->defaultFloatRound, "DirectiveModule", "defaultFloatRound"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveModule", "reserved"); } break; case BRIG_KIND_NONE: { DirectiveNone it = item; } break; case BRIG_KIND_DIRECTIVE_PRAGMA: { DirectivePragma it = item; validate_BrigDataOffsetOperandList(item, it.brig()->operands, "DirectivePragma", "operands"); } break; case BRIG_KIND_DIRECTIVE_VARIABLE: { DirectiveVariable it = item; validate_BrigDataOffsetString(item, it.brig()->name, "DirectiveVariable", "name"); validate_BrigOperandOffset(item, it.brig()->init, "DirectiveVariable", "init"); validate_BrigType(item, it.brig()->type, "DirectiveVariable", "type"); validate_BrigSegment(item, it.brig()->segment, "DirectiveVariable", "segment"); validate_BrigAlignment(item, it.brig()->align, "DirectiveVariable", "align"); validate_fld_Dim(item, it.brig()->dim, "DirectiveVariable", "dim"); validate_BrigVariableModifier(item, it.brig()->modifier, "DirectiveVariable", "modifier"); validate_BrigLinkage(item, it.brig()->linkage, "DirectiveVariable", "linkage"); validate_BrigAllocation(item, it.brig()->allocation, "DirectiveVariable", "allocation"); validate_fld_Reserved(item, it.brig()->reserved, "DirectiveVariable", "reserved"); } break; default: return false; // not found } // switch return true; // found and validated }
/// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// /// Returns true if any valid directives were found. static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, Preprocessor *PP, SourceLocation Pos, VerifyDiagnosticConsumer::DirectiveStatus &Status) { DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics(); // A single comment may contain multiple directives. bool FoundDirective = false; for (ParseHelper PH(S); !PH.Done();) { // Search for token: expected if (!PH.Search("expected", true)) break; PH.Advance(); // Next token: - if (!PH.Next("-")) continue; PH.Advance(); // Next token: { error | warning | note } DirectiveList* DL = NULL; if (PH.Next("error")) DL = ED ? &ED->Errors : NULL; else if (PH.Next("warning")) DL = ED ? &ED->Warnings : NULL; else if (PH.Next("note")) DL = ED ? &ED->Notes : NULL; else if (PH.Next("no-diagnostics")) { if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives) Diags.Report(Pos, diag::err_verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/true; else Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics; continue; } else continue; PH.Advance(); if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) { Diags.Report(Pos, diag::err_verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/false; continue; } Status = VerifyDiagnosticConsumer::HasOtherExpectedDirectives; // If a directive has been found but we're not interested // in storing the directive information, return now. if (!DL) return true; // Default directive kind. bool RegexKind = false; const char* KindStr = "string"; // Next optional token: - if (PH.Next("-re")) { PH.Advance(); RegexKind = true; KindStr = "regex"; } // Next optional token: @ SourceLocation ExpectedLoc; if (!PH.Next("@")) { ExpectedLoc = Pos; } else { PH.Advance(); unsigned Line = 0; bool FoundPlus = PH.Next("+"); if (FoundPlus || PH.Next("-")) { // Relative to current line. PH.Advance(); bool Invalid = false; unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid); if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) { if (FoundPlus) ExpectedLine += Line; else ExpectedLine -= Line; ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1); } } else if (PH.Next(Line)) { // Absolute line number. if (Line > 0) ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1); } else if (PP && PH.Search(":")) { // Specific source file. StringRef Filename(PH.C, PH.P-PH.C); PH.Advance(); // Lookup file via Preprocessor, like a #include. const DirectoryLookup *CurDir; const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir, NULL, NULL, 0); if (!FE) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_file) << Filename << KindStr; continue; } if (SM.translateFile(FE).isInvalid()) SM.createFileID(FE, Pos, SrcMgr::C_User); if (PH.Next(Line) && Line > 0) ExpectedLoc = SM.translateFileLineCol(FE, Line, 1); } if (ExpectedLoc.isInvalid()) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_line) << KindStr; continue; } PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next optional token: positive integer or a '+'. unsigned Min = 1; unsigned Max = 1; if (PH.Next(Min)) { PH.Advance(); // A positive integer can be followed by a '+' meaning min // or more, or by a '-' meaning a range from min to max. if (PH.Next("+")) { Max = Directive::MaxCount; PH.Advance(); } else if (PH.Next("-")) { PH.Advance(); if (!PH.Next(Max) || Max < Min) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_invalid_range) << KindStr; continue; } PH.Advance(); } else { Max = Min; } } else if (PH.Next("+")) { // '+' on its own means "1 or more". Max = Directive::MaxCount; PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next token: {{ if (!PH.Next("{{")) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_start) << KindStr; continue; } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin // Search for token: }} if (!PH.SearchClosingBrace("{{", "}}")) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_end) << KindStr; continue; } const char* const ContentEnd = PH.P; // mark content end PH.Advance(); // Build directive text; convert \n to newlines. std::string Text; StringRef NewlineStr = "\\n"; StringRef Content(ContentBegin, ContentEnd-ContentBegin); size_t CPos = 0; size_t FPos; while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) { Text += Content.substr(CPos, FPos-CPos); Text += '\n'; CPos = FPos + NewlineStr.size(); } if (Text.empty()) Text.assign(ContentBegin, ContentEnd); // Check that regex directives contain at least one regex. if (RegexKind && Text.find("{{") == StringRef::npos) { Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), diag::err_verify_missing_regex) << Text; return false; } // Construct new directive. Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max); std::string Error; if (D->isValid(Error)) { DL->push_back(D); FoundDirective = true; } else { Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), diag::err_verify_invalid_content) << KindStr << Error; } } return FoundDirective; }
inline void debug_ast(AST_Node* node, std::string ind, Env* env) { if (node == 0) return; if (ind == "") std::cerr << "####################################################################\n"; if (dynamic_cast<Bubble*>(node)) { Bubble* bubble = dynamic_cast<Bubble*>(node); std::cerr << ind << "Bubble " << bubble; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << bubble->tabs(); std::cerr << std::endl; debug_ast(bubble->node(), ind + " ", env); } else if (dynamic_cast<Trace*>(node)) { Trace* trace = dynamic_cast<Trace*>(node); std::cerr << ind << "Trace " << trace; std::cerr << " (" << pstate_source_position(node) << ")" << " [name:" << trace->name() << "]" << std::endl; debug_ast(trace->block(), ind + " ", env); } else if (dynamic_cast<At_Root_Block*>(node)) { At_Root_Block* root_block = dynamic_cast<At_Root_Block*>(node); std::cerr << ind << "At_Root_Block " << root_block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << root_block->tabs(); std::cerr << std::endl; debug_ast(root_block->expression(), ind + ":", env); debug_ast(root_block->block(), ind + " ", env); } else if (dynamic_cast<CommaSequence_Selector*>(node)) { CommaSequence_Selector* selector = dynamic_cast<CommaSequence_Selector*>(node); std::cerr << ind << "CommaSequence_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [@media:" << selector->media_block() << "]"; std::cerr << (selector->is_invisible() ? " [INVISIBLE]": " -"); std::cerr << (selector->has_placeholder() ? " [PLACEHOLDER]": " -"); std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); } // } else if (dynamic_cast<Expression*>(node)) { // Expression* expression = dynamic_cast<Expression*>(node); // std::cerr << ind << "Expression " << expression << " " << expression->concrete_type() << std::endl; } else if (dynamic_cast<Parent_Selector*>(node)) { Parent_Selector* selector = dynamic_cast<Parent_Selector*>(node); std::cerr << ind << "Parent_Selector " << selector; // if (selector->not_selector()) cerr << " [in_declaration]"; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [" << (selector->is_real_parent_ref() ? "REAL" : "FAKE") << "]"; std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; // debug_ast(selector->selector(), ind + "->", env); } else if (dynamic_cast<Sequence_Selector*>(node)) { Sequence_Selector* selector = dynamic_cast<Sequence_Selector*>(node); std::cerr << ind << "Sequence_Selector " << selector << " (" << pstate_source_position(node) << ")" << " <" << selector->hash() << ">" << " [length:" << longToHex(selector->length()) << "]" << " [weight:" << longToHex(selector->specificity()) << "]" << " [@media:" << selector->media_block() << "]" << (selector->is_invisible() ? " [INVISIBLE]": " -") << (selector->has_placeholder() ? " [PLACEHOLDER]": " -") << (selector->is_optional() ? " [is_optional]": " -") << (selector->has_parent_ref() ? " [has parent]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << (selector->has_line_break() ? " [line-break]": " -") << " -- "; std::string del; switch (selector->combinator()) { case Sequence_Selector::PARENT_OF: del = ">"; break; case Sequence_Selector::PRECEDES: del = "~"; break; case Sequence_Selector::ADJACENT_TO: del = "+"; break; case Sequence_Selector::ANCESTOR_OF: del = " "; break; case Sequence_Selector::REFERENCE: del = "//"; break; } // if (del = "/") del += selector->reference()->perform(&to_string) + "/"; std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; debug_ast(selector->head(), ind + " " /* + "[" + del + "]" */, env); if (selector->tail()) { debug_ast(selector->tail(), ind + "{" + del + "}", env); } else if(del != " ") { std::cerr << ind << " |" << del << "| {trailing op}" << std::endl; } SourcesSet set = selector->sources(); // debug_sources_set(set, ind + " @--> "); } else if (dynamic_cast<SimpleSequence_Selector*>(node)) { SimpleSequence_Selector* selector = dynamic_cast<SimpleSequence_Selector*>(node); std::cerr << ind << "SimpleSequence_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " [weight:" << longToHex(selector->specificity()) << "]"; std::cerr << " [@media:" << selector->media_block() << "]"; std::cerr << (selector->extended() ? " [extended]": " -"); std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">" << std::endl; for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Wrapped_Selector*>(node)) { Wrapped_Selector* selector = dynamic_cast<Wrapped_Selector*>(node); std::cerr << ind << "Wrapped_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; debug_ast(selector->selector(), ind + " () ", env); } else if (dynamic_cast<Pseudo_Selector*>(node)) { Pseudo_Selector* selector = dynamic_cast<Pseudo_Selector*>(node); std::cerr << ind << "Pseudo_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; debug_ast(selector->expression(), ind + " <= ", env); } else if (dynamic_cast<Attribute_Selector*>(node)) { Attribute_Selector* selector = dynamic_cast<Attribute_Selector*>(node); std::cerr << ind << "Attribute_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; debug_ast(selector->value(), ind + "[" + selector->matcher() + "] ", env); } else if (dynamic_cast<Class_Selector*>(node)) { Class_Selector* selector = dynamic_cast<Class_Selector*>(node); std::cerr << ind << "Class_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; } else if (dynamic_cast<Id_Selector*>(node)) { Id_Selector* selector = dynamic_cast<Id_Selector*>(node); std::cerr << ind << "Id_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << std::endl; } else if (dynamic_cast<Element_Selector*>(node)) { Element_Selector* selector = dynamic_cast<Element_Selector*>(node); std::cerr << ind << "Element_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <" << selector->hash() << ">"; std::cerr << " <<" << selector->ns_name() << ">>"; std::cerr << (selector->is_optional() ? " [is_optional]": " -"); std::cerr << (selector->has_parent_ref() ? " [has-parent]": " -"); std::cerr << (selector->has_line_break() ? " [line-break]": " -"); std::cerr << (selector->has_line_feed() ? " [line-feed]": " -"); std::cerr << " <" << prettyprint(selector->pstate().token.ws_before()) << ">"; std::cerr << std::endl; } else if (dynamic_cast<Placeholder_Selector*>(node)) { Placeholder_Selector* selector = dynamic_cast<Placeholder_Selector*>(node); std::cerr << ind << "Placeholder_Selector [" << selector->ns_name() << "] " << selector << " <" << selector->hash() << ">" << " [@media:" << selector->media_block() << "]" << (selector->is_optional() ? " [is_optional]": " -") << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; } else if (dynamic_cast<Simple_Selector*>(node)) { Simple_Selector* selector = dynamic_cast<Simple_Selector*>(node); std::cerr << ind << "Simple_Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; } else if (dynamic_cast<Selector_Schema*>(node)) { Selector_Schema* selector = dynamic_cast<Selector_Schema*>(node); std::cerr << ind << "Selector_Schema " << selector; std::cerr << " (" << pstate_source_position(node) << ")" << (selector->at_root() && selector->at_root() ? " [@ROOT]" : "") << " [@media:" << selector->media_block() << "]" << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; debug_ast(selector->contents(), ind + " "); // for(auto i : selector->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Selector*>(node)) { Selector* selector = dynamic_cast<Selector*>(node); std::cerr << ind << "Selector " << selector; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << std::endl; } else if (dynamic_cast<Media_Query_Expression*>(node)) { Media_Query_Expression* block = dynamic_cast<Media_Query_Expression*>(node); std::cerr << ind << "Media_Query_Expression " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (block->is_interpolated() ? " [is_interpolated]": " -") << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); } else if (dynamic_cast<Media_Query*>(node)) { Media_Query* block = dynamic_cast<Media_Query*>(node); std::cerr << ind << "Media_Query " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (block->is_negated() ? " [is_negated]": " -") << (block->is_restricted() ? " [is_restricted]": " -") << std::endl; debug_ast(block->media_type(), ind + " "); for(auto i : block->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Media_Block*>(node)) { Media_Block* block = dynamic_cast<Media_Block*>(node); std::cerr << ind << "Media_Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->media_queries(), ind + " =@ "); if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Supports_Block*>(node)) { Supports_Block* block = dynamic_cast<Supports_Block*>(node); std::cerr << ind << "Supports_Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->condition(), ind + " =@ "); debug_ast(block->block(), ind + " <>"); } else if (dynamic_cast<Supports_Operator*>(node)) { Supports_Operator* block = dynamic_cast<Supports_Operator*>(node); std::cerr << ind << "Supports_Operator " << block; std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->left(), ind + " left) "); debug_ast(block->right(), ind + " right) "); } else if (dynamic_cast<Supports_Negation*>(node)) { Supports_Negation* block = dynamic_cast<Supports_Negation*>(node); std::cerr << ind << "Supports_Negation " << block; std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->condition(), ind + " condition) "); } else if (dynamic_cast<At_Root_Query*>(node)) { At_Root_Query* block = dynamic_cast<At_Root_Query*>(node); std::cerr << ind << "At_Root_Query " << block; std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); } else if (dynamic_cast<Supports_Declaration*>(node)) { Supports_Declaration* block = dynamic_cast<Supports_Declaration*>(node); std::cerr << ind << "Supports_Declaration " << block; std::cerr << " (" << pstate_source_position(node) << ")" << std::endl; debug_ast(block->feature(), ind + " feature) "); debug_ast(block->value(), ind + " value) "); } else if (dynamic_cast<Block*>(node)) { Block* root_block = dynamic_cast<Block*>(node); std::cerr << ind << "Block " << root_block; std::cerr << " (" << pstate_source_position(node) << ")"; if (root_block->is_root()) std::cerr << " [root]"; std::cerr << " " << root_block->tabs() << std::endl; if (root_block->block()) for(auto i : root_block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Warning*>(node)) { Warning* block = dynamic_cast<Warning*>(node); std::cerr << ind << "Warning " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->message(), ind + " : "); } else if (dynamic_cast<Error*>(node)) { Error* block = dynamic_cast<Error*>(node); std::cerr << ind << "Error " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; } else if (dynamic_cast<Debug*>(node)) { Debug* block = dynamic_cast<Debug*>(node); std::cerr << ind << "Debug " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->value(), ind + " "); } else if (dynamic_cast<Comment*>(node)) { Comment* block = dynamic_cast<Comment*>(node); std::cerr << ind << "Comment " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << " <" << prettyprint(block->pstate().token.ws_before()) << ">" << std::endl; debug_ast(block->text(), ind + "// ", env); } else if (dynamic_cast<If*>(node)) { If* block = dynamic_cast<If*>(node); std::cerr << ind << "If " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->predicate(), ind + " = "); debug_ast(block->block(), ind + " <>"); debug_ast(block->alternative(), ind + " ><"); } else if (dynamic_cast<Return*>(node)) { Return* block = dynamic_cast<Return*>(node); std::cerr << ind << "Return " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; } else if (dynamic_cast<Extension*>(node)) { Extension* block = dynamic_cast<Extension*>(node); std::cerr << ind << "Extension " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->selector(), ind + "-> ", env); } else if (dynamic_cast<Content*>(node)) { Content* block = dynamic_cast<Content*>(node); std::cerr << ind << "Content " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [@media:" << block->media_block() << "]"; std::cerr << " " << block->tabs() << std::endl; } else if (dynamic_cast<Import_Stub*>(node)) { Import_Stub* block = dynamic_cast<Import_Stub*>(node); std::cerr << ind << "Import_Stub " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << block->imp_path() << "] "; std::cerr << " " << block->tabs() << std::endl; } else if (dynamic_cast<Import*>(node)) { Import* block = dynamic_cast<Import*>(node); std::cerr << ind << "Import " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; // std::vector<std::string> files_; for (auto imp : block->urls()) debug_ast(imp, ind + "@: ", env); debug_ast(block->media_queries(), ind + "@@ "); } else if (dynamic_cast<Assignment*>(node)) { Assignment* block = dynamic_cast<Assignment*>(node); std::cerr << ind << "Assignment " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " <<" << block->variable() << ">> " << block->tabs() << std::endl; debug_ast(block->value(), ind + "=", env); } else if (dynamic_cast<Declaration*>(node)) { Declaration* block = dynamic_cast<Declaration*>(node); std::cerr << ind << "Declaration " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->property(), ind + " prop: ", env); debug_ast(block->value(), ind + " value: ", env); debug_ast(block->block(), ind + " ", env); } else if (dynamic_cast<Keyframe_Rule*>(node)) { Keyframe_Rule* has_block = dynamic_cast<Keyframe_Rule*>(node); std::cerr << ind << "Keyframe_Rule " << has_block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << has_block->tabs() << std::endl; if (has_block->selector()) debug_ast(has_block->selector(), ind + "@"); if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Directive*>(node)) { Directive* block = dynamic_cast<Directive*>(node); std::cerr << ind << "Directive " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << block->keyword() << "] " << block->tabs() << std::endl; debug_ast(block->selector(), ind + "~", env); debug_ast(block->value(), ind + "+", env); if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Each*>(node)) { Each* block = dynamic_cast<Each*>(node); std::cerr << ind << "Each " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<For*>(node)) { For* block = dynamic_cast<For*>(node); std::cerr << ind << "For " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<While*>(node)) { While* block = dynamic_cast<While*>(node); std::cerr << ind << "While " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << block->tabs() << std::endl; if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Definition*>(node)) { Definition* block = dynamic_cast<Definition*>(node); std::cerr << ind << "Definition " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [name: " << block->name() << "] "; std::cerr << " [type: " << (block->type() == Sass::Definition::Type::MIXIN ? "Mixin " : "Function ") << "] "; // this seems to lead to segfaults some times? // std::cerr << " [signature: " << block->signature() << "] "; std::cerr << " [native: " << block->native_function() << "] "; std::cerr << " " << block->tabs() << std::endl; debug_ast(block->parameters(), ind + " params: ", env); if (block->block()) debug_ast(block->block(), ind + " ", env); } else if (dynamic_cast<Mixin_Call*>(node)) { Mixin_Call* block = dynamic_cast<Mixin_Call*>(node); std::cerr << ind << "Mixin_Call " << block << " " << block->tabs(); std::cerr << " [" << block->name() << "]"; std::cerr << " [has_content: " << block->has_content() << "] " << std::endl; debug_ast(block->arguments(), ind + " args: "); if (block->block()) debug_ast(block->block(), ind + " ", env); } else if (Ruleset* ruleset = dynamic_cast<Ruleset*>(node)) { std::cerr << ind << "Ruleset " << ruleset; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [indent: " << ruleset->tabs() << "]"; std::cerr << (ruleset->is_invisible() ? " [INVISIBLE]" : ""); std::cerr << (ruleset->at_root() ? " [@ROOT]" : ""); std::cerr << (ruleset->is_root() ? " [root]" : ""); std::cerr << std::endl; debug_ast(ruleset->selector(), ind + ">"); debug_ast(ruleset->block(), ind + " "); } else if (dynamic_cast<Block*>(node)) { Block* block = dynamic_cast<Block*>(node); std::cerr << ind << "Block " << block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << (block->is_invisible() ? " [INVISIBLE]" : ""); std::cerr << " [indent: " << block->tabs() << "]" << std::endl; for(auto i : block->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Textual*>(node)) { Textual* expression = dynamic_cast<Textual*>(node); std::cerr << ind << "Textual "; if (expression->type() == Textual::NUMBER) std::cerr << " [NUMBER]"; else if (expression->type() == Textual::PERCENTAGE) std::cerr << " [PERCENTAGE]"; else if (expression->type() == Textual::DIMENSION) std::cerr << " [DIMENSION]"; else if (expression->type() == Textual::HEX) std::cerr << " [HEX]"; std::cerr << expression << " [" << expression->value() << "]"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; if (expression->is_delayed()) std::cerr << " [delayed]"; std::cerr << std::endl; } else if (dynamic_cast<Variable*>(node)) { Variable* expression = dynamic_cast<Variable*>(node); std::cerr << ind << "Variable " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->name() << "]" << std::endl; std::string name(expression->name()); if (env && env->has(name)) debug_ast(static_cast<Expression*>((*env)[name]), ind + " -> ", env); } else if (dynamic_cast<Function_Call_Schema*>(node)) { Function_Call_Schema* expression = dynamic_cast<Function_Call_Schema*>(node); std::cerr << ind << "Function_Call_Schema " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << "" << std::endl; debug_ast(expression->name(), ind + "name: ", env); debug_ast(expression->arguments(), ind + " args: ", env); } else if (dynamic_cast<Function_Call*>(node)) { Function_Call* expression = dynamic_cast<Function_Call*>(node); std::cerr << ind << "Function_Call " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->name() << "]"; if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << std::endl; debug_ast(expression->arguments(), ind + " args: ", env); } else if (dynamic_cast<Arguments*>(node)) { Arguments* expression = dynamic_cast<Arguments*>(node); std::cerr << ind << "Arguments " << expression; if (expression->is_delayed()) std::cerr << " [delayed]"; std::cerr << " (" << pstate_source_position(node) << ")"; if (expression->has_named_arguments()) std::cerr << " [has_named_arguments]"; if (expression->has_rest_argument()) std::cerr << " [has_rest_argument]"; if (expression->has_keyword_argument()) std::cerr << " [has_keyword_argument]"; std::cerr << std::endl; for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Argument*>(node)) { Argument* expression = dynamic_cast<Argument*>(node); std::cerr << ind << "Argument " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->value() << "]"; std::cerr << " [name: " << expression->name() << "] "; std::cerr << " [rest: " << expression->is_rest_argument() << "] "; std::cerr << " [keyword: " << expression->is_keyword_argument() << "] " << std::endl; debug_ast(expression->value(), ind + " value: ", env); } else if (dynamic_cast<Parameters*>(node)) { Parameters* expression = dynamic_cast<Parameters*>(node); std::cerr << ind << "Parameters " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [has_optional: " << expression->has_optional_parameters() << "] "; std::cerr << " [has_rest: " << expression->has_rest_parameter() << "] "; std::cerr << std::endl; for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Parameter*>(node)) { Parameter* expression = dynamic_cast<Parameter*>(node); std::cerr << ind << "Parameter " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [name: " << expression->name() << "] "; std::cerr << " [default: " << expression->default_value() << "] "; std::cerr << " [rest: " << expression->is_rest_parameter() << "] " << std::endl; } else if (dynamic_cast<Unary_Expression*>(node)) { Unary_Expression* expression = dynamic_cast<Unary_Expression*>(node); std::cerr << ind << "Unary_Expression " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " [delayed: " << expression->is_delayed() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->type() << "]" << std::endl; debug_ast(expression->operand(), ind + " operand: ", env); } else if (dynamic_cast<Binary_Expression*>(node)) { Binary_Expression* expression = dynamic_cast<Binary_Expression*>(node); std::cerr << ind << "Binary_Expression " << expression; if (expression->is_interpolant()) std::cerr << " [is interpolant] "; if (expression->is_left_interpolant()) std::cerr << " [left interpolant] "; if (expression->is_right_interpolant()) std::cerr << " [right interpolant] "; std::cerr << " [delayed: " << expression->is_delayed() << "] "; std::cerr << " [ws_before: " << expression->op().ws_before << "] "; std::cerr << " [ws_after: " << expression->op().ws_after << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << expression->type_name() << "]" << std::endl; debug_ast(expression->left(), ind + " left: ", env); debug_ast(expression->right(), ind + " right: ", env); } else if (dynamic_cast<Map*>(node)) { Map* expression = dynamic_cast<Map*>(node); std::cerr << ind << "Map " << expression; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [Hashed]" << std::endl; for (auto i : expression->elements()) { debug_ast(i.first, ind + " key: "); debug_ast(i.second, ind + " val: "); } } else if (dynamic_cast<List*>(node)) { List* expression = dynamic_cast<List*>(node); std::cerr << ind << "List " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " (" << expression->length() << ") " << (expression->separator() == SASS_COMMA ? "Comma " : expression->separator() == SASS_HASH ? "Map" : "Space ") << " [delayed: " << expression->is_delayed() << "] " << " [interpolant: " << expression->is_interpolant() << "] " << " [listized: " << expression->from_selector() << "] " << " [arglist: " << expression->is_arglist() << "] " << " [hash: " << expression->hash() << "] " << std::endl; for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Content*>(node)) { Content* expression = dynamic_cast<Content*>(node); std::cerr << ind << "Content " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [@media:" << expression->media_block() << "]"; std::cerr << " [Statement]" << std::endl; } else if (dynamic_cast<Boolean*>(node)) { Boolean* expression = dynamic_cast<Boolean*>(node); std::cerr << ind << "Boolean " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " [" << expression->value() << "]" << std::endl; } else if (dynamic_cast<Color*>(node)) { Color* expression = dynamic_cast<Color*>(node); std::cerr << ind << "Color " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [delayed: " << expression->is_delayed() << "] "; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " [" << expression->r() << ":" << expression->g() << ":" << expression->b() << "@" << expression->a() << "]" << std::endl; } else if (dynamic_cast<Number*>(node)) { Number* expression = dynamic_cast<Number*>(node); std::cerr << ind << "Number " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [interpolant: " << expression->is_interpolant() << "] "; std::cerr << " [" << expression->value() << expression->unit() << "]" << " [hash: " << expression->hash() << "] " << std::endl; } else if (dynamic_cast<String_Quoted*>(node)) { String_Quoted* expression = dynamic_cast<String_Quoted*>(node); std::cerr << ind << "String_Quoted " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << prettyprint(expression->value()) << "]"; if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; if (expression->quote_mark()) std::cerr << " [quote_mark: " << expression->quote_mark() << "]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; } else if (dynamic_cast<String_Constant*>(node)) { String_Constant* expression = dynamic_cast<String_Constant*>(node); std::cerr << ind << "String_Constant " << expression; if (expression->concrete_type()) { std::cerr << " " << expression->concrete_type(); } std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " [" << prettyprint(expression->value()) << "]"; if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; } else if (dynamic_cast<String_Schema*>(node)) { String_Schema* expression = dynamic_cast<String_Schema*>(node); std::cerr << ind << "String_Schema " << expression; std::cerr << " " << expression->concrete_type(); if (expression->is_delayed()) std::cerr << " [delayed]"; if (expression->is_interpolant()) std::cerr << " [is interpolant]"; if (expression->has_interpolant()) std::cerr << " [has interpolant]"; if (expression->is_left_interpolant()) std::cerr << " [left interpolant] "; if (expression->is_right_interpolant()) std::cerr << " [right interpolant] "; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; for(auto i : expression->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<String*>(node)) { String* expression = dynamic_cast<String*>(node); std::cerr << ind << "String " << expression; std::cerr << " " << expression->concrete_type(); std::cerr << " (" << pstate_source_position(node) << ")"; if (expression->is_interpolant()) std::cerr << " [interpolant]"; std::cerr << " <" << prettyprint(expression->pstate().token.ws_before()) << ">" << std::endl; } else if (dynamic_cast<Expression*>(node)) { Expression* expression = dynamic_cast<Expression*>(node); std::cerr << ind << "Expression " << expression; std::cerr << " (" << pstate_source_position(node) << ")"; switch (expression->concrete_type()) { case Expression::Concrete_Type::NONE: std::cerr << " [NONE]"; break; case Expression::Concrete_Type::BOOLEAN: std::cerr << " [BOOLEAN]"; break; case Expression::Concrete_Type::NUMBER: std::cerr << " [NUMBER]"; break; case Expression::Concrete_Type::COLOR: std::cerr << " [COLOR]"; break; case Expression::Concrete_Type::STRING: std::cerr << " [STRING]"; break; case Expression::Concrete_Type::LIST: std::cerr << " [LIST]"; break; case Expression::Concrete_Type::MAP: std::cerr << " [MAP]"; break; case Expression::Concrete_Type::SELECTOR: std::cerr << " [SELECTOR]"; break; case Expression::Concrete_Type::NULL_VAL: std::cerr << " [NULL_VAL]"; break; case Expression::Concrete_Type::C_WARNING: std::cerr << " [C_WARNING]"; break; case Expression::Concrete_Type::C_ERROR: std::cerr << " [C_ERROR]"; break; case Expression::Concrete_Type::NUM_TYPES: std::cerr << " [NUM_TYPES]"; break; } std::cerr << std::endl; } else if (dynamic_cast<Has_Block*>(node)) { Has_Block* has_block = dynamic_cast<Has_Block*>(node); std::cerr << ind << "Has_Block " << has_block; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << has_block->tabs() << std::endl; if (has_block->block()) for(auto i : has_block->block()->elements()) { debug_ast(i, ind + " ", env); } } else if (dynamic_cast<Statement*>(node)) { Statement* statement = dynamic_cast<Statement*>(node); std::cerr << ind << "Statement " << statement; std::cerr << " (" << pstate_source_position(node) << ")"; std::cerr << " " << statement->tabs() << std::endl; } if (ind == "") std::cerr << "####################################################################\n"; }
/// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// /// Returns true if any valid directives were found. static bool ParseDirective(StringRef S, ExpectedData &ED, SourceManager &SM, SourceLocation Pos, DiagnosticsEngine &Diags) { // A single comment may contain multiple directives. bool FoundDirective = false; for (ParseHelper PH(S); !PH.Done();) { // Search for token: expected if (!PH.Search("expected")) break; PH.Advance(); // Next token: - if (!PH.Next("-")) continue; PH.Advance(); // Next token: { error | warning | note } DirectiveList* DL = NULL; if (PH.Next("error")) DL = &ED.Errors; else if (PH.Next("warning")) DL = &ED.Warnings; else if (PH.Next("note")) DL = &ED.Notes; else continue; PH.Advance(); // Default directive kind. bool RegexKind = false; const char* KindStr = "string"; // Next optional token: - if (PH.Next("-re")) { PH.Advance(); RegexKind = true; KindStr = "regex"; } // Next optional token: @ SourceLocation ExpectedLoc; if (!PH.Next("@")) { ExpectedLoc = Pos; } else { PH.Advance(); unsigned Line = 0; bool FoundPlus = PH.Next("+"); if (FoundPlus || PH.Next("-")) { // Relative to current line. PH.Advance(); bool Invalid = false; unsigned ExpectedLine = SM.getSpellingLineNumber(Pos, &Invalid); if (!Invalid && PH.Next(Line) && (FoundPlus || Line < ExpectedLine)) { if (FoundPlus) ExpectedLine += Line; else ExpectedLine -= Line; ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), ExpectedLine, 1); } } else { // Absolute line number. if (PH.Next(Line) && Line > 0) ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1); } if (ExpectedLoc.isInvalid()) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_line) << KindStr; continue; } PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next optional token: positive integer or a '+'. unsigned Min = 1; unsigned Max = 1; if (PH.Next(Min)) { PH.Advance(); // A positive integer can be followed by a '+' meaning min // or more, or by a '-' meaning a range from min to max. if (PH.Next("+")) { Max = Directive::MaxCount; PH.Advance(); } else if (PH.Next("-")) { PH.Advance(); if (!PH.Next(Max) || Max < Min) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_invalid_range) << KindStr; continue; } PH.Advance(); } else { Max = Min; } } else if (PH.Next("+")) { // '+' on its own means "1 or more". Max = Directive::MaxCount; PH.Advance(); } // Skip optional whitespace. PH.SkipWhitespace(); // Next token: {{ if (!PH.Next("{{")) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_start) << KindStr; continue; } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin // Search for token: }} if (!PH.Search("}}")) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_end) << KindStr; continue; } const char* const ContentEnd = PH.P; // mark content end PH.Advance(); // Build directive text; convert \n to newlines. std::string Text; StringRef NewlineStr = "\\n"; StringRef Content(ContentBegin, ContentEnd-ContentBegin); size_t CPos = 0; size_t FPos; while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) { Text += Content.substr(CPos, FPos-CPos); Text += '\n'; CPos = FPos + NewlineStr.size(); } if (Text.empty()) Text.assign(ContentBegin, ContentEnd); // Construct new directive. Directive *D = Directive::create(RegexKind, Pos, ExpectedLoc, Text, Min, Max); std::string Error; if (D->isValid(Error)) { DL->push_back(D); FoundDirective = true; } else { Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), diag::err_verify_invalid_content) << KindStr << Error; } } return FoundDirective; }