private void PrintExpressionsInBraces(LNode body, bool isInitializer, Ambiguity flags) { bool anyNewlines = false; using (Indented) { NewlineOpt nlo = isInitializer ? NewlineOpt.AfterOpenBraceInNewExpr : NewlineOpt.Minimal | NewlineOpt.BeforeEachEnumItem; NewlineOpt next_nlo = isInitializer ? NewlineOpt.AfterEachInitializer : NewlineOpt.BeforeEachEnumItem; for (int i = 0, c = body.ArgCount; i < c; i++) { var stmt = body.Args[i]; if (i != 0) { _out.Write(','); nlo = next_nlo; } if (NewlineOrSpace(nlo, IsDefaultNewlineSuppressed(stmt), SpaceOpt.AfterComma)) { anyNewlines = true; } PrintExpr(stmt, StartExpr, flags); } } NewlineOrSpace(isInitializer ? NewlineOpt.BeforeCloseBraceInExpr : NewlineOpt.Default, !anyNewlines); }
public SPResult AutoPrintEvent(Ambiguity flags) { var eventType = EcsValidators.EventDefinitionType(_n, Pedantics); if (eventType == EcsValidators.EventDef.Invalid) { return(SPResult.Fail); } var ifClause = PrintTypeAndName(false, false, AttrStyle.IsDefinition, "event "); if (eventType == EcsValidators.EventDef.WithBody) { return(AutoPrintBodyOfMethodOrProperty(_n.Args[2, null], ifClause)); } else // EcsValidators.EventDef.List { for (int i = 2, c = _n.ArgCount; i < c; i++) { WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(_n.Args[i], ContinueExpr); } return(SPResult.NeedSemicolon); } }
private void PrintVariableDecl(bool printAttrs, Precedence context, Ambiguity allowPointer) { if (printAttrs) { G.Verify(0 == PrintAttrs(StartExpr, AttrStyle.IsDefinition, 0)); } Debug.Assert(_n.Name == S.Var); var a = _n.Args; if (IsSimpleSymbolWPA(a[0], S.Missing)) { _out.Write("var", true); } else { PrintType(a[0], context, allowPointer & Ambiguity.AllowPointer); } _out.Space(); for (int i = 1; i < a.Count; i++) { var @var = a[i]; if (i > 1) { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(@var, EP.Assign.RightContext(context), Ambiguity.NoParenthesis); } }
private bool PrintBracedBlockOrStmt(LNode stmt, Ambiguity flags, NewlineOpt beforeBrace = NewlineOpt.BeforeExecutableBrace) { var name = stmt.Name; if (name == S.Braces && !HasPAttrs(stmt) && HasSimpleHeadWPA(stmt)) { PrintBracedBlock(stmt, beforeBrace); return(true); } // Detect "else if (...)", and suppress newline/indent between "else" and "if". if (name == S.If && (flags & Ambiguity.ElseClause) != 0) { using (With(stmt)) if (EcsValidators.OtherBlockStmtType(_n, Pedantics) == S.If) { PrintStmt(flags & (Ambiguity.FinalStmt | Ambiguity.ElseClause)); return(false); } } using (Indented) { Newline(NewlineOpt.BeforeSingleSubstmt); PrintStmt(stmt, flags & (Ambiguity.FinalStmt | Ambiguity.NoIfWithoutElse)); return(false); } }
protected internal void PrintExpr(Precedence context, Ambiguity flags = 0) { if (!EP.Primary.CanAppearIn(context) && !_n.IsParenthesizedExpr()) { Debug.Assert((flags & Ambiguity.AllowUnassignedVarDecl) == 0); // Above EP.Primary (inside '$' or unary '.'), we can't use prefix // notation or most other operators so we're very limited in what // we can print. if (!HasPAttrs(_n)) { if (!_n.IsCall) { PrintSimpleSymbolOrLiteral(flags); return; } } PrintWithinParens(ParenFor.Grouping, _n); return; } NodeStyle style = _n.BaseStyle; if (style == NodeStyle.PrefixNotation && !PreferPlainCSharp) { PrintPrefixNotation(context, true, flags, false); } else { bool isVarDecl = IsVariableDecl(false, (flags & (Ambiguity.AllowUnassignedVarDecl | Ambiguity.ForEachInitializer)) != 0); int inParens = 0; if (_n.AttrCount != 0) { inParens = PrintAttrs(ref context, isVarDecl ? AttrStyle.IsDefinition : AttrStyle.AllowKeywordAttrs, flags); } bool startStmt = context.RangeEquals(StartStmt); bool startExpr = context.RangeEquals(StartExpr); if (isVarDecl && (startExpr || startStmt || (flags & Ambiguity.ForEachInitializer) != 0)) { PrintVariableDecl(false, context, flags); } else if (startExpr && IsNamedArgument()) { PrintNamedArg(context); } else if (!AutoPrintOperator(context, flags)) { PrintPrefixNotation(context, true, flags, true); } WriteCloseParens(inParens); } if (context.Lo != StartStmt.Lo) { PrintSuffixTrivia(false); } }
public bool PrintRawText(Precedence mainPrec, Precedence context, Ambiguity flags) { if (OmitRawText) { return(false); } _out.Write(GetRawText(_n), true); return(true); }
public SPResult AutoPrintResult(Ambiguity flags) { if (!IsResultExpr(_n) || (flags & Ambiguity.FinalStmt) == 0) { return(SPResult.Fail); } PrintExpr(_n.Args[0], StartExpr); // not StartStmt => allows multiplication e.g. a*b by avoiding ptr ambiguity return(SPResult.NeedSuffixTrivia); }
public SPResult AutoPrintAssemblyAttribute(Ambiguity flags) { Debug.Assert(_n.Calls(S.Assembly)); PrintAttrs(StartStmt, AttrStyle.NoKeywordAttrs, flags); _out.Write("[assembly:", true); Space(SpaceOpt.Default); PrintArgs(_n, flags, false); _out.Write(']', true); return(SPResult.NeedSuffixTrivia); }
public SPResult AutoPrintMissingStmt(Ambiguity flags) { Debug.Assert(_n.Name == S.Missing); if (!_n.IsId) { return(SPResult.Fail); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowKeywordAttrs, flags)); return(SPResult.NeedSemicolon); }
public SPResult AutoPrintRawText(Ambiguity flags) { if (OmitRawText) { return(SPResult.Fail); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.NoKeywordAttrs, flags)); WriteRawText(GetRawText(_n)); return(SPResult.NeedSuffixTrivia); }
public SPResult AutoPrintBlockOfStmts(Ambiguity flags) { if (!_n.Calls(S.Braces)) { return(SPResult.Fail); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowKeywordAttrs, flags)); PrintBracedBlock(_n, 0); return(SPResult.NeedSuffixTrivia); }
static void Main(string[] args) { Ambiguity.DateAmbiguity(); Ambiguity.TimeAmbiguity(); Ambiguity.DateTimeAmbiguity(); Ranges.DateRange(); Ranges.TimeRange(); Parsing.Examples(); LanguageGeneration.Examples(); Resolution.Examples(); Constraints.Examples(); }
public SPResult AutoPrintTwoArgBlockStmt() { // S.Do, S.Fixed, S.Lock, S.Switch, S.UsingStmt, S.While var type = EcsValidators.TwoArgBlockStmtType(_n, Pedantics); if (type == null) { return(SPResult.Fail); } var allowAttrs = (_name == S.UsingStmt ? AttrStyle.AllowKeywordAttrs : AttrStyle.AllowWordAttrs); G.Verify(0 == PrintAttrs(allowAttrs)); if (type == S.DoWhile) { _out.Write("do", true); bool braces = PrintBracedBlockOrStmt(_n.Args[0], NewlineOpt.BeforeSimpleStmtBrace); // Print newline in front of "while" if appropriate and avoid printing // "while (\ncondition)" when condition has an explicit newline; use // "\nwhile (condition)" instead. LNode cond = _n.Args[1]; LNode condWithoutNewline = cond.WithoutAttrNamed(S.TriviaNewline); if (cond != condWithoutNewline) { _out.Newline(); } else if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) { Space(SpaceOpt.Default); } _out.Write("while", true); PrintWithinParens(ParenFor.KeywordCall, condWithoutNewline); return(SPResult.NeedSemicolon); } else { WriteOperatorName(_name); Ambiguity argFlags = 0; if (_name == S.Fixed) { argFlags |= Ambiguity.AllowPointer; } PrintWithinParens(ParenFor.KeywordCall, _n.Args[0], argFlags); PrintBracedBlockOrStmt(_n.Args[1]); return(SPResult.NeedSuffixTrivia); } }
public SPResult AutoPrintVarDecl(Ambiguity flags) { if (!IsVariableDecl(true, true)) { return(SPResult.Fail); } var ifClause = GetIfClause(); G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.IsDefinition, flags, ifClause)); PrintVariableDecl(false, StartStmt, flags); AutoPrintIfClause(ifClause); return(SPResult.NeedSemicolon); }
public void PrintStmt(Ambiguity flags = 0) { if ((flags & Ambiguity.ElseClause) == 0) { _out.BeginStatement(); } if (AllowChangeParenthesis || !_n.IsParenthesizedExpr()) { var style = _n.BaseStyle; StatementPrinter printer; var name = _n.Name; if (StatementPrinters.TryGetValue(name, out printer) && HasSimpleHeadWPA(_n)) { if (PreferPlainCSharp || name == S.RawText || (style != NodeStyle.Expression && style != NodeStyle.PrefixNotation)) { var result = printer(this, flags | Ambiguity.NoParenthesis); if (result != SPResult.Fail) { if (result != SPResult.Complete) { PrintSuffixTrivia(result == SPResult.NeedSemicolon); } return; } } } if (style == NodeStyle.Special && AutoPrintMacroBlockCall(flags | Ambiguity.NoParenthesis)) { return; } var attrs = _n.Attrs; for (int i = 0, c = attrs.Count; i < c; i++) { var a = attrs[i]; if ((a.Name == S.TriviaMacroAttribute && AutoPrintMacroAttribute()) || (a.Name == S.TriviaForwardedProperty && AutoPrintForwardedProperty())) { return; } } } PrintExpr(StartStmt); PrintSuffixTrivia(true); }
static void Main(string[] args) { // Creating TIMEX expressions from natural language using the Recognizer package. Ambiguity.DateAmbiguity(); Ambiguity.TimeAmbiguity(); Ambiguity.DateTimeAmbiguity(); Ranges.DateRange(); Ranges.TimeRange(); // Manipulating TIMEX expressions in code using the TIMEX Datatype package. Parsing.Examples(); LanguageGeneration.Examples(); Resolution.Examples(); Constraints.Examples(); }
public SPResult AutoPrintSimpleStmt(Ambiguity flags) { // S.Break, S.Continue, S.Goto, S.GotoCase, S.Return, S.Throw, S.Import if (!EcsValidators.IsSimpleExecutableKeywordStmt(_n, Pedantics)) { return(SPResult.Fail); } var name = _n.Name; LNode usingStatic = name == S.Import && _n.AttrCount > 0 && _n.Attrs.Last.IsIdNamed(S.Static) ? _n.Attrs.Last : null; var allowAttrs = (name == S.Import ? AttrStyle.AllowKeywordAttrs : AttrStyle.AllowWordAttrs); G.Verify(0 == PrintAttrs(StartStmt, allowAttrs, flags, usingStatic)); if (name == S.GotoCase) { _out.Write("goto case", true); if (_n.ArgCount == 1 && _n.Args[0].IsIdNamed(S.Default)) { _out.Write("default", true); return(SPResult.NeedSemicolon); } } else if (name == S.Import) { _out.Write(usingStatic != null ? "using static" : "using", true); } else { WriteOperatorName(name); } int i = 0; foreach (var arg in _n.Args) { if (i++ == 0) { Space(SpaceOpt.Default); } else { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(arg, StartExpr); } return(SPResult.NeedSemicolon); }
private void PrintSimpleSymbolOrLiteral(Ambiguity flags) { Debug.Assert(_n.HasSimpleHead()); if (_n.IsLiteral) { PrintLiteral(); } else if (_n.Name == S.RawText && !OmitRawText) { _out.Write(GetRawText(_n), true); } else { PrintSimpleIdent(_n.Name, flags, false, _n.AttrNamed(S.TriviaUseOperatorKeyword) != null); } }
private void PrintArgs(VList <LNode> args, Ambiguity flags, bool omitMissingArguments, char separator = ',') { for (int i = 0; i < args.Count; i++) { var arg = args[i]; bool missing = omitMissingArguments && IsSimpleSymbolWPA(arg, S.Missing) && args.Count > 1; if (i != 0) { WriteThenSpace(separator, missing ? SpaceOpt.MissingAfterComma : SpaceOpt.AfterComma); } if (!missing) { PrintExpr(arg, StartExpr, flags); } } }
private void WriteOperatorName(Symbol name, Ambiguity flags = 0) { string opName = name.Name; if ((flags & Ambiguity.UseBacktick) != 0) { PrintString(opName, '`', null); } else if (opName.StartsWith("#")) { _out.Write(opName.Substring(1), true); } else { _out.Write(opName, true); } }
public SPResult AutoPrintProperty(Ambiguity flags) { // S.Property: // #property(int, Foo, { // get({ return _foo; }); // set({ _foo = value; }); // }); if (!IsPropertyDefinition()) { return(SPResult.Fail); } var ifClause = PrintTypeAndName(false); PrintWhereClauses(_n.Args[1]); return(AutoPrintBodyOfMethodOrProperty(_n.Args[2, null], ifClause)); }
public SPResult AutoPrintLabelStmt(Ambiguity flags) { if (!EcsValidators.IsLabelStmt(_n, Pedantics)) { return(SPResult.Fail); } _out.BeginLabel(); G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); if (_n.Name == S.Label) { if (_n.Args[0].Name == S.Default) { _out.Write("default", true); } else { PrintExpr(_n.Args[0], StartStmt); } } else if (_n.Name == S.Case) { _out.Write("case", true); _out.Space(); bool first = true; foreach (var arg in _n.Args) { if (first) { first = false; } else { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(arg, StartStmt); } } _out.Write(':', true); return(SPResult.NeedSuffixTrivia); }
public SPResult AutoPrintProperty(Ambiguity flags) { // For S.Property (#property), _n typically looks like this: // #property(int, Foo, @``, { // get({ return _foo; }); // set({ _foo = value; }); // }); if (!EcsValidators.IsPropertyDefinition(_n, Pedantics)) { return(SPResult.Fail); } var ifClause = PrintTypeAndName(false); PrintWhereClauses(_n.Args[1]); // Detect if property has argument list (T this[...] {...}) if (_n.Args[2].Calls(S.AltList)) { // Do what PrintArgList does, only with [] instead of () Space(SpaceOpt.BeforeMethodDeclArgList); _out.Write('[', true); WriteInnerSpace(ParenFor.MethodDecl); PrintArgs(_n.Args[2].Args, flags | Ambiguity.AllowUnassignedVarDecl, false); WriteInnerSpace(ParenFor.MethodDecl); _out.Write(']', true); } var spr = AutoPrintBodyOfMethodOrProperty(_n.Args[3, null], ifClause); if (_n.Args.Count >= 5) { var initializer = _n.Args[4]; if (!initializer.IsIdNamed(S.Missing)) { PrintInfixWithSpace(S.Assign, EcsPrecedence.Assign, 0); PrintExpr(initializer, StartExpr, flags); return(SPResult.NeedSemicolon); } } return(spr); }
static Symbol SpecialTypeKind(LNode n, Ambiguity flags, Precedence context) { // detects when notation for special types applies: Foo[], Foo*, Foo? // assumes IsComplexIdentifier() is already known to be true LNode first; if (n.Calls(S.Of, 2) && (first = n.Args[0]).IsId && (flags & Ambiguity.TypeContext) != 0) { var kind = first.Name; if (S.IsArrayKeyword(kind) || kind == S.QuestionMark) { return(kind); } if (kind == S._Pointer && ((flags & Ambiguity.AllowPointer) != 0 || context.Left == StartStmt.Left)) { return(kind); } } return(null); }
public SPResult AutoPrintSimpleStmt(Ambiguity flags) { // S.Break, S.Continue, S.Goto, S.GotoCase, S.Return, S.Throw if (!IsSimpleKeywordStmt()) { return(SPResult.Fail); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); var name = _n.Name; if (name == S.GotoCase) { _out.Write("goto case", true); } else if (name == S.Import) { _out.Write("using", true); } else { WriteOperatorName(name); } int i = 0; foreach (var arg in _n.Args) { if (i++ == 0) { Space(SpaceOpt.Default); } else { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(arg, StartExpr); } return(SPResult.NeedSemicolon); }
public SPResult AutoPrintTwoArgBlockStmt(Ambiguity flags) { // S.Do, S.Fixed, S.Lock, S.Switch, S.UsingStmt, S.While var type = EcsValidators.TwoArgBlockStmtType(_n, Pedantics); if (type == null) { return(SPResult.Fail); } var allowAttrs = (_n.Name == S.UsingStmt ? AttrStyle.AllowKeywordAttrs : AttrStyle.AllowWordAttrs); G.Verify(0 == PrintAttrs(StartStmt, allowAttrs, flags)); if (type == S.DoWhile) { _out.Write("do", true); bool braces = PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) { Space(SpaceOpt.Default); } _out.Write("while", true); PrintWithinParens(ParenFor.KeywordCall, _n.Args[1]); return(SPResult.NeedSemicolon); } else { WriteOperatorName(_n.Name); Ambiguity argFlags = 0; if (_n.Name == S.Fixed) { argFlags |= Ambiguity.AllowPointer; } PrintWithinParens(ParenFor.KeywordCall, _n.Args[0], argFlags); PrintBracedBlockOrStmt(_n.Args[1], flags); return(SPResult.NeedSuffixTrivia); } }
private bool AutoPrintOperator(Precedence context, Ambiguity flags) { if (!_n.IsCall || !_n.HasSimpleHead()) { return(false); } Pair <Precedence, OperatorPrinter> info; if (OperatorPrinters.TryGetValue(_n.Name, out info)) { return(info.Item2(this, info.Item1, context, flags)); } else if (_n.BaseStyle == NodeStyle.Operator) { if (_n.ArgCount == 2) { return(AutoPrintInfixBinaryOperator(EP.Backtick, context, flags | Ambiguity.UseBacktick)); } //if (_n.ArgCount == 1) // return AutoPrintPrefixUnaryOperator(EP.Backtick, context, flags | Ambiguity.UseBacktick); } return(false); }
public SPResult AutoPrintEvent(Ambiguity flags) { LNode type, name, body; if (!EcsValidators.IsEventDefinition(_n, out type, out name, out body, Pedantics)) { return(SPResult.Fail); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.IsDefinition, 0)); _out.Write("event ", true); PrintType(type, ContinueExpr, Ambiguity.AllowPointer); _out.Space(); if (name.Calls(S.AltList)) { bool first = true; foreach (var name2 in name.Args) { if (first) { first = false; } else { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(name2, ContinueExpr); } } else { PrintExpr(name, ContinueExpr); } return(AutoPrintBodyOfMethodOrProperty(body, null)); }
public bool AutoPrintCallOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles "call operators" such as default(...) and checked(...) bool needParens; Debug.Assert(CanAppearIn(precedence, context, out needParens)); Debug.Assert(_n.HasSpecialName); if (_n.ArgCount != 1) { return(false); } var name = _n.Name; var arg = _n.Args[0]; bool type = (name == S.Default || name == S.Typeof || name == S.Sizeof); if (type && !IsComplexIdentifier(arg, ICI.Default | ICI.AllowAttrs)) { return(false); } WriteOperatorName(name); PrintWithinParens(ParenFor.MethodCall, arg, type ? Ambiguity.TypeContext | Ambiguity.AllowPointer : 0); return(true); }
private void PrintVariableDecl(bool printAttrs, Precedence context, Ambiguity allowPointer) { if (printAttrs) G.Verify(0 == PrintAttrs(StartExpr, AttrStyle.IsDefinition, 0)); Debug.Assert(_n.Name == S.Var); var a = _n.Args; if (IsSimpleSymbolWPA(a[0], S.Missing)) _out.Write("var", true); else PrintType(a[0], context, allowPointer & Ambiguity.AllowPointer); _out.Space(); for (int i = 1; i < a.Count; i++) { var @var = a[i]; if (i > 1) WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(@var, EP.Assign.RightContext(context), Ambiguity.NoParenthesis); } }
private void PrintSimpleSymbolOrLiteral(Ambiguity flags) { Debug.Assert(_n.HasSimpleHead()); if (_n.IsLiteral) PrintLiteral(); else if (_n.Name == S.RawText && !OmitRawText) _out.Write(GetRawText(_n), true); else PrintSimpleIdent(_n.Name, flags, false, _n.AttrNamed(S.TriviaUseOperatorKeyword) != null); }
internal void PrintPrefixNotation(Precedence context, bool purePrefixNotation, Ambiguity flags = 0, bool skipAttrs = false) { Debug.Assert(EP.Primary.CanAppearIn(context) || _n.IsParenthesizedExpr()); int inParens = 0; if (!skipAttrs) inParens = PrintAttrs(ref context, purePrefixNotation ? AttrStyle.NoKeywordAttrs : AttrStyle.AllowKeywordAttrs, flags); if (!_n.IsCall) PrintSimpleSymbolOrLiteral(flags); else if (!purePrefixNotation && IsComplexIdentifier(_n, ICI.Default | ICI.AllowAttrs | ICI.AllowParensAround)) PrintExpr(context); else { if (!AllowConstructorAmbiguity && _n.Calls(_spaceName) && context == StartStmt && inParens == 0) { inParens++; WriteOpenParen(ParenFor.Grouping); } // Print Target var target = _n.Target; var f = Ambiguity.IsCallTarget; if (_spaceName == S.Fn || context != StartStmt) f |= Ambiguity.AllowThisAsCallTarget; PrintExpr(target, EP.Primary.LeftContext(context), f); // Print argument list WriteOpenParen(ParenFor.MethodCall); bool first = true; foreach (var arg in _n.Args) { if (OmitMissingArguments && IsSimpleSymbolWPA(arg, S.Missing) && _n.ArgCount > 1) { if (!first) WriteThenSpace(',', SpaceOpt.MissingAfterComma); } else { if (!first) WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(arg, StartExpr); } first = false; } WriteCloseParen(ParenFor.MethodCall); } WriteCloseParens(inParens); }
void PrintType(LNode n, Precedence context, Ambiguity flags = 0) { using (With(n)) PrintExpr(context, flags | Ambiguity.TypeContext); }
protected internal void PrintExpr(Precedence context, Ambiguity flags = 0) { if (!EP.Primary.CanAppearIn(context) && !_n.IsParenthesizedExpr()) { Debug.Assert((flags & Ambiguity.AllowUnassignedVarDecl) == 0); // Above EP.Primary (inside '$' or unary '.'), we can't use prefix // notation or most other operators so we're very limited in what // we can print. if (!HasPAttrs(_n)) { if (!_n.IsCall) { PrintSimpleSymbolOrLiteral(flags); return; } } PrintWithinParens(ParenFor.Grouping, _n); return; } NodeStyle style = _n.BaseStyle; if (style == NodeStyle.PrefixNotation && !PreferPlainCSharp) PrintPrefixNotation(context, true, flags, false); else { bool isVarDecl = IsVariableDecl(false, (flags & (Ambiguity.AllowUnassignedVarDecl|Ambiguity.ForEachInitializer)) != 0); int inParens = 0; if (_n.AttrCount != 0) inParens = PrintAttrs(ref context, isVarDecl ? AttrStyle.IsDefinition : AttrStyle.AllowKeywordAttrs, flags); bool startStmt = context.RangeEquals(StartStmt); bool startExpr = context.RangeEquals(StartExpr); if (isVarDecl && (startExpr || startStmt || (flags & Ambiguity.ForEachInitializer) != 0)) PrintVariableDecl(false, context, flags); else if (startExpr && IsNamedArgument()) PrintNamedArg(context); else if (!AutoPrintOperator(context, flags)) PrintPrefixNotation(context, true, flags, true); WriteCloseParens(inParens); } if (context.Lo != StartStmt.Lo) PrintSuffixTrivia(false); }
void PrintExpr(LNode n, Precedence context, Ambiguity flags) { using (With(n, context, CheckOneLiner(flags, n))) PrintCurrentExpr(); }
private bool AutoPrintOperator(Precedence context, Ambiguity flags) { if (!_n.IsCall || !_n.HasSimpleHead()) return false; Pair<Precedence, OperatorPrinter> info; if (OperatorPrinters.TryGetValue(_n.Name, out info)) return info.Item2(this, info.Item1, context, flags); else if (_n.BaseStyle == NodeStyle.Operator) { if (_n.ArgCount == 2) return AutoPrintInfixBinaryOperator(EP.Backtick, context, flags | Ambiguity.UseBacktick); //if (_n.ArgCount == 1) // return AutoPrintPrefixUnaryOperator(EP.Backtick, context, flags | Ambiguity.UseBacktick); } return false; }
public SPResult AutoPrintBlockOfStmts(Ambiguity flags) { if (!IsBlockOfStmts(_n)) return SPResult.Fail; G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowKeywordAttrs, flags)); PrintBracedBlock(_n, 0); return SPResult.NeedSuffixTrivia; }
void PrintStmt(LNode n, Ambiguity flags) { using (With(n, StartStmt, CheckOneLiner(flags, n))) PrintCurrentStmt(); }
public bool AutoPrintComplexIdentOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles #of and #., including array types int argCount = _n.ArgCount; Symbol name = _n.Name; Debug.Assert((name == S.Of || name == S.Dot) && _n.IsCall); var first = _n.Args[0, null]; if (first == null) return false; // no args bool needParens, needSpecialOfNotation = false; if (!CanAppearIn(precedence, context, out needParens) || needParens) return false; // this only happens inside $ operator, e.g. $(a.b) if (name == S.Dot) { // The trouble with the dot is its high precedence; because of // this, arguments after a dot cannot use prefix notation as a // fallback. For example "@.(a, b(c))" cannot be printed "a.b(c)" // since that means @.(a, b)(c)". The first argument to non- // unary "." can use prefix notation safely though, e.g. // "@.(b(c), a)" can (and must) be printed "b(c).a". if (argCount > 2) return false; if (HasPAttrs(first)) return false; LNode afterDot = _n.Args.Last; // Unary dot is no problem: .(a) is parsed the same as .a, i.e. // the parenthesis are ignored, so we can print an expr like // @`.`(a+b) as .(a+b), but the parser counts parens on binary // dot, so in that case the argument after the dot must not be any // kind of call (except substitution) and must not have attributes, // unless it is in parens. if (argCount == 2 && !afterDot.IsParenthesizedExpr()) { if (HasPAttrs(afterDot)) return false; if (afterDot.IsCall && afterDot.Name != S.Substitute) return false; } } else if (name == S.Of) { var ici = ICI.Default | ICI.AllowAttrs; if ((flags & Ambiguity.InDefinitionName) != 0) ici |= ICI.NameDefinition; if (!IsComplexIdentifier(_n, ici)) { if (IsComplexIdentifier(_n, ici | ICI.AllowAnyExprInOf)) needSpecialOfNotation = true; else return false; } } if (name == S.Dot) { if (argCount == 1) { _out.Write('.', true); PrintExpr(first, EP.Substitute); } else { PrintExpr(first, precedence.LeftContext(context), flags & Ambiguity.TypeContext); _out.Write('.', true); PrintExpr(_n.Args[1], precedence.RightContext(context)); } } else if (_n.Name == S.Of) { // Check for special type names such as Foo? or Foo[] Symbol stk = SpecialTypeKind(_n, flags, context); if (stk != null) { if (S.IsArrayKeyword(stk)) { // We do something very strange in case of arrays of arrays: // the order of the square brackets must be reversed when // arrays are nested. For example, an array of two-dimensional // arrays of int is written int[][,], rather than int[,][] // which would be much easier to handle. var stack = InternalList<Symbol>.Empty; var innerType = _n; do { stack.Add(stk); innerType = innerType.Args[1]; } while (S.IsArrayKeyword(stk = SpecialTypeKind(innerType, flags, context) ?? GSymbol.Empty)); PrintType(innerType, EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer)); for (int i = 0; i < stack.Count; i++) _out.Write(stack[i].Name, true); // e.g. [] or [,] } else { PrintType(_n.Args[1], EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer)); _out.Write(stk == S._Pointer ? '*' : '?', true); } return true; } PrintExpr(first, precedence.LeftContext(context)); _out.Write(needSpecialOfNotation ? "!(" : "<", true); for (int i = 1; i < argCount; i++) { if (i > 1) WriteThenSpace(',', SpaceOpt.AfterCommaInOf); PrintType(_n.Args[i], StartExpr, Ambiguity.InOf | Ambiguity.AllowPointer | (flags & Ambiguity.InDefinitionName)); } _out.Write(needSpecialOfNotation ? ')' : '>', true); } else { Debug.Assert(_n.Name == S.Substitute); G.Verify(AutoPrintOperator(ContinueExpr, 0)); } return true; }
static Symbol SpecialTypeKind(LNode n, Ambiguity flags, Precedence context) { // detects when notation for special types applies: Foo[], Foo*, Foo? // assumes IsComplexIdentifier() is already known to be true LNode first; if (n.Calls(S.Of, 2) && (first = n.Args[0]).IsId && (flags & Ambiguity.TypeContext)!=0) { var kind = first.Name; if (S.IsArrayKeyword(kind) || kind == S.QuestionMark) return kind; if (kind == S._Pointer && ((flags & Ambiguity.AllowPointer) != 0 || context.Left == StartStmt.Left)) return kind; } return null; }
public bool AutoPrintListOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles #tuple and {} braces. int argCount = _n.ArgCount; Symbol name = _n.Name; Debug.Assert(_n.IsCall); bool? braceMode; if (name == S.Tuple) { braceMode = false; flags &= Ambiguity.AllowUnassignedVarDecl; } else if (name == S.Braces) { // A braced block is not allowed at start of an expression // statement; the parser would mistake it for a standalone // braced block (the difference is that a standalone braced // block ends automatically after '}', with no semicolon.) if (context.Left == StartStmt.Left || (flags & Ambiguity.NoBracedBlock) != 0) return false; braceMode = true; if (context.Left <= ContinueExpr.Left && _n.BaseStyle == NodeStyle.OldStyle) braceMode = null; // initializer mode } else if (name == S.ArrayInit) { braceMode = null; // initializer mode } else { Debug.Assert(false); // Code quote operator has been REMOVED from EC#, in favor of #quote(...), at least for now. //Debug.Assert(name == S.CodeQuote || name == S.CodeQuoteSubstituting || name == S.List); //_out.Write(name == S.CodeQuote ? "@" : "@@", false); braceMode = _n.BaseStyle == NodeStyle.Statement && (flags & Ambiguity.NoBracedBlock) == 0; flags = 0; } int c = _n.ArgCount; if (braceMode ?? true) { if (!Newline(NewlineOpt.BeforeOpenBraceInExpr)) Space(SpaceOpt.OutsideParens); _out.Write('{', true); if (braceMode == true) { using (Indented) { for (int i = 0; i < c; i++) PrintStmt(_n.Args[i], i + 1 == c ? Ambiguity.FinalStmt : 0); } } else { _out.Space(); for (int i = 0; i < c; i++) { if (i != 0) WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(_n.Args[i], StartExpr, flags); } } if (!Newline(NewlineOpt.BeforeCloseBraceInExpr)) _out.Space(); _out.Write('}', true); if (!Newline(NewlineOpt.AfterCloseBraceInExpr)) Space(SpaceOpt.OutsideParens); } else { WriteOpenParen(ParenFor.Grouping); for (int i = 0; i < c; i++) { if (i != 0) WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(_n.Args[i], StartExpr, flags); } if (name == S.Tuple && c == 1) _out.Write(',', true); WriteCloseParen(ParenFor.Grouping); } return true; }
public bool AutoPrintCastOperator(Precedence precedence, Precedence context, Ambiguity flags) { if (_n.ArgCount != 2) return false; // Cast operators can have attributes on the second argument using // alternate notation, e.g. x(as [A] Foo) is legal but "x as [A] Foo" // is not, because attributes must only appear at the beginning of an // expression and only the second case treats the text after 'as' as // the beginning of a new expression. Also, because a standard cast // like (Foo)(x) is ambiguous (is x being cast to type Foo, or is a // delegate named Foo being called with x as an argument?), an // attribute list can be used to resolve the ambiguity. So (Foo)(x) // is considered a cast, while ([ ] Foo)(x) is a call to Foo in which // Foo happens to be placed in parenthesis. Thus, if target type of a // cast has attributes, it must be expressed in alternate form, e.g. // (x)(->[A] Foo), or in prefix form. // // There is an extra rule for (X)Y casts: X must be a complex (or // simple) identifier, since anything else won't be parsed as a cast. Symbol name = _n.Name; bool alternate = (_n.Style & NodeStyle.Alternate) != 0 && !PreferPlainCSharp; LNode subject = _n.Args[0], target = _n.Args[1]; if (HasPAttrs(subject)) return false; if (HasPAttrs(target) || (name == S.Cast && !IsComplexIdentifier(target, ICI.Default | ICI.AllowAnyExprInOf))) alternate = true; bool needParens; if (alternate) precedence = EP.Primary; if (!CanAppearIn(precedence, context, out needParens)) { // There are two different precedences for cast operators; we prefer // the traditional forms (T)x, x as T, x using T which have lower // precedence, but they don't work in this context so consider using // x(->T), x(as T) or x(using T) instead. alternate = true; precedence = EP.Primary; if (!CanAppearIn(precedence, context, out needParens)) return false; } if (alternate && PreferPlainCSharp) return false; // old-style cast is impossible here if (WriteOpenParen(ParenFor.Grouping, needParens)) context = StartExpr; if (alternate) { PrintExpr(subject, precedence.LeftContext(context)); WriteOpenParen(ParenFor.NewCast); _out.Write(GetCastText(_n.Name), true); Space(SpaceOpt.AfterCastArrow); PrintType(target, StartExpr, Ambiguity.AllowPointer); WriteCloseParen(ParenFor.NewCast); } else { if (_n.Name == S.Cast) { WriteOpenParen(ParenFor.Grouping); PrintType(target, ContinueExpr, Ambiguity.AllowPointer); WriteCloseParen(ParenFor.Grouping); Space(SpaceOpt.AfterCast); PrintExpr(subject, precedence.RightContext(context), Ambiguity.CastRhs); } else { // "x as y" or "x using y" PrintExpr(subject, precedence.LeftContext(context)); _out.Write(GetCastText(_n.Name), true); PrintType(target, precedence.RightContext(context)); } } WriteCloseParen(ParenFor.Grouping, needParens); return true; }
private void PrintArgs(VList<LNode> args, Ambiguity flags, bool omitMissingArguments, char separator = ',') { for (int i = 0; i < args.Count; i++) { var arg = args[i]; bool missing = omitMissingArguments && IsSimpleSymbolWPA(arg, S.Missing) && args.Count > 1; if (i != 0) WriteThenSpace(separator, missing ? SpaceOpt.MissingAfterComma : SpaceOpt.AfterComma); if (!missing) PrintExpr(arg, StartExpr, flags); } }
public SPResult AutoPrintOtherBlockStmt(Ambiguity flags) { // S.If, S.For, S.ForEach, S.Checked, S.Unchecked, S.Try var type = OtherBlockStmtType(); if (type == null) return SPResult.Fail; if (type == S.If) { var @else = _n.Args[2, null]; bool needCloseBrace = false; if (@else == null && (flags & Ambiguity.NoIfWithoutElse) != 0) { if (AllowExtraBraceForIfElseAmbig) { _out.Write('{', true); needCloseBrace = true; } else return SPResult.Fail; } // Note: the "if" statement in particular cannot have "word" attributes // because they would create ambiguity with property declarations G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowKeywordAttrs, flags)); _out.Write("if", true); PrintWithinParens(ParenFor.KeywordCall, _n.Args[0]); var thenFlags = flags & ~(Ambiguity.ElseClause); if (@else != null) thenFlags |= Ambiguity.NoIfWithoutElse; bool braces = PrintBracedBlockOrStmt(_n.Args[1], thenFlags); if (@else != null) { if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) Space(SpaceOpt.Default); _out.Write("else", true); PrintBracedBlockOrStmt(@else, flags | Ambiguity.ElseClause); } if (needCloseBrace) _out.Write('}', true); return SPResult.NeedSuffixTrivia; } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); if (type == S.For) { _out.Write("for", true); PrintArgList(_n, ParenFor.KeywordCall, 3, flags, true, ';'); PrintBracedBlockOrStmt(_n.Args[3], flags); } else if (type == S.ForEach) { _out.Write("foreach", true); WriteOpenParen(ParenFor.KeywordCall); PrintExpr(_n.Args[0], EP.Equals.LeftContext(StartStmt), Ambiguity.AllowUnassignedVarDecl | Ambiguity.ForEachInitializer); _out.Space(); _out.Write("in", true); _out.Space(); PrintExpr(_n.Args[1], ContinueExpr, flags); WriteCloseParen(ParenFor.KeywordCall); PrintBracedBlockOrStmt(_n.Args[2], flags); } else if (type == S.Try) { _out.Write("try", true); bool braces = PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); for (int i = 1, c = _n.ArgCount; i < c; i++) { if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) Space(SpaceOpt.Default); var clause = _n.Args[i]; LNode first = clause.Args[0], second = clause.Args[1, null]; WriteOperatorName(clause.Name); if (second != null && !IsSimpleSymbolWPA(first, S.Missing)) PrintWithinParens(ParenFor.KeywordCall, first, Ambiguity.AllowUnassignedVarDecl); braces = PrintBracedBlockOrStmt(second ?? first, flags); } } else if (type == S.Checked) // includes S.Unchecked { WriteOperatorName(_n.Name); PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); } return SPResult.NeedSuffixTrivia; }
public void PrintStmt(Ambiguity flags = 0) { if ((flags & Ambiguity.ElseClause) == 0) _out.BeginStatement(); if (AllowChangeParenthesis || !_n.IsParenthesizedExpr()) { var style = _n.BaseStyle; StatementPrinter printer; var name = _n.Name; if (StatementPrinters.TryGetValue(name, out printer) && HasSimpleHeadWPA(_n)) { if (PreferPlainCSharp || name == S.RawText || (style != NodeStyle.Expression && style != NodeStyle.PrefixNotation)) { var result = printer(this, flags | Ambiguity.NoParenthesis); if (result != SPResult.Fail) { if (result != SPResult.Complete) PrintSuffixTrivia(result == SPResult.NeedSemicolon); return; } } } if (style == NodeStyle.Special && AutoPrintMacroBlockCall(flags | Ambiguity.NoParenthesis)) return; var attrs = _n.Attrs; for (int i = 0, c = attrs.Count; i < c; i++) { var a = attrs[i]; if ((a.Name == S.TriviaMacroAttribute && AutoPrintMacroAttribute()) || (a.Name == S.TriviaForwardedProperty && AutoPrintForwardedProperty())) return; } } PrintExpr(StartStmt); PrintSuffixTrivia(true); }
public SPResult AutoPrintSimpleStmt(Ambiguity flags) { // S.Break, S.Continue, S.Goto, S.GotoCase, S.Return, S.Throw if (!IsSimpleKeywordStmt()) return SPResult.Fail; G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); var name = _n.Name; if (name == S.GotoCase) _out.Write("goto case", true); else if (name == S.Import) _out.Write("using", true); else WriteOperatorName(name); int i = 0; foreach (var arg in _n.Args) { if (i++ == 0) Space(SpaceOpt.Default); else WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(arg, StartExpr); } return SPResult.NeedSemicolon; }
void PrintStmt(LNode n, Ambiguity flags = 0) { using (With(n)) PrintStmt(flags); }
public bool AutoPrintPrefixUnaryOperator(Precedence precedence, Precedence context, Ambiguity flags) { if (!IsPrefixOperator(_n, false)) return false; var name = _n.Name; var arg = _n.Args[0]; bool needParens; if (CanAppearIn(precedence, context, out needParens, true)) { // Check for the ambiguous case of (Foo)-x, (Foo)*x, etc. if ((flags & Ambiguity.CastRhs) != 0 && !needParens && ( name == S._Dereference || name == S.PreInc || name == S.PreDec || name == S._UnaryPlus || name == S._Negate || name == S.NotBits || name == S._AddressOf) && !_n.IsParenthesizedExpr()) { if (AllowChangeParenthesis) needParens = true; // Resolve ambiguity with extra parens else return false; // Fallback to prefix notation } // Check for the ambiguous case of "~Foo(...);" if (name == S.NotBits && context.Lo == StartStmt.Lo && arg.IsCall) return false; if (WriteOpenParen(ParenFor.Grouping, needParens)) context = StartExpr; _out.Write(_n.Name.Name, true); PrefixSpace(precedence); PrintExpr(arg, precedence.RightContext(context), name == S.Forward ? Ambiguity.TypeContext : 0); //if (backtick) { // Debug.Assert(precedence == EP.Backtick); // if ((SpacingOptions & SpaceOpt.AroundInfix) != 0 && precedence.Lo < SpaceAroundInfixStopPrecedence) // _out.Space(); // PrintOperatorName(_n.Name, Ambiguity.UseBacktick); //} WriteCloseParen(ParenFor.Grouping, needParens); return true; } return false; }
public SPResult AutoPrintLabelStmt(Ambiguity flags) { if (!IsLabelStmt()) return SPResult.Fail; _out.BeginLabel(); G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); if (_n.Name == S.Label) { if (_n.Args[0].Name == S.Default) _out.Write("default", true); else PrintExpr(_n.Args[0], StartStmt); } else if (_n.Name == S.Case) { _out.Write("case", true); _out.Space(); bool first = true; foreach (var arg in _n.Args) { if (first) first = false; else WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(arg, StartStmt); } } _out.Write(':', true); return SPResult.NeedSuffixTrivia; }
public bool AutoPrintCallOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles "call operators" such as default(...) and checked(...) bool needParens; Debug.Assert(CanAppearIn(precedence, context, out needParens)); Debug.Assert(_n.HasSpecialName); if (_n.ArgCount != 1) return false; var name = _n.Name; var arg = _n.Args[0]; bool type = (name == S.Default || name == S.Typeof || name == S.Sizeof); if (type && !IsComplexIdentifier(arg, ICI.Default | ICI.AllowAttrs)) return false; WriteOperatorName(name); PrintWithinParens(ParenFor.MethodCall, arg, type ? Ambiguity.TypeContext | Ambiguity.AllowPointer : 0); return true; }
public SPResult AutoPrintTwoArgBlockStmt(Ambiguity flags) { // S.Do, S.Fixed, S.Lock, S.Switch, S.UsingStmt, S.While var type = TwoArgBlockStmtType(); if (type == null) return SPResult.Fail; G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); if (type == S.DoWhile) { _out.Write("do", true); bool braces = PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) Space(SpaceOpt.Default); _out.Write("while", true); PrintWithinParens(ParenFor.KeywordCall, _n.Args[1]); return SPResult.NeedSemicolon; } else { WriteOperatorName(_n.Name); Ambiguity argFlags = 0; if (_n.Name == S.Fixed) argFlags |= Ambiguity.AllowPointer; PrintWithinParens(ParenFor.KeywordCall, _n.Args[0], argFlags); PrintBracedBlockOrStmt(_n.Args[1], flags); return SPResult.NeedSuffixTrivia; } }
public bool PrintRawText(Precedence mainPrec, Precedence context, Ambiguity flags) { if (OmitRawText) return false; _out.Write(GetRawText(_n), true); return true; }
public bool AutoPrintNewOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Prints the new Xyz(...) {...} operator Debug.Assert (_n.Name == S.New); int argCount = _n.ArgCount; if (argCount == 0) return false; bool needParens; Debug.Assert(CanAppearIn(precedence, context, out needParens) && !needParens); LNode cons = _n.Args[0]; LNode type = cons.Target; var consArgs = cons.Args; // There are two basic uses of new: for objects, and for arrays. // In all cases, #new has 1 arg plus optional initializer arguments, // and there's always a list of "constructor args" even if it is empty // (exception: new {...}). // 1. Init an object: 1a. new Foo<Bar>() { ... } <=> #new(Foo<bar>(...), ...) // 1b. new { ... } <=> #new(@``, ...) // 2. Init an array: 2a. new int[] { ... }, <=> #new(int[](), ...) <=> #new(#of(@`[]`, int)(), ...) // 2b. new[,] { ... }. <=> #new(@`[,]`(), ...) // 2c. new int[10,10] { ... }, <=> #new(#of(@`[,]`, int)(10,10), ...) // 2d. new int[10][] { ... }, <=> #new(#of(@`[]`, #of(@`[]`, int))(10), ...) if (HasPAttrs(cons)) return false; if (type == null ? !cons.IsIdNamed(S.Missing) : HasPAttrs(type) || !IsComplexIdentifier(type)) return false; // Okay, we can now be sure that it's printable, but is it an array decl? if (type == null) { // 1b, new {...} _out.Write("new ", true); PrintBracedBlockInNewExpr(); } else if (type != null && type.IsId && S.CountArrayDimensions(type.Name) > 0) { // 2b _out.Write("new", true); _out.Write(type.Name.Name, true); Space(SpaceOpt.Default); PrintBracedBlockInNewExpr(); } else { _out.Write("new ", true); int dims = CountDimensionsIfArrayType(type); if (dims > 0 && cons.Args.Count == dims) { PrintTypeWithArraySizes(cons); } else { // Otherwise we can print the type name without caring if it's an array or not. PrintType(type, EP.Primary.LeftContext(context)); if (cons.ArgCount != 0 || (argCount == 1 && dims == 0)) PrintArgList(cons, ParenFor.MethodCall, cons.ArgCount, 0, OmitMissingArguments); } if (_n.Args.Count > 1) PrintBracedBlockInNewExpr(); } return true; }
void PrintExpr(LNode n, Precedence context, Ambiguity flags = 0) { using (With(n)) PrintExpr(context, flags); }
public bool AutoPrintInfixBinaryOperator(Precedence prec, Precedence context, Ambiguity flags) { var name = _n.Name; Debug.Assert(!CastOperators.ContainsKey(name)); // not called for cast operators if (_n.ArgCount != 2) return false; // Attributes on the children disqualify operator notation LNode left = _n.Args[0], right = _n.Args[1]; if (HasPAttrs(left) || HasPAttrs(right)) return false; bool needParens, backtick = (_n.Style & NodeStyle.Alternate) != 0; if (CanAppearIn(ref prec, context, out needParens, ref backtick)) { // Check for the ambiguous case of "A * b;" and consider using `*` instead if (name == S.Mul && context.Left == StartStmt.Left && IsComplexIdentifier(left)) { backtick = true; prec = EP.Backtick; if (!CanAppearIn(prec, context, out needParens, false)) return false; } if (WriteOpenParen(ParenFor.Grouping, needParens)) context = StartExpr; PrintExpr(left, prec.LeftContext(context), (name == S.Assign || name == S.Lambda ? Ambiguity.AllowUnassignedVarDecl : 0)); if (backtick) flags |= Ambiguity.UseBacktick; PrintInfixWithSpace(_n.Name, prec, flags); PrintExpr(right, prec.RightContext(context)); WriteCloseParen(ParenFor.Grouping, needParens); return true; } return false; }
public bool AutoPrintOtherSpecialOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles one of: ? [] suf++ suf-- int argCount = _n.ArgCount; Symbol name = _n.Name; if (argCount < 1) return false; // no args bool needParens; if (!CanAppearIn(precedence, context, out needParens)) return false; // precedence fail // Verify that the special operator can appear at this precedence // level and that its arguments fit the operator's constraints. var first = _n.Args[0]; if (name == S.Bracks) { // Careful: a[] means #of(@`[]`, a) in a type context, @`[]`(a) otherwise int minArgs = (flags&Ambiguity.TypeContext)!=0 ? 2 : 1; if (argCount < minArgs || HasPAttrs(first)) return false; } else if (name == S.QuestionMark) { if (argCount != 3 || HasPAttrs(first) || HasPAttrs(_n.Args[1]) || HasPAttrs(_n.Args[2])) return false; } else { Debug.Assert(name == S.PostInc || name == S.PostDec || name == S.IsLegal); if (argCount != 1 || HasPAttrs(first)) return false; } // Print the thing! WriteOpenParen(ParenFor.Grouping, needParens); if (name == S.Bracks) { PrintExpr(first, precedence.LeftContext(context)); Space(SpaceOpt.BeforeMethodCall); _out.Write('[', true); Space(SpaceOpt.InsideCallParens); for (int i = 1, c = _n.ArgCount; i < c; i++) { if (i != 1) WriteThenSpace(',', SpaceOpt.AfterComma); PrintExpr(_n.Args[i], StartExpr); } Space(SpaceOpt.InsideCallParens); _out.Write(']', true); } else if (name == S.QuestionMark) { PrintExpr(_n.Args[0], precedence.LeftContext(context)); PrintInfixWithSpace(S.QuestionMark, EP.IfElse, 0); PrintExpr(_n.Args[1], ContinueExpr); PrintInfixWithSpace(S.Colon, EP.IfElse, 0); PrintExpr(_n.Args[2], precedence.RightContext(context)); } else { Debug.Assert(name == S.PostInc || name == S.PostDec || name == S.IsLegal); PrintExpr(first, precedence.LeftContext(context)); _out.Write(name == S.PostInc ? "++" : name == S.PostDec ? "--" : "is legal", true); } WriteCloseParen(ParenFor.Grouping, needParens); return true; }
public SPResult AutoPrintOtherBlockStmt(Ambiguity flags) { // S.If, S.For, S.ForEach, S.Checked, S.Unchecked, S.Try var type = EcsValidators.OtherBlockStmtType(_n, Pedantics); if (type == null) { return(SPResult.Fail); } if (type == S.If) { var @else = _n.Args[2, null]; bool needCloseBrace = false; if (@else == null && (flags & Ambiguity.NoIfWithoutElse) != 0) { if (AllowExtraBraceForIfElseAmbig) { _out.Write('{', true); needCloseBrace = true; } else { return(SPResult.Fail); } } // Note: the "if" statement in particular cannot have "word" attributes // because they would create ambiguity with property declarations G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowKeywordAttrs, flags)); _out.Write("if", true); PrintWithinParens(ParenFor.KeywordCall, _n.Args[0]); var thenFlags = flags & ~(Ambiguity.ElseClause); if (@else != null) { thenFlags |= Ambiguity.NoIfWithoutElse; } bool braces = PrintBracedBlockOrStmt(_n.Args[1], thenFlags); if (@else != null) { if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) { Space(SpaceOpt.Default); } _out.Write("else", true); PrintBracedBlockOrStmt(@else, flags | Ambiguity.ElseClause); } if (needCloseBrace) { _out.Write('}', true); } return(SPResult.NeedSuffixTrivia); } G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.AllowWordAttrs, flags)); if (type == S.For) { _out.Write("for", true); PrintArgList(_n.Args.First(3), ParenFor.KeywordCall, flags, true, ';'); PrintBracedBlockOrStmt(_n.Args[3], flags); } else if (type == S.ForEach) { _out.Write("foreach", true); WriteOpenParen(ParenFor.KeywordCall); PrintExpr(_n.Args[0], EP.Equals.LeftContext(StartStmt), Ambiguity.AllowUnassignedVarDecl | Ambiguity.ForEachInitializer); _out.Space(); _out.Write("in", true); _out.Space(); PrintExpr(_n.Args[1], ContinueExpr, flags); WriteCloseParen(ParenFor.KeywordCall); PrintBracedBlockOrStmt(_n.Args[2], flags); } else if (type == S.Try) { _out.Write("try", true); bool braces = PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); for (int i = 1, c = _n.ArgCount; i < c; i++) { if (!Newline(braces ? NewlineOpt.BeforeExecutableBrace : NewlineOpt.Default)) { Space(SpaceOpt.Default); } var clause = _n.Args[i]; LNode first = clause.Args[0], second = clause.Args[1, null]; WriteOperatorName(clause.Name); if (clause.Name == S.Finally) { braces = PrintBracedBlockOrStmt(clause.Args[0], flags); } else // catch { var eVar = clause.Args[0]; if (!eVar.IsIdNamed(S.Missing)) { PrintWithinParens(ParenFor.KeywordCall, eVar, Ambiguity.AllowUnassignedVarDecl); } var when = clause.Args[1]; if (!when.IsIdNamed(S.Missing)) { Space(SpaceOpt.Default); _out.Write("when", true); PrintWithinParens(ParenFor.KeywordCall, when); } braces = PrintBracedBlockOrStmt(clause.Args[2], flags); } } } else if (type == S.Checked) // includes S.Unchecked { WriteOperatorName(_n.Name); PrintBracedBlockOrStmt(_n.Args[0], flags, NewlineOpt.BeforeSimpleStmtBrace); } return(SPResult.NeedSuffixTrivia); }
public bool AutoPrintPrefixOrInfixOperator(Precedence infixPrec, Precedence context, Ambiguity flags) { if (_n.ArgCount == 2) return AutoPrintInfixBinaryOperator(infixPrec, context, flags); else return AutoPrintPrefixUnaryOperator(PrefixOperators[_n.Name], context, flags); }
protected void PrintType(LNode n, Precedence context, Ambiguity flags = 0) { using (With(n, context, CheckOneLiner(flags | Ambiguity.TypeContext, n))) PrintCurrentType(); }
private void WriteOperatorName(Symbol name, Ambiguity flags = 0) { string opName = name.Name; if ((flags & Ambiguity.UseBacktick) != 0) PrintString(opName, '`', null); else if (opName.StartsWith("#")) _out.Write(opName.Substring(1), true); else _out.Write(opName, true); }