Prints a Loyc tree to EC# source code.
This class is designed to faithfully represent Loyc trees by default; any Loyc tree that can be represented as EC# source code will be represented properly by this class, so that it is possible to parse the output text back into a Loyc tree equivalent to the one that was printed. In other words, EcsNodePrinter is designed to support round-tripping. For round- tripping to work, there are a couple of restrictions on the input tree:
-
The Value property must only be used in LiteralNodes, and only literals that can exist in C# source code are allowed. For example, Values of type int, string, and double are acceptable, but Values of type Regex or int[] are not, because single tokens cannot represent these types in C# source code. The printer ignores Values of non-literal nodes, and non-representable literals are printed out using ToString().
-
Names must come from the global symbol pool (GSymbol.Pool). The printer will happily print Symbols from other pools, but there is no way to indicate the pool in source code, so the parser always recreates symbols in the global pool. Non-global symbols are used after semantic analysis, so there is no way to faithfully represent the results of semantic analysis.
Only the attributes, head (LiteralNode.Value, IdNode.Name or CallNode.Target), and arguments of nodes are round-trippable. Superficial properties such as original source code locations and the LNode.Style are, in general, lost, although the printer can faithfully reproduce some (not all) NodeStyles. Also, any attribute whose Name starts with "#trivia_" will be dropped, because these attributes are considered extensions of the NodeStyle. However, the style indicated by the #trivia_* attribute will be used if the printer recognizes it.
Because EC# is based on C# which has some tricky ambiguities, there is a lot of code in this class dedicated to special cases and ambiguities. Even so, it is likely that some cases have been missed–that some unusual trees will not round-trip properly. Any failure to round-trip is a bug, and your bug reports are welcome. If this class uses prefix notation (with #specialNames) unnecessarily, that's also a bug, but it has low priority unless it affects plain C# output (where #specialNames are illegal.)
This class contains some configuration options that will defeat round- tripping but will make the output look better. For example, AllowExtraBraceForIfElseAmbig will print a tree such as #if(a, #if(b, f()), g())
as if (a) { if (b) f(); } else g();
, by adding braces to eliminate prefix notation, even though braces make the Loyc tree different.
To avoid printing EC# syntax that does not exist in C#, you can call SetPlainCSharpMode, but this only works if the syntax tree does not contain invalid structure or EC#-specific code such as "==>", "alias", and template arguments ($T).
|
LNode | Node [get, set] |
|
INodePrinterWriter | Writer [get, set] |
|
IMessageSink | Errors [get, set] |
| Any error that occurs during printing is printed to this object. More...
|
|
bool | MixImmiscibleOperators [get, set] |
| Allows operators to be mixed that will cause the parser to produce a warning. An example is x & @==(y, z) : if you enable this option, it will be printed as x & y == z , which the parser will complain about because mixing those operators is deprecated. More...
|
|
bool | AllowChangeParentheses [get, set] |
| Permits extra parentheses to express precedence, instead of resorting to prefix notation (defaults to true). Also permits removal of parenthesis if necessary to print special constructs. More...
|
|
bool | AllowExtraBraceForIfElseAmbig [get, set] |
| Solve if-else ambiguity by adding braces rather than reverting to prefix notation. More...
|
|
bool | DropNonDeclarationAttributes [get, set] |
| Suppresses printing of all attributes that are not on declaration or definition statements (such as classes, methods and variable declarations at statement level). Also, avoids prefix notation when the attributes would have required it, e.g. @+([Foo] a, b) can be printed "a+b" instead. More...
|
|
bool | OmitMissingArguments [get, set] |
| When an argument to a method or macro has an empty name (@``), it will be omitted completely if this flag is set. More...
|
|
bool | OmitSpaceTrivia [get, set] |
| When this flag is set, space trivia attributes are ignored (e.g. CodeSymbols.TriviaSpaceAfter). More...
|
|
bool | OmitComments [get, set] |
| When this flag is set, comment trivia attributes are ignored (e.g. CodeSymbols.TriviaSLCommentAfter). More...
|
|
bool | OmitRawText [get, set] |
| When this flag is set, raw text trivia attributes are ignored (e.g. CodeSymbols.TriviaRawTextBefore). More...
|
|
bool | QuoteUnprintableLiterals [get, set] |
| When the printer encounters an unprintable literal, it calls Value.ToString(). When this flag is set, the string is placed in double quotes; when this flag is clear, it is printed as raw text. More...
|
|
bool | AllowConstructorAmbiguity [get, set] |
| Causes the ambiguity between constructors and method calls to be ignored; see EcsPrinterAndParserTests.ConstructorAmbiguities(). More...
|
|
bool | AvoidMacroSyntax [get, set] |
| Prints statements like "foo (...) bar()" in the equivalent form "foo (..., bar())" instead. Does not affect foo {...} because property and event definitions require this syntax (get {...}, set {...}). More...
|
|
bool | PreferPlainCSharp [get, set] |
| Prefers plain C# syntax for certain other things (not covered by the other options), even when the syntax tree requests a different style, e.g. EC# cast operators are blocked so x(->int) becomes (int) x. More...
|
|
SpaceOpt | SpaceOptions [get, set] |
| Controls the locations where spaces should be emitted. More...
|
|
NewlineOpt | NewlineOptions [get, set] |
| Controls the locations where newlines should be emitted. More...
|
|
int | SpaceAroundInfixStopPrecedence [get, set] |
|
int | SpaceAfterPrefixStopPrecedence [get, set] |
|