[flang] Markdown improvements.
authorpeter klausler <pklausler@nvidia.com>
Tue, 6 Feb 2018 19:14:53 +0000 (11:14 -0800)
committerpeter klausler <pklausler@nvidia.com>
Tue, 6 Feb 2018 19:14:53 +0000 (11:14 -0800)
Original-commit: flang-compiler/f18@f40b5e40df72542153552442fd6800fe6449236f

flang/C++style.md
flang/ParserCombinators.md

index e5889d7..eb1a4db 100755 (executable)
 1. File names should use dashes, not underscores.  C++ sources have the
 extension ".cc", not ".C" or ".cpp" or ".cxx".  Don't create needless
 source directory hierarchies.
-1. Header files should be idempotent.  Use the usual "#ifndef FORTRAN_header_H_",
-"#define FORTRAN_header_H_", and "#endif  // FORTRAN_header_H_" technique.
-1. #include every header defining an entity that your project header or source
+1. Header files should be idempotent.  Use the usual technique:
+```
+#ifndef FORTRAN_header_H_
+#define FORTRAN_header_H_
+// code
+#endif  // FORTRAN_header_H_
+```
+1. `#include` every header defining an entity that your project header or source
 file actually uses directly.  (Exception: when foo.cc starts, as it should,
-with #include "foo.h", and foo.h includes bar.h in order to define the
-interface to the module foo, you don't have to redundantly #include "bar.h"
+with `#include "foo.h"`, and foo.h includes bar.h in order to define the
+interface to the module foo, you don't have to redundantly `#include "bar.h"`
 in foo.cc.)
-1. In the source file "foo.cc", put the #include of "foo.h" first.
-Then #include other project headers in alphabetic order; then C++ standard
+1. In the source file "foo.cc", put the `#include "foo.h"` first.
+Then `#include` other project headers in alphabetic order; then C++ standard
 headers, also alphabetically; then C and system headers.
-1. Don't include the standard iostream header.  If you need it for debugging,
+1. Don't use `#include <iostream>`.  If you need it for debugging,
 remove the inclusion before committing.
 ### Naming
 1. C++ names that correspond to STL names should look like those STL names
