public TokenRange GetMatchingRangeIn(TokenRange range) { Func <Token, bool> pred; int dir; switch (Value) { case "(": pred = t => t.Value != ")" || t.ParenDepth != ParenDepth; dir = +1; break; case ")": pred = t => t.Value != "(" || t.ParenDepth != ParenDepth; dir = -1; break; case "{": pred = t => t.Value != "}" || t.BraceDepth != BraceDepth; dir = +1; break; case "}": pred = t => t.Value != "{" || t.BraceDepth != BraceDepth; dir = -1; break; case "<": return (new TokenRange(range.GetAllTokens(), Position + 1, AngleBracketParser.NotInsideAngleBrackets( new TokenRange(range.GetAllTokens(), Position, range.End)) .Skip(1) // skip the "<", which is considered "outside" .First() // get the ">", which is likewise "outside" .Position)); case "[": return (new TokenRange(range.GetAllTokens(), Position + 1, BracketParser.NotInsideBrackets( new TokenRange(range.GetAllTokens(), Position, range.End)) .Skip(1) // skip the "[", which is considered "outside" .First() // get the "]", which is likewise "outside" .Position)); default: throw new NotSupportedException("Can't match this token!"); } TokenRange r; if (dir == -1) { r = new TokenRange(range.GetAllTokens(), range.Begin, Position) .RevTakeWhile(pred); if (r.Begin == range.Begin) { throw new Error(SourceLine, "Syntax error: Unmatched " + Value); } } else { r = new TokenRange(range.GetAllTokens(), Position + 1, range.End) .TakeWhile(pred); if (r.End == range.End) { throw new Error(SourceLine, "Syntax error: Unmatched " + Value); } } return(r); }
IEnumerable <TokenRange> SplitParameterList(TokenRange toks, string delimiter) { if (toks.Begin == toks.End) { yield break; } while (true) { Token comma = AngleBracketParser.NotInsideAngleBrackets(toks) .FirstOrDefault(t => t.Value == delimiter && t.ParenDepth == toks.First().ParenDepth); if (comma == null) { break; } yield return(range(toks.Begin, comma.Position)); toks = range(comma.Position + 1, toks.End); } yield return(toks); }
IEnumerable <Token> NormalizeWhitespace(IEnumerable <Token> tokens) { bool inWhitespace = false; bool leading = true; foreach (var tok in tokens) { if (!tok.IsWhitespace) { if (inWhitespace && !leading) { yield return new Token { Value = " " } } ; inWhitespace = false; yield return(tok); leading = false; } else { inWhitespace = true; } } } void ParseDeclaration(TokenRange tokens, out Token name, out TokenRange type, out TokenRange initializer, out bool constructorSyntax) { initializer = null; TokenRange beforeInitializer = tokens; constructorSyntax = false; Token equals = AngleBracketParser.NotInsideAngleBrackets(tokens) .FirstOrDefault(t => t.Value == "=" && t.ParenDepth == tokens.First().ParenDepth); if (equals != null) { // type name = initializer; beforeInitializer = range(tokens.Begin, equals.Position); initializer = range(equals.Position + 1, tokens.End); } else { Token paren = AngleBracketParser.NotInsideAngleBrackets(tokens) .FirstOrDefault(t => t.Value == "("); if (paren != null) { // type name(initializer); constructorSyntax = true; beforeInitializer = range(tokens.Begin, paren.Position); initializer = range(paren.Position + 1, tokens.End) .TakeWhile(t => t.ParenDepth > paren.ParenDepth); } } name = beforeInitializer.Last(NonWhitespace); if (beforeInitializer.Begin == name.Position) { throw new Error(beforeInitializer.First().SourceLine, "Declaration has no type."); } type = range(beforeInitializer.Begin, name.Position); } VarDeclaration ParseVarDeclaration(TokenRange tokens) { Token name; TokenRange type, initializer; bool constructorSyntax; ParseDeclaration(tokens, out name, out type, out initializer, out constructorSyntax); return(new VarDeclaration { name = name.Value, type = str(NormalizeWhitespace(type)), initializer = initializer == null ? "" : str(NormalizeWhitespace(initializer)), initializerConstructorSyntax = constructorSyntax }); }