Enhanced C#
Language of your choice: library documentation
|
Prints a Loyc tree to EC# source code. More...
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:
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).
Public Types | |
enum | Ambiguity { Ambiguity.AllowUnassignedVarDecl = 0x0001, Ambiguity.CastRhs = 0x0002, Ambiguity.IsCallTarget = 0x0004, Ambiguity.NoBracedBlock = 0x0008, Ambiguity.FinalStmt = 0x0010, Ambiguity.TypeContext = 0x0020, Ambiguity.InDefinitionName = 0x0040, Ambiguity.InOf = 0x0080, Ambiguity.AllowPointer = 0x0100, Ambiguity.UseBacktick = 0x0400, Ambiguity.DropAttributes = 0x0800, Ambiguity.ForEachInitializer = 0x1000, Ambiguity.ElseClause = 0x2000, Ambiguity.AllowThisAsCallTarget = 0x8000, Ambiguity.NoIfWithoutElse = 0x10000, Ambiguity.NoParenthesis = 0x20000 } |
Internal enum (marked public for an obscure technical reason). These are flags that represent special situations in EC# syntax. More... | |
Public static fields | |
static readonly LNodePrinter | Printer = PrintECSharp |
Properties | |
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] |
Public Member Functions | |
void | Print (LNode node, StringBuilder target, IMessageSink errors, object mode, string indentString, string lineSeparator) |
EcsNodePrinter (LNode node, INodePrinterWriter target) | |
EcsNodePrinter | SetPlainCSharpMode () |
Sets AllowChangeParentheses, PreferPlainCSharp and DropNonDeclarationAttributes to true. More... | |
Static Public Member Functions | |
static EcsNodePrinter | New (LNode node, StringBuilder target, string indentString="\t", string lineSeparator="\n") |
static EcsNodePrinter | New (LNode node, TextWriter target, string indentString="\t", string lineSeparator="\n") |
static void | PrintPlainCSharp (LNode node, StringBuilder target, IMessageSink errors, object mode, string indentString, string lineSeparator) |
Internal enum (marked public for an obscure technical reason). These are flags that represent special situations in EC# syntax.
|
inline |
Sets AllowChangeParentheses, PreferPlainCSharp and DropNonDeclarationAttributes to true.
|
getset |
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.
For example, the Loyc tree x * @+(a, b)
will be printed x * (a + b)
. Originally, the second tree had a significantly different structure from the first, as parenthesis were represented by a call to the empty symbol @``. This was annoyingly restrictive, so I reconsidered the design; now, parenthesis will be represented only by a trivia attribute #trivia_inParens, so adding new parenthesis no longer changes the Loyc tree in an important way, so the default has changed from false to true (except in the test suite).
|
getset |
Causes the ambiguity between constructors and method calls to be ignored; see EcsPrinterAndParserTests.ConstructorAmbiguities().
|
getset |
Solve if-else ambiguity by adding braces rather than reverting to prefix notation.
For example, the tree #if(c1, #if(c2, x++), y++)
will be parsed incorrectly if it is printed if (c1) if (c2) x++; else y++;
. This problem can be resolved either by adding braces around if (c2) x++;
, or by printing #if(c2, x++)
in prefix notation.
|
getset |
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 {...}).
|
getset |
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.
This also affects the validation methods such as IsVariableDecl. With this flag, validation methods will ignore attributes in locations where they don't belong instead of returning false.
|
getset |
Any error that occurs during printing is printed to this object.
|
getset |
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.
|
getset |
Controls the locations where newlines should be emitted.
|
getset |
When this flag is set, comment trivia attributes are ignored (e.g. CodeSymbols.TriviaSLCommentAfter).
|
getset |
When an argument to a method or macro has an empty name (@``), it will be omitted completely if this flag is set.
|
getset |
When this flag is set, raw text trivia attributes are ignored (e.g. CodeSymbols.TriviaRawTextBefore).
|
getset |
When this flag is set, space trivia attributes are ignored (e.g. CodeSymbols.TriviaSpaceAfter).
Note: since EcsNodePrinter inserts its own spaces automatically, space trivia (if any) may be redundant unless you set SpaceOptions and/or NewlineOptions to zero.
|
getset |
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.
|
getset |
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.
|
getset |
Controls the locations where spaces should be emitted.