Encapsulates an algorithm that consumes trivia (comments and newlines) from a list and adds it as trivia attributes into LNodes.
More...
Encapsulates an algorithm that consumes trivia (comments and newlines) from a list and adds it as trivia attributes into LNodes.
Call Run to invoke the algorithm. One must also write a derived class that knows how to interpret the trivia and associate it with a specific LNode, or use the standard derived class StandardTriviaInjector.
The algorithm is designed to postprocess output from a parser that works in a typical way. The lexer for your language needs to follow the following rules:
-
It must not include the newline character in the range of a single-line comment.
-
Generally, newlines (including the newline after a single-line comment) should be included in the trivia list, as the algorithm relies on newline trivia to notice when a new line is starting. Notably, a comment/trivia right after a statement (e.g. on the same line) should normally be associated with that statement; if this class is unaware of the newline it will be associated with the next statement instead.
Typically one will wrap the lexer in Lexing.TriviaSaver, which saves trivia while filtering out whitespace so that the parser doesen't see it.
Your language's parser needs to follow the following rules:
-
The parser should assign minimal boundaries to each node: the LNode.Range should not be wider than necessary. If there is a comment before an expression like
/* ! * / x + y, the parser should not include the comment as part of the range unless it wants the comment to be associated with a child node (x) instead of with the entire expression (x + y).
-
However, if a node has normal (non-trivia) attributes attached to it, the Range of the node must include those attributes. If your parser fails to do this, one symptom can be that a newline after an attribute "moves up" in the attribute list so it appears before the attribute.
-
The parser should use LNodeFactory.InParens to place a node in parentheses and include the index of the opening and closing parens.
-
If an expression/statement is terminated by a semicolon/comma, it's best (but not crucial) to include the semicolon/comma in the LNode.Range, but if a statement is terminated by a newline, the newline should not be included in the range. If general, when the terminator is included in the range, then any comment that appears before the terminator is attached to the final child node rather than to the node as a whole. (e.g. in
x = y /*y* /;, the comment is associated with y if the comment is within the range of the statement as a whole.)
This example shows how comments are associated with nodes: [NOTE: the space in "* /" is a workaround for a serious bug in Doxygen, the html doc generator]
// Comment attached to block
{
// Comment attached to Foo() call
Foo(
// Comment attached to «argument1 + 1». Note that the comma is
// generally invisible to the injector since it is not part of the LNode
// tree, so the 1st and 2nd comments will both be attached to the sum-
// expression as a whole.
argument1 + 1 /*1st comment* /, // 2nd comment
// Comment attached to «argument2 + 2»
argument2 + 2); // Comment attached to Foo() call
Area = 3.14159265/*PI* / * /*radius* /r**2;
// Comment attached to «Area =» statement, preceded by newline trivia? // Comment attached to Bar()
// Comment attached to BarAttr attribute
Bar();
// Comment attached to Bar() because there are no statements afterward
}
When there is a single newline between two nodes, Run will associate it with the second one. When there is a blank line between two nodes (two newlines), the first newline (and any before) is associated with the first node and the second newline (and any following) is associated with the second.
|
| abstract LNodeList | GetTriviaToAttach (LNode node, IListSource< Trivia > trivia, TriviaLocation loc, LNode?parent, int indexInParent) |
| | Derived class translates a list of trivia (tokens) into appropriate trivia attributes. This will be called for leading trivia before trailing trivia. More...
|
| |
| virtual void | ProcessChildrenOfOneLiner (ref LNode node) |
| | This method is called when a node has no newlines or comments within it (although the node may still have a leading or trailing comment). The method should add appendStatement trivia inside blocks in the node, if necessary. More...
|
| |
| abstract SourceRange | GetRange (Trivia trivia) |
| | Gets the SourceRange for an element of trivia. More...
|
| |
| abstract bool | IsNewline (Trivia trivia) |
| | Returns true if the trivia represents a newline, false otherwise. More...
|
| |
| virtual LNode | GetEmptyResultSet () |
| | A method called to create a virtual node, in order to apply trivia to a source file that is completely empty except for trivia. More...
|
| |
| virtual LNode | DoneAttaching (LNode node, LNode?parent, int indexInParent) |
| | This method is called after a node has been processed and any applicable trivia was attached. More...
|
| |
| IEnumerator< Pair< LNode, int > > | RunCore (IEnumerator< Pair< LNode, int >> nodes, LNode?parent) |
| | Core trivia associaton algorithm. More...
|
| |