From 92d277d12e5023d9b84407bb727311e38a98715d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 31 Oct 2015 14:47:28 +0200 Subject: Parse and enter documentation variables --- cli/html.cxx | 3 ++ cli/parser.cxx | 116 ++++++++++++++++++++++++++++++++++++++++++++------------- cli/parser.hxx | 2 +- 3 files changed, 94 insertions(+), 27 deletions(-) (limited to 'cli') diff --git a/cli/html.cxx b/cli/html.cxx index dd49a91..1f84fdd 100644 --- a/cli/html.cxx +++ b/cli/html.cxx @@ -82,6 +82,9 @@ namespace virtual void traverse (type& ds) { + if (ds.name ().compare (0, 3, "doc") != 0) // Ignore doc variables. + return; + // n = 1 - common doc string // n = 2 - arg string, common doc string // n > 2 - arg string, usage string, man string diff --git a/cli/parser.cxx b/cli/parser.cxx index faca765..c7695bc 100644 --- a/cli/parser.cxx +++ b/cli/parser.cxx @@ -420,31 +420,87 @@ decl (token& t) void parser:: scope_doc (token& t) { - size_t l (t.line ()), c (t.column ()); - - doc* d (0); - - if (valid_) - { - // Use a counter to give scope-level docs unique names. We use a - // single counter throughout all units/scope because we could be - // reopening namespaces. - // - ostringstream os; - os << "doc " << doc_count_++; - - d = &root_->new_node (*path_, l, c); - root_->new_edge (*scope_, *d, os.str ()); - } + size_t ln (t.line ()), cl (t.column ()); + // Use a counter to give scope-level docs unique names. We use a + // single counter throughout all units/scope because we could be + // reopening namespaces. + // if (t.type () == token::t_string_lit) { // string-literal // if (valid_) { - d->push_back (doc_string (t)); - cerr << d->name () << " '" << d->back () << "'" << endl; + // Enter each ""-enclosed string as a separate documentation + // entry, handle documentation variables. + // + const string& l (t.literal ()); + + char p ('\0'); + for (size_t b (0), e (1); e < l.size (); ++e) + { + if (l[e] == '"' && p != '\\') + { + string s (doc_string (l.c_str () + b, e - b + 1)); + + if (!s.empty ()) + { + doc& d (root_->new_node (*path_, ln, cl)); + + // See if this is a variable assignment: "\=". + // + size_t p (0); // '=' position. + if (s.size () >= 3 && s[0] == '\\' && s[1] != '\\') + { + for (p = 1; p != s.size (); ++p) + { + char c (s[p]); + + // Variable name should be a C identifier. + // + if (!(c == '_' || + ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + (p != 1 && '0' <= c && c <= '9'))) + break; + } + + if (p == s.size () || s[p] != '=' || p == 1) // Not a variable. + p = 0; + } + + if (p != 0) + { + root_->new_edge ( + *scope_, d, "var: " + string (s, 1, p - 1)); + s = string (s, p + 1); + } + else + { + ostringstream os; + os << "doc: " << doc_count_++; + root_->new_edge (*scope_, d, os.str ()); + } + + d.push_back (s); // move(). + } + + // If we have more, then make b point to the opening '"'. Second + // ++e in for() above will make e point to the character after it. + // + b = ++e; + continue; + } + + // We need to keep track of \\ escapings so we don't confuse + // them with \", as in "\\". + // + if (l[e] == '\\' && p == '\\') + p = '\0'; + else + p = l[e]; + } } } else @@ -453,6 +509,16 @@ scope_doc (token& t) // assert (t.punctuation () == token::p_lcbrace); + doc* d (0); + if (valid_) + { + ostringstream os; + os << "doc: " << doc_count_++; + + d = &root_->new_node (*path_, ln, cl); + root_->new_edge (*scope_, *d, os.str ()); + } + for (t = lexer_->next ();; t = lexer_->next ()) { if (t.type () != token::t_string_lit) @@ -463,10 +529,8 @@ scope_doc (token& t) } if (valid_) - { - d->push_back (doc_string (t)); - cerr << d->name () << " '" << d->back () << "'" << endl; - } + d->push_back (doc_string (t.literal ().c_str (), + t.literal ().size ())); t = lexer_->next (); @@ -850,7 +914,8 @@ option_def (token& t) } if (valid_) - o->doc ().push_back (doc_string (t)); + o->doc ().push_back (doc_string (t.literal ().c_str (), + t.literal ().size ())); t = lexer_->next (); @@ -879,15 +944,14 @@ option_def (token& t) } string parser:: -doc_string (token& t) +doc_string (const char* l, size_t n) { // Get rid of '"'. // string t1, t2; - string const& l (t.literal ()); char p ('\0'); - for (size_t i (0), n (l.size ()); i < n; ++i) + for (size_t i (0); i < n; ++i) { if (l[i] == '"' && p != '\\') continue; diff --git a/cli/parser.hxx b/cli/parser.hxx index e3b1fee..733921a 100644 --- a/cli/parser.hxx +++ b/cli/parser.hxx @@ -56,7 +56,7 @@ private: option_def (token&); std::string - doc_string (token&); + doc_string (const char*, std::size_t); bool qualified_name (token&, std::string& name); -- cgit v1.1