Home | History | Annotate | Download | only in bookmaker
      1 /*
      2  * Copyright 2018 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef mdOut_DEFINED
      9 #define mdOut_DEFINED
     10 
     11 #include "parserCommon.h"
     12 
     13 class IncludeParser;
     14 
     15 class MdOut : public ParserCommon {
     16 public:
     17     struct SubtopicDescriptions {
     18         string fSingular;
     19         string fPlural;
     20         string fOneLiner;
     21         string fDetails;
     22     };
     23 
     24     MdOut(BmhParser& bmh, IncludeParser& inc) : ParserCommon()
     25         , fBmhParser(bmh)
     26         , fIncludeParser(inc) {
     27         this->reset();
     28         this->addPopulators();
     29         fBmhParser.setUpGlobalSubstitutes();
     30         fNames = &fBmhParser.fGlobalNames;
     31     }
     32 
     33     bool buildReferences(const char* docDir, const char* mdOutDirOrFile);
     34     bool buildStatus(const char* docDir, const char* mdOutDir);
     35     void checkAnchors();
     36 
     37 private:
     38     enum class TableState {
     39         kNone,
     40         kRow,
     41         kColumn,
     42     };
     43 
     44     struct AnchorDef {
     45         string fDef;
     46         MarkType fMarkType;
     47     };
     48 
     49     struct DefinedState {
     50         DefinedState(const MdOut& mdOut, const char* refStart, const char* refEnd,
     51                 Resolvable resolvable)
     52             : fBmhParser(&mdOut.fBmhParser)
     53             , fNames(mdOut.fNames)
     54             , fGlobals(&mdOut.fBmhParser.fGlobalNames)
     55             , fLastDef(mdOut.fLastDef)
     56             , fMethod(mdOut.fMethod)
     57             , fSubtopic(mdOut.fSubtopic)
     58             , fRoot(mdOut.fRoot)
     59             , fRefStart(refStart)
     60             , fRefEnd(refEnd)
     61             , fResolvable(resolvable)
     62             , fInProgress(mdOut.fInProgress) {
     63             TextParser matrixParser(fLastDef->fFileName, refStart, refEnd, fLastDef->fLineCount);
     64             const char* bracket = matrixParser.anyOf("|=\n");
     65             fInMatrix = bracket && ('|' == bracket[0] || '=' == bracket[0]);
     66         }
     67 
     68         void backup() {
     69             fPriorWord = fBack2Word;
     70             fPriorLink = "";
     71             fPriorSeparator = "";
     72             fSeparator = fBack2Separator;
     73         }
     74 
     75         bool findEnd(const char* start) {
     76             if (fEnd < fRefEnd && '~' == fEnd[0]) {
     77                 ++fEnd;
     78             }
     79             do {
     80                 while (fEnd < fRefEnd && (isalnum(fEnd[0]) || '-' == fEnd[0] || '_' == fEnd[0])) {
     81                     ++fEnd;
     82                 }
     83                 if (fEnd + 1 >= fRefEnd || '/' != fEnd[0] || start == fEnd || !isalpha(fEnd[-1])
     84                         || !isalpha(fEnd[1])) {
     85                     break;  // stop unless pattern is xxx/xxx as in I/O
     86                 }
     87                 ++fEnd; // skip slash
     88             } while (true);
     89             while (start != fEnd && '-' == fEnd[-1]) {
     90                 --fEnd;
     91             }
     92             return start == fEnd;
     93         }
     94 
     95         bool findLink(string ref, string* linkPtr, bool addParens);
     96         bool findLink(string ref, string* linkPtr, unordered_map<string, Definition*>& map);
     97         bool hasWordSpace(string wordSpace) const;
     98         void setLink();
     99 
    100         string nextSeparator(const char* start) {
    101             fBack2Separator = fPriorSeparator;
    102             fPriorSeparator = fSeparator;
    103             fEnd = start;
    104             return fBack2Separator;
    105         }
    106 
    107         const char* nextWord() {
    108             fBack2Word = fPriorWord;
    109             fPriorWord = fWord;
    110             fPriorLink = fLink;
    111             return fEnd;
    112         }
    113 
    114         bool phraseContinues(string phrase, string* priorWord, string* priorLink) const;
    115 
    116         void setLower() {
    117             fAddParens = false;
    118             bool allLower = std::all_of(fWord.begin(), fWord.end(), [](char c) {
    119                 return islower(c);
    120             });
    121             bool hasParens = fEnd + 2 <= fRefEnd && "()" == string(fEnd, 2);
    122             if (hasParens) {
    123                 if (allLower) {
    124                     fWord += "()";
    125                     fEnd += 2;
    126                 }
    127             } else if (allLower) {
    128                 fAddParens = true;
    129             }
    130         }
    131 
    132         bool setPriorSpaceWord(const char** startPtr) {
    133             if (!fPriorSpace) {
    134                 return false;
    135             }
    136             string phrase = fPriorWord + fWord;
    137             if (this->phraseContinues(phrase, &fPriorWord, &fPriorLink)) {
    138                 *startPtr = fEnd;
    139                 return true;
    140             }
    141             fPriorWord = fPriorWord.substr(0, fPriorWord.length() - 1);
    142             return false;
    143         }
    144 
    145         void skipParens() {
    146             if ("()" == fSeparator.substr(0, 2)) {
    147                 string funcRef = fPriorWord + "()";
    148                 if (this->findLink(funcRef, &fPriorLink, false)) {
    149                     fPriorWord = funcRef;
    150                     fSeparator = fSeparator.substr(2);
    151                 }
    152             }
    153         }
    154 
    155         const char* skipWhiteSpace() {
    156             const char* start = fSeparatorStart;
    157             bool whiteSpace = start < fRefEnd && ' ' >= start[0];
    158             while (start < fRefEnd && !isalpha(start[0]) && '~' != start[0]) {
    159                 whiteSpace &= ' ' >= start[0];
    160                 ++start;
    161             }
    162             fPriorSpace = false;
    163             fSeparator = string(fSeparatorStart, start - fSeparatorStart);
    164             if ("" != fPriorWord && whiteSpace) {
    165                 string wordSpace = fPriorWord + ' ';
    166                 if (this->hasWordSpace(wordSpace)) {
    167                     fPriorWord = wordSpace;
    168                     fPriorSpace = true;
    169                 }
    170             }
    171             return start;
    172         }
    173 
    174         string fRef;
    175         string fBack2Word;
    176         string fBack2Separator;
    177         string fPriorWord;
    178         string fPriorLink;
    179         string fPriorSeparator;
    180         string fWord;
    181         string fLink;
    182         string fSeparator;
    183         string fMethodName;
    184         BmhParser* fBmhParser;
    185         const NameMap* fNames;
    186         const NameMap* fGlobals;
    187         const Definition* fLastDef;
    188         const Definition* fMethod;
    189         const Definition* fSubtopic;
    190         const Definition* fPriorDef;
    191         const RootDefinition* fRoot;
    192         const char* fSeparatorStart;
    193         const char* fRefStart;
    194         const char* fRefEnd;
    195         const char* fEnd;
    196         Resolvable fResolvable;
    197         bool fAddParens;
    198         bool fInMatrix;
    199         bool fInProgress;
    200         bool fPriorSpace;
    201     };
    202 
    203     void addCodeBlock(const Definition* def, string& str) const;
    204     void addPopulators();
    205     string addReferences(const char* start, const char* end, Resolvable );
    206     string anchorDef(string def, string name);
    207     string anchorLocalRef(string ref, string name);
    208     string anchorRef(string def, string name);
    209     bool buildRefFromFile(const char* fileName, const char* outDir);
    210     bool checkParamReturnBody(const Definition* def);
    211     Definition* checkParentsForMatch(Definition* test, string ref) const;
    212     void childrenOut(Definition* def, const char* contentStart);
    213     Definition* csParent();
    214     const Definition* findParamType();
    215     string getMemberTypeName(const Definition* def, string* memberType);
    216     static bool HasDetails(const Definition* def);
    217     void htmlOut(string );
    218     bool isDefined(DefinedState& s);
    219     const Definition* isDefined(const TextParser& , Resolvable );
    220     string linkName(const Definition* ) const;
    221     void markTypeOut(Definition* , const Definition** prior);
    222     void mdHeaderOut(int depth) { mdHeaderOutLF(depth, 2); }
    223     void mdHeaderOutLF(int depth, int lf);
    224     void parameterHeaderOut(TextParser& paramParser, const Definition** prior, Definition* def);
    225     void parameterTrailerOut();
    226     bool parseFromFile(const char* path) override { return true; }
    227     void populateOne(Definition* def,
    228             unordered_map<string, RootDefinition::SubtopicContents>& populator);
    229     void populateTables(const Definition* def, RootDefinition* );
    230 
    231     SubtopicDescriptions& populator(string key) {
    232         auto entry = fPopulators.find(key);
    233         // FIXME: this should have been detected earlier
    234         SkASSERT(fPopulators.end() != entry);
    235         return entry->second;
    236     }
    237 
    238     void reset() override {
    239         INHERITED::resetCommon();
    240         fNames = nullptr;
    241         fEnumClass = nullptr;
    242         fMethod = nullptr;
    243         fRoot = nullptr;
    244         fSubtopic = nullptr;
    245         fLastParam = nullptr;
    246         fTableState = TableState::kNone;
    247         fAddRefFailed = false;
    248         fHasFiddle = false;
    249         fInDescription = false;
    250         fInList = false;
    251         fResolveAndIndent = false;
    252         fLiteralAndIndent = false;
    253         fLastDef = nullptr;
    254         fParamEnd = nullptr;
    255         fInProgress = false;
    256     }
    257 
    258     Resolvable resolvable(const Definition* definition) const {
    259         MarkType markType = definition->fMarkType;
    260         if (MarkType::kCode == markType) {
    261             for (auto child : definition->fChildren) {
    262                 if (MarkType::kLiteral == child->fMarkType) {
    263                     return Resolvable::kLiteral;
    264                 }
    265             }
    266         }
    267         if ((MarkType::kExample == markType
    268                 || MarkType::kFunction == markType) && fHasFiddle) {
    269             return Resolvable::kNo;
    270         }
    271         return BmhParser::kMarkProps[(int) markType].fResolve;
    272     }
    273 
    274     void resolveOut(const char* start, const char* end, Resolvable );
    275     void returnHeaderOut(const Definition** prior, Definition* def);
    276     void rowOut(string col1, const Definition* col2);
    277     void rowOut(const char * name, string description, bool literalName);
    278 
    279     void subtopicOut(string name);
    280     void subtopicsOut(Definition* def);
    281     void subtopicOut(string key, const vector<Definition*>& data, const Definition* csParent,
    282         const Definition* topicParent, bool showClones);
    283     bool subtopicRowOut(string keyName, const Definition* entry);
    284     void summaryOut(const Definition* def, MarkType , string name);
    285     string tableDataCodeDef(const Definition* def);
    286     string tableDataCodeDef(string def, string name);
    287     string tableDataCodeLocalRef(string name);
    288     string tableDataCodeLocalRef(string ref, string name);
    289     string tableDataCodeRef(const Definition* ref);
    290     string tableDataCodeRef(string ref, string name);
    291     void writeSubtopicTableHeader(string key);
    292 
    293     vector<const Definition*> fClassStack;
    294     unordered_map<string, vector<AnchorDef> > fAllAnchorDefs;
    295     unordered_map<string, vector<string> > fAllAnchorRefs;
    296     NameMap* fNames;
    297     BmhParser& fBmhParser;
    298     IncludeParser& fIncludeParser;
    299     const Definition* fEnumClass;
    300     const Definition* fLastDef;
    301     Definition* fMethod;
    302     RootDefinition* fRoot;  // used in generating populated tables; always struct or class
    303     RootDefinition* fSubtopic; // used in resolving symbols
    304     const Definition* fLastParam;
    305     TableState fTableState;
    306     unordered_map<string, SubtopicDescriptions> fPopulators;
    307     unordered_map<string, string> fPhraseParams;
    308     const char* fParamEnd;
    309     bool fAddRefFailed;
    310     bool fHasFiddle;
    311     bool fInDescription;   // FIXME: for now, ignore unfound camelCase in description since it may
    312                            // be defined in example which at present cannot be linked to
    313     bool fInList;
    314     bool fLiteralAndIndent;
    315     bool fResolveAndIndent;
    316     bool fOddRow;
    317     bool fHasDetails;
    318     bool fInProgress;
    319     typedef ParserCommon INHERITED;
    320 };
    321 
    322 #endif
    323