-(e.g., *clear()* and *size()* member functions in a class that implements
+(e.g., `clear()` and `size()` member functions in a class that implements
 a container).
 1. Non-public data members should be named with leading miniscule (lower-case)
 letters, internal camelCase capitalization, and a trailing underscore,
-e.g. "DoubleEntryBookkeepingSystem myLedger_;".  POD structures with
+e.g. `DoubleEntryBookkeepingSystem myLedger_;`.  POD structures with
 only public data members shouldn't use trailing underscores, since they
 don't have class functions in which data members need to be distinguishable.
 1. Accessor member functions are named with the non-public data member's name,
-less the trailing underscore.  Mutator member functions are named *set_...*
-and should return "*this".  Don't define accessors or mutators needlessly.
+less the trailing underscore.  Mutator member functions are named `set_...`
+and should return `*this`.  Don't define accessors or mutators needlessly.
 1. Other class functions should be named with leading capital letters,
 CamelCase, and no underscores, and, like all functions, should be based
-on imperative verbs, e.g. *HaltAndCatchFire()*.
+on imperative verbs, e.g. `HaltAndCatchFire()`.
 1. It is fine to use short names for local variables with limited scopes,
-especially when you can declare them directly in a for()/while()/if()
+especially when you can declare them directly in a `for()`/`while()`/`if()`
 condition.  Otherwise, prefer complete English words to abbreviations
 when creating names.
 ### Commentary
-1. Use // for all comments except for short notes within expressions.
-1. When // follows code on a line, precede it with two spaces.
+1. Use `//` for all comments except for short `/*notes*/` within expressions.
+1. When `//` follows code on a line, precede it with two spaces.
 1. Comments should matter.  Assume that the reader knows current C++ at least as
 well as you do and avoid distracting her by calling out usage of new
 features in comments.
 ### Layout
-Always run *clang-format* before committing code.  Other developers should
-be able to run "git pull", then *clang-format*, and see only their own
+Always run `clang-format` before committing code.  Other developers should
+be able to run `git pull`, then `clang-format`, and see only their own
 changes.
 
-Here's what you can expect to see *clang-format* do:
+Here's what you can expect to see `clang-format` do:
 1. Indent with two spaces.
 1. Don't indent public:, protected:, and private:
 accessibility labels.
@@ -65,12 +70,12 @@ names.
 Don't try to make columns of variable names or comments
 align vertically -- they are maintenance problems.
 
-Always wrap the bodies of if(), else, while(), for(), do, &c.
+Always wrap the bodies of `if()`, `else`, `while()`, `for()`, `do`, &c.
 with braces, even when the body is a single statement or empty.  The
-opening { goes on
+opening `{` goes on
 the end of the line, not on the next line.  Functions also put the opening
-{ after the formal arguments or new-style result type, not on the next
-line.  Use {} for empty inline constructors and destructors in classes.
+`{` after the formal arguments or new-style result type, not on the next
+line.  Use `{}` for empty inline constructors and destructors in classes.
 
 Don't waste space on the screen with needless blank lines or elaborate block
 commentary (lines of dashes, boxes of asterisks, &c.).  Write code so as to be
@@ -79,39 +84,40 @@ easily read and understood with a minimum of scrolling.
 Use *C++17*, unless some compiler to which we must be portable lacks a feature
 you are considering.
 1. Never throw or catch exceptions.
-1. Never use run-time type information or dynamic_cast<>.
+1. Never use run-time type information or `dynamic_cast<>`.
 1. Never declare static data that executes a constructor.
-Use {braced initializers} in all circumstances where they work, including
+   (This is why `#include <iostream>` is contraindicated.)
+Use `{braced initializers}` in all circumstances where they work, including
 default data member initialization.  They inhibit implicit truncation.
-Don't use "= expr" initialization just to effect implicit truncation;
-prefer an explicit static_cast<>.
-1. Avoid unsigned types apart from size_t, which must be used with care.
-When *int* just obviously works, just use *int*.  When you need something
-bigger than *int*, use std::int64_t rather than *long* or long long.
+Don't use `= expr` initialization just to effect implicit truncation;
+prefer an explicit `static_cast<>`.
+1. Avoid unsigned types apart from `size_t`, which must be used with care.
+When `int` just obviously works, just use `int`.  When you need something
+bigger than `int`, use `std::int64_t` rather than `long` or `long long`.
 1. Use namespaces to avoid conflicts with client code.  Use one top-level
 project namespace.  Don't introduce needless nested namespaces within a
 project when names don't conflict or better solutions exist.  Never use
-"using namespace ...;", especially not "using namespace std;".  Access
-STL entities with names like std::unique_ptr<>, without a leading "::".
+`using namespace ...;`, especially not `using namespace std;`.  Access
+STL entities with names like `std::unique_ptr<>`, without a leading `::`.
 1. Prefer static functions to functions in anonymous namespaces in source files.
-1. Use *auto* judiciously.  When the type of a local variable is known,
-monomorphic, and easy to type, be explicit rather than using *auto*.
+1. Use `auto` judiciously.  When the type of a local variable is known,
+monomorphic, and easy to type, be explicit rather than using `auto`.
 1. Use move semantics and smart pointers to make dynamic memory ownership
-clear.  Consider reworking any code that uses malloc() or a (non-placement)
-operator new.
-1. Use references for const arguments; prefer const references to values for
-all but small types that are trivially copyable (e.g., *int*).  Use non-const
-pointers for output arguments.  Put output arguments last (pace the standard
-C library conventions for memcpy() & al.).
-1. Prefer *typename* to *class* in template argument declarations.
-1. Prefer enum class to plain enum wherever enum class will work.
-1. Use constexpr and const generously.
-1. When a switch() statement's labels do not cover all possible case values
-explicitly, it should contains either a "default:;" at its end or a
-default: label that obviously crashes.
+clear.  Consider reworking any code that uses `malloc()` or a (non-placement)
+`operator new`.
+1. Use references for `const` arguments; prefer `const` references to values for
+all but small types that are trivially copyable (e.g., use `const std::string &`
+and `int`).  Use non-`const` pointers for output arguments.  Put output arguments
+last (_pace_ the standard C library conventions for `memcpy()` & al.).
+1. Prefer `typename` to `class` in template argument declarations.
+1. Prefer `enum class` to plain `enum` wherever `enum class` will work.
+1. Use `constexpr` and `const` generously.
+1. When a `switch()` statement's labels do not cover all possible case values
+explicitly, it should contains either a `default:;` at its end or a
+`default:` label that obviously crashes.
 #### Classes
-1. Define only POD structures with struct.
-1. Don't use "this->" in (non-static) member functions.
+1. Define only POD structures with `struct`.
+1. Don't use `this->` in (non-static) member functions.
 1. Define accessor and mutator member functions (implicitly) inline in the
 class, after constructors and assignments.  Don't needlessly define
 (implicit) inline member functions in classes unless they really solve a
@@ -121,7 +127,7 @@ interfaces, at least to the extent that C++ allows.
 1. When copy constructors and copy assignment are not necessary,
 and move constructors/assignment is present, don't declare them and they
 will be implicitly deleted.  When neither copy nor move constructors
-or assignments should exist for a class, explicitly delete all of them.
+or assignments should exist for a class, explicitly `=delete` all of them.
 1. Make single-argument constructors (other than copy and move constructors)
 explicit unless you really want to define an implicit conversion.
 #### Overall design preferences
index 82032b6..8dac0bd 100644 (file)
@@ -4,31 +4,31 @@ descent parser.  It is composed from a *parser combinator* library that
 defines a few fundamental parsers and a few ways to compose them into more
 powerful parsers.
 
-For our purposes here, a *parser* is any object that can attempt to recognize
+For our purposes here, a *parser* is any object that attempts to recognize
 an instance of some syntax from an input stream.  It may succeed or fail.
 On success, it may return some semantic value to its caller.
 
 In C++ terms, a parser is any instance of a class that
-1. has a *constexpr* default constructor,
-1. defines a resultType type, and
-1. provides a member or static function that accepts a pointer to a
-ParseState as its argument and returns a std::optional<resultType> as a
-result, with the presence or absence of a value in the std::optional<>
+1. has a `constexpr` default constructor,
+1. defines a type named `resultType`, and
+1. provides a function (`const` member or static) that accepts a pointer to a
+ParseState as its argument and returns a `std::optional<resultType>` as a
+result, with the presence or absence of a value in the `std::optional<>`
 signifying success or failure, respectively.
-
-std::optional<resultType> Parse(ParseState *) const;
-
-The resultType of a parser is typically the class type of some particular
+```
+std::optional<resultType> Parse(ParseState *) const;
+```
+The `resultType` of a parser is typically the class type of some particular
 node type in the parse tree.
 
-*ParseState* is a class that encapsulates a position in the source stream,
-collects messages, and holds a few state flags that determive tokenization
-(e.g., are we in a character literal?).  Instances of *ParseState* are
+`ParseState` is a class that encapsulates a position in the source stream,
+collects messages, and holds a few state flags that determine tokenization
+(e.g., are we in a character literal?).  Instances of `ParseState` are
 independent and complete -- they are cheap to duplicate whenever necessary to
 implement backtracking.
 
-The constexpr default constructor of a parser is important.  The functions
-(below) that operate on instances of parsers are themselves all constexpr.
+The `constexpr` default constructor of a parser is important.  The functions
+(below) that operate on instances of parsers are themselves all `constexpr`.
 This use of compile-time expressions allows the entirety of a recursive
 descent parser for a language to be constructed at compilation time through
 the use of templates.
@@ -36,110 +36,115 @@ the use of templates.
 ### Fundamental Predefined Parsers
 These objects and functions are (or return) the fundamental parsers:
 
-* *ok* is a trivial parser that always succeeds without advancing.
-* "pure(x)" returns a trivial parser that always succeeds without advancing,
-  returning some value *x*.
-* "fail<T>(msg)" denotes a trivial parser that always fails, emitting the
-  given message.  The template parameter is the type of the value that
-  the parser never returns.
-* *cut* is a trivial parser that always fails silently.
-* "guard(pred)" returns a parser that succeeds if and only if the predicate
+* `ok` is a trivial parser that always succeeds without advancing.
+* `pure(x)` returns a trivial parser that always succeeds without advancing,
+  returning some value `x`.
+* `fail<T>(msg)` denotes a trivial parser that always fails, emitting the
+  given message as a side effect.  The template parameter is the type of
+  the value that the parser never returns.
+* `cut` is a trivial parser that always fails silently.
+* `guard(pred)` returns a parser that succeeds if and only if the predicate
   expression evaluates to true.
-* *rawNextChar* returns the next raw character, and fails at EOF.
-* *cookedNextChar* returns the next character after preprocessing, skipping
+* `rawNextChar` returns the next raw character, and fails at EOF.
+* `cookedNextChar` returns the next character after preprocessing, skipping
   Fortran line continuations and comments; it also fails at EOF
 
 ### Combinators
-These functions and operators combine parsers to generate new parsers.
+These functions and operators combine existing parsers to generate new parsers.
+They are `constexpr`, so they should be viewed as type-safe macros.
 
-* "!p" succeeds if p fails, and fails if p succeeds.
-* "p >> q" fails if p does, otherwise running q and returning its value when
+* `!p` succeeds if p fails, and fails if p succeeds.
+* `p >> q` fails if p does, otherwise running q and returning its value when
   it succeeds.
-* "p / q" fails if p does, otherwise running q and returning *p's* value
+* `p / q` fails if p does, otherwise running q and returning p's value
   if q succeeds.
-* "p || q" succeeds if p does, otherwise running q.  The two parsers must
+* `p || q` succeeds if p does, otherwise running q.  The two parsers must
   have the same type, and the value returned by the first succeeding parser
   is the value of the combination.
-* "lookAhead(p)" succeeds if p does, but doesn't modify any state.
-* "attempt(p)" succeeds if p does, safely preserving state on failure.
-* "many(p)" recognizes a greedy sequence of zero or more nonempty successes
-  of *p*, and returns std::list<> of their values.  It always succeeds.
-* "some(p)" recognized a greedy sequence of one or more successes of *p*.
+* `lookAhead(p)` succeeds if p does, but doesn't modify any state.
+* `attempt(p)` succeeds if p does, safely preserving state on failure.
+* `many(p)` recognizes a greedy sequence of zero or more nonempty successes
+  of p, and returns `std::list<>` of their values.  It always succeeds.
+* `some(p)` recognized a greedy sequence of one or more successes of p.
   It fails if p immediately fails.
-* "skipMany(p)" is the same as "many(p)", but it discards the results.
-* "maybe(p)" tries to match *p*, returning an "std::optional<T>" value.
+* `skipMany(p)` is the same as `many(p)`, but it discards the results.
+* `maybe(p)` tries to match p, returning an `std::optional<T>` value.
   It always succeeds.
-* "defaulted(p)" matches *p*, and when *p* fails it returns a
-  default-constructed instance of *p*'s resultType.  It always succeeds.
-* "nonemptySeparated(p, q)" repeatedly matches "p q p q p q ... p",
-  returning a std::list<> of only the values of the p's.  It fails if
-  *p* immediately fails.
-* "extension(p)" parses *p* if strict standard compliance is disabled,
+* `defaulted(p)` matches p, and when p fails it returns a
+  default-constructed instance of p's resultType.  It always succeeds.
+* `nonemptySeparated(p, q)` repeatedly matches "p q p q p q ... p",
+  returning a `std::list<>` of only the values of the p's.  It fails if
+  p immediately fails.
+* `extension(p)` parses p if strict standard compliance is disabled,
    or with a warning if nonstandard usage warnings are enabled.
-* "deprecated(p)" parses *p* if strict standard compliance is disabled,
+* `deprecated(p)` parses p if strict standard compliance is disabled,
   with a warning if deprecated usage warnings are enabled.
-* "inContext(..., p)" runs *p* within an error message context.
+* `inContext(..., p)` runs p within an error message context.
 
-Note that "a >> b >> c / d / e" matches a sequence of five parsers,
-but returns only the result that was obtained by matching c.
+Note that
+```
+a >> b >> c / d / e
+```
+matches a sequence of five parsers, but returns only the result that was
+obtained by matching `c`.
 
 ### Applicatives
 The following *applicative* combinators combine parsers and modify or
 collect the values that they return.
 
-* "construct<T>{}(p1, p2, ...)" matches zero or more parsers in succession,
+* `construct<T>{}(p1, p2, ...)` matches zero or more parsers in succession,
   collecting their results and then passing them with move semantics to a
-  constructor for the type *T* if they all succeed.
-* "applyFunction(f, p1, p2, ...)" matches one or more parsers in succession,
+  constructor for the type T if they all succeed.
+* `applyFunction(f, p1, p2, ...)` matches one or more parsers in succession,
   collecting their results and passing them as rvalue reference arguments to
   some function, returning its result.
-* "applyLambda([](&&x){}, p1, p2, ...)" is the same thing, but for lambdas
+* `applyLambda([](&&x){}, p1, p2, ...)` is the same thing, but for lambdas
   and other function objects.
-* "applyMem(mf, p1, p2, ...)" is the same thing, but invokes a member
+* `applyMem(mf, p1, p2, ...)` is the same thing, but invokes a member
   function of the result of the first parser for updates in place.
 
 ### Non-Advancing State Inquiries and Updates
 These are non-advancing state inquiry and update parsers:
 
-* *getColumn* returns the 1-based column position.
-* *inCharLiteral* succeeds under withinCharLiteral.
-* *inFortran* succeeds unless in a preprocessing directive.
-* *inFixedForm* succeeds in fixed-form source.
-* *setInFixedForm* sets the fixed-form flag, returning its prior value.
-* *columns* returns the 1-based column number after which source is clipped.
-* "setColumns(c)" sets the column limit and returns its prior value.
+* `getColumn` returns the 1-based column position.
+* `inCharLiteral` succeeds under withinCharLiteral.
+* `inFortran` succeeds unless in a preprocessing directive.
+* `inFixedForm` succeeds in fixed-form source.
+* `setInFixedForm` sets the fixed-form flag, returning its prior value.
+* `columns` returns the 1-based column number after which source is clipped.
+* `setColumns(c)` sets the column limit and returns its prior value.
 
 ### Monadic Combination
 When parsing depends on the result values of earlier parses, the
-"monadic bind" combinator is available.
+*monadic bind* combinator is available.
 Please try to avoid using it, as it makes automatic analysis of the
 grammar difficult.
-It has the syntax "p >>= f", and it constructs a parser that matches p,
+It has the syntax `p >>= f`, and it constructs a parser that matches p,
 yielding some value x on success, then matches the parser returned from
-the function call "f(x)".
+the function call `f(x)`.
 
 ### Token Parsers
 Last, we have these basic parsers on which the actual grammar of the Fortran
 is built.  All of the following parsers consume characters acquired from
-*cookedNextChar*.
+`cookedNextChar`.
 
-* *spaces* always succeeds after consuming any spaces or tabs
-* *digit* matches one cooked decimal digit (0-9)
-* *letter* matches one cooked letter (A-Z)
-* "CharMatch<'c'>{}" matches one specific cooked character.
-* "..."_tok match the content of the string, skipping spaces before and
+* `spaces` always succeeds after consuming any spaces or tabs
+* `digit` matches one cooked decimal digit (0-9)
+* `letter` matches one cooked letter (A-Z)
+* `CharMatch<'c'>{}` matches one specific cooked character.
+* `"..."_tok` match the content of the string, skipping spaces before and
   after, and with multiple spaces accepted for any internal space.
-  (Note that the _tok suffix is optional when the parser appears before
-  the combinator ">>" or after "/".)
-* "parenthesized(p)" is shorthand for "(" >> p / ")".
-* "bracketed(p)" is shorthand for "[" >> p / "]".
-* "withinCharLiteral(p)" applies the parser *p*, tokenizing for
+  (Note that the `_tok` suffix is optional when the parser appears before
+  the combinator`">>` or after `/`.)
+* `parenthesized(p)` is shorthand for `"(" >> p / ")"`.
+* `bracketed(p)` is shorthand for `"[" >> p / "]"`.
+* `withinCharLiteral(p)` applies the parser p, tokenizing for
   CHARACTER/Hollerith literals.
-* "nonEmptyListOf(p)" matches a comma-separated list of one or more
-  instances of *p*.
-* "optionalListOf(p)" is the same thing, but can be empty, and always succeeds.
+* `nonEmptyListOf(p)` matches a comma-separated list of one or more
+  instances of p.
+* `optionalListOf(p)` is the same thing, but can be empty, and always succeeds.
 
 ### Debugging Parser
-Last, the parser "..."_debug emit the string to the standard error and succeeds.
-It is useful for tracing while debugging a parser but should obviously not
-be committed for production code.
+Last, the parser `"..."_debug` emits the string to the standard error
+and succeeds.  It is useful for tracing while debugging a parser but should
+obviously not be committed for production code.