private void PrintLiteral(ILNode node) { object value = node.Value; if (!PrintLiteralCore(value, node.Style)) { ErrorSink.Error(node, "LesNodePrinter: Encountered unprintable literal of type {0}", value.GetType().Name); bool quote = _o.QuoteUnprintableLiterals; string unprintable; try { unprintable = value.ToString(); } catch (Exception ex) { unprintable = ex.Message; quote = true; } if (quote) { PrintStringCore('"', true, unprintable); } else { _out.Write(unprintable, true); } } }
LNode ParseHostReturnType(Token paren) { var list = ParseHostCode(paren, ParsingMode.FormalArguments); if (list.Count != 1) { Error(-1, "LLLPG: Expected a single variable declaration (or data type) after '{0}'", ToString(paren.TypeInt)); } LNode result; if (list.Count > 0) { result = list[0]; } else { result = LNode.Missing; } if (result.Calls(S.Var, 2)) { if (!result[1].IsIdNamed("result")) { ErrorSink.Error(result[1], "LLLPG requires that the result of a rule be called 'result'"); } return(result[0]); } else { return(result); } }
/// <summary>A method that is called when the indent level changed without /// a corresponding indent trigger.</summary> /// <param name="tokenBeforeNewline">Final non-whitespace token before the newline.</param> /// <param name="tokenAfterNewline">First non-whitespace token after the newline. /// Though it's a <see cref="Maybe{T}"/>, it always has a value, but this /// function can suppress its emission by setting it to NoValue.Value.</param> /// <param name="deltaIndent">Amount of unexpected indentation (positive or /// negative). On return, this parameter holds the amount by which to change /// the <see cref="CurrentIndent"/>; the default implementation leaves this /// value unchanged, which means that subsequent lines will be expected to /// be indented by the same (unexpected) amount.</param> /// <returns>true if <see cref="MakeEndOfLineToken"/> should be called as /// usual, or false to suppress EOL genertion. EOL can only be suppressed /// in case of an unexpected indent (<c>deltaIndent>0</c>), not an unindent.</returns> /// <remarks>The default implementation always returns true. It normally /// writes an error message, but switches to a warning in case /// <c>OuterIndents[OuterIndents.Count-1] == OuterIndents[OuterIndents.Count-2]</c>, /// which this class interprets as a single unindent. /// </remarks> protected virtual bool IndentChangedUnexpectedly(Token tokenBeforeNewline, ref Maybe <Token> tokenAfterNewline, ref int deltaIndent) { var pos = IndexToMsgContext(tokenAfterNewline.Or(default(Token))); if (deltaIndent > 0) { if (_errorBias >= 0) { ErrorSink.Error(pos, "Unexpected indent"); } _errorBias++; } else { if (_errorBias <= 0) { var sev = Severity.Error; if (_outerIndents.Count >= 2 && _outerIndents.Last == _outerIndents[_outerIndents.Count - 2]) { sev = Severity.Warning; } ErrorSink.Write(sev, pos, "Unindent does not match any outer indentation level"); } _errorBias--; } return(true); }
protected override void Error(int lookaheadIndex, string message) { // the fast "blitting" code path may not be able to handle errors _parseNeeded = true; var pos = new SourceRange(SourceFile, InputPosition + lookaheadIndex); if (ErrorSink != null) { ErrorSink.Error(pos, message); } else { throw new FormatException(pos + ": " + message); } }
private bool?Evaluate(LNode expr) { if (expr.IsId) { return(DefinedSymbols.Contains(expr.Name)); } else if (expr.IsLiteral && expr.Value is bool) { return((bool)expr.Value); } else if (expr.Calls(S.And, 2)) { return(Evaluate(expr.Args[0]) & Evaluate(expr.Args[1])); } else if (expr.Calls(S.Or, 2)) { return(Evaluate(expr.Args[0]) | Evaluate(expr.Args[1])); } else if (expr.Calls(S.Not, 1)) { return(!Evaluate(expr.Args[0])); } else if (expr.Calls(S.Eq, 2)) { return(Evaluate(expr.Args[0]) == Evaluate(expr.Args[1])); } else if (expr.Calls(S.Neq, 2)) { return(Evaluate(expr.Args[0]) != Evaluate(expr.Args[1])); } else { ErrorSink.Error(expr.Range, "Only simple boolean expressions with &&, ||, !, ==, !=, are supported in #if and #elif"); return(null); } }
private void Error(Token pptoken, string message) { ErrorSink.Error(pptoken.ToSourceRange(SourceFile), message); }
public override Maybe <Token> NextToken() { do { Maybe <Token> t_ = Lexer.NextToken(); redo: if (!t_.HasValue) { break; } var t = t_.Value; if (t.IsWhitespace) { AddWSToken(t); continue; } else if (t.Kind == TokenKind.Other) { switch (t.Type()) { case TokenType.PPdefine: case TokenType.PPundef: ReadRest(_rest); bool undef = t.Type() == TokenType.PPundef; if (_rest.Count == 1 && _rest[0].Type() == TokenType.Id) { if (undef) { DefinedSymbols.Remove((Symbol)_rest[0].Value); } else { DefinedSymbols.Add((Symbol)_rest[0].Value); } } else { ErrorSink.Error(t.ToSourceRange(SourceFile), "'{0}' should be followed by a single, simple identifier", undef ? "#undef" : "#define"); } continue; case TokenType.PPif: var tree = ReadRestAsTokenTree(); LNode expr = ParseExpr(tree); var cond = Evaluate(expr) ?? false; _ifRegions.Push(Pair.Create(t, cond)); t_ = SaveDirectiveAndAutoSkip(t, cond); goto redo; case TokenType.PPelse: case TokenType.PPelif: var tree_ = ReadRestAsTokenTree(); if (_ifRegions.Count == 0) { ErrorSink.Error(t.ToSourceRange(SourceFile), "Missing #if clause before '{0}'", t); _ifRegions.Push(Pair.Create(t, false)); } bool isElif = t.Type() == TokenType.PPelif, hasExpr = tree_.HasIndex(0); if (hasExpr != isElif) { Error(t, isElif ? "Missing condition on #elif" : "Unexpected tokens after #else"); } bool cond_ = true; if (hasExpr) { LNode expr_ = ParseExpr(tree_); cond_ = Evaluate(expr_) ?? false; } if (_ifRegions.Peek().B) { cond_ = false; } t_ = SaveDirectiveAndAutoSkip(t, cond_); if (cond_) { _ifRegions.Push(Pair.Create(_ifRegions.Pop().A, cond_)); } goto redo; case TokenType.PPendif: var tree__ = ReadRestAsTokenTree(); if (_ifRegions.Count == 0) { Error(t, "Missing #if before #endif"); } else { _ifRegions.Pop(); if (tree__.Count > 0) { Error(t, "Unexpected tokens after #endif"); } } _triviaList.Add(t); continue; case TokenType.PPerror: _triviaList.Add(t); Error(t, t.Value.ToString()); continue; case TokenType.PPwarning: _triviaList.Add(t); ErrorSink.Warning(t.ToSourceRange(SourceFile), t.Value.ToString()); continue; case TokenType.PPregion: _triviaList.Add(t); _regions.Push(t); continue; case TokenType.PPendregion: _triviaList.Add(t); if (_regions.Count == 0) { ErrorSink.Warning(t.ToSourceRange(SourceFile), "#endregion without matching #region"); } else { _regions.Pop(); } continue; case TokenType.PPline: _triviaList.Add(new Token(t.TypeInt, t.StartIndex, Lexer.InputPosition)); var rest = ReadRestAsTokenTree(); // TODO: use LineRemapper ErrorSink.Write(Severity.Note, t.ToSourceRange(SourceFile), "Support for #line is not implemented"); continue; case TokenType.PPpragma: _triviaList.Add(new Token(t.TypeInt, t.StartIndex, Lexer.InputPosition)); var rest_ = ReadRestAsTokenTree(); // TODO ErrorSink.Write(Severity.Note, t.ToSourceRange(SourceFile), "Support for #pragma is not implemented"); continue; } } return(t_); } while (true); // end of stream if (_ifRegions.Count > 0) { ErrorSink.Error(_ifRegions.Peek().A.ToSourceRange(SourceFile), "#if without matching #endif"); } if (_regions.Count > 0) { ErrorSink.Warning(_regions.Peek().ToSourceRange(SourceFile), "#region without matching #endregion"); } return(Maybe <Token> .NoValue); }
// An Particle is: // - an (expression) in parenthesis or a tuple // - a literal or simple identifier // - simple calls are also handled here, as a space optimization // - a token literal @{ ... } // - a prefix operator followed by an Expr // - a { block } in braces // - a [ list ] in square brackets LNode Particle() { TT la0; Token c = default(Token); Token o = default(Token); LNode result = default(LNode); TokenTree tree = default(TokenTree); // Line 192: ( TT.Id | TT.Literal | TT.At (TT.LBrack TokenTree TT.RBrack | TT.LBrace TokenTree TT.RBrace) | TT.LBrace StmtList TT.RBrace | TT.LBrack ExprList TT.RBrack | (TT.LParen|TT.SpaceLParen) ExprList TT.RParen ) switch ((TT)LA0) { case TT.Id: { var id = MatchAny(); // line 193 result = F.Id(id).SetStyle(id.Style); } break; case TT.Literal: { var lit = MatchAny(); // line 195 result = F.Literal(lit).SetStyle(lit.Style); } break; case TT.At: { o = MatchAny(); // Line 198: (TT.LBrack TokenTree TT.RBrack | TT.LBrace TokenTree TT.RBrace) la0 = (TT)LA0; if (la0 == TT.LBrack) { Skip(); tree = TokenTree(); c = Match((int)TT.RBrack); } else { Match((int)TT.LBrace); tree = TokenTree(); c = Match((int)TT.RBrace); } // line 200 result = F.Literal(tree, o.StartIndex, c.EndIndex); } break; case TT.LBrace: { o = MatchAny(); var list = StmtList(); c = Match((int)TT.RBrace); // line 203 result = F.Braces(list, o.StartIndex, c.EndIndex).SetStyle(NodeStyle.StatementBlock); } break; case TT.LBrack: { o = MatchAny(); var list = ExprList(); c = Match((int)TT.RBrack); // line 205 result = F.Call(S.Array, list, o.StartIndex, c.EndIndex, o.StartIndex, o.EndIndex, NodeStyle.Expression); } break; case TT.LParen: case TT.SpaceLParen: { // line 207 var endMarker = default(TT); o = MatchAny(); // line 208 var hasAttrList = ((TT)LA0) == TT.LBrack || ((TT)LA0) == TT.At; var list = ExprList(ref endMarker); c = Match((int)TT.RParen); // line 211 if ((endMarker == TT.Semicolon || list.Count != 1)) { result = F.Call(S.Tuple, list, o.StartIndex, c.EndIndex, o.StartIndex, o.EndIndex, NodeStyle.Expression); if ((endMarker == TT.Comma)) { var msg = "Tuples require ';' as a separator."; if ((o.Type() == TT.SpaceLParen)) { msg += " If a function call was intended, remove the space(s) before '('."; } ErrorSink.Error(list[0].Range.End, msg); } } else { result = hasAttrList ? list[0] : F.InParens(list[0], o.StartIndex, c.EndIndex); } } break; default: { // line 225 Error(0, "Expected a particle (id, literal, {braces} or (parens))."); result = MissingExpr(LT0); } break; } return(result); }