static CodeCommentStatement _ParseCommentStatement(_PC pc, bool docComments = false) { var s = pc.Value; switch (pc.SymbolId) { case ST.lineComment: pc.Advance(false); if (docComments && s.StartsWith("///", StringComparison.InvariantCulture)) { if (3 < s.Length && char.IsWhiteSpace(s[3])) { return(new CodeCommentStatement(s.Substring(4).TrimEnd('\r'), true)); } return(new CodeCommentStatement(s.Substring(3).TrimEnd('\r'), true)); } if (2 < s.Length && char.IsWhiteSpace(s[2])) { return(new CodeCommentStatement(s.Substring(3).TrimEnd('\r'))); } return(new CodeCommentStatement(s.Substring(2).TrimEnd('\r'))); case ST.blockComment: pc.Advance(false); return(new CodeCommentStatement(s.Substring(2, s.Length - 4))); } pc.Error("Expecting line comment or block comment"); return(null); }
static CodeNamespaceImportCollection _ParseNamespaceImports(_PC pc) { var result = new CodeNamespaceImportCollection(); while (ST.keyword == pc.SymbolId && "using" == pc.Value) { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated using declaration", "input"); } if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in using declaration", "input"); } var ns = _ParseNamespaceName(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated using declaration", "input"); } if (ST.semi != pc.SymbolId) { throw new ArgumentException("Expecting ; in using declaration", "input"); } pc.Advance(); _SkipComments(pc); result.Add(new CodeNamespaceImport(ns)); } return(result); }
static CodeGotoStatement _ParseGotoStatement(_PC pc) { // expects to be on goto. pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated goto statement", "input"); } if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in goto statement", "input"); } var g = new CodeGotoStatement(pc.Value); pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated goto statement", "input"); } if (ST.semi != pc.SymbolId) { throw new ArgumentException("Expecting ; after goto statement", "input"); } pc.Advance(); return(g); }
static CodeStatement _ParseVariableDeclarationStatement(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; CodeTypeReference ctr = null; if (ST.varType != pc.SymbolId) { ctr = _ParseType(pc); } else { pc.Advance(); } var id = _ParseIdentifier(pc); CodeExpression init = null; if (ST.eq == pc.SymbolId) { pc.Advance(); init = _ParseExpression(pc); } else if (null == ctr) { pc.Error("Variable declaration using var must have an initializer", l, c, p); } if (ST.semi != pc.SymbolId) { pc.Error("Expecting ; in variable declaration statement"); } pc.Advance(); return(new CodeVariableDeclarationStatement(ctr, id, init).Mark(l, c, p, null == ctr)); }
static CodeIterationStatement _ParseWhileStatement(_PC pc) { // expects to be on while. if (!pc.Advance()) { throw new ArgumentException("Unterminated while statement", "input"); } _SkipComments(pc); if (ST.lparen != pc.SymbolId || !pc.Advance()) { throw new ArgumentException("Unterminated while statement", "input"); } _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated while statement", "input"); } var cnd = _ParseExpression(pc); _SkipComments(pc); if (ST.rparen != pc.SymbolId || !pc.Advance()) { throw new ArgumentException("Unterminated while statement", "input"); } _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated while statement", "input"); } var result = new CodeIterationStatement(new CodeSnippetStatement(), cnd, new CodeSnippetStatement()); if (ST.lbrace == pc.SymbolId) { if (!pc.Advance()) { throw new ArgumentException("Unterminated while statement", "input"); } while (!pc.IsEnded && ST.rbrace != pc.SymbolId) { result.Statements.Add(_ParseStatement(pc, true)); } if (ST.rbrace != pc.SymbolId) { throw new ArgumentException("Unterminated while statement", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { return(result); } } else { result.Statements.Add(_ParseStatement(pc)); } _SkipComments(pc); return(result); }
static CodeThrowExceptionStatement _ParseThrowStatement(_PC pc) { // expects to be on throw pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated throw statement", "input"); } if (ST.semi == pc.SymbolId) { pc.Advance(); return(new CodeThrowExceptionStatement()); } var e = _ParseExpression(pc); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated throw statement", "input"); } if (ST.semi != pc.SymbolId) { throw new ArgumentException("Invalid expression in throw statement", "input"); } pc.Advance(); return(new CodeThrowExceptionStatement(e)); }
static CodeStatement _ParseWhileStatement(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; if (ST.whileKeyword != pc.SymbolId) { pc.Error("Expecting while"); } pc.Advance(); if (ST.lparen != pc.SymbolId) { pc.Error("Expecting ( in while statement"); } pc.Advance(); var test = _ParseExpression(pc); if (ST.rparen != pc.SymbolId) { pc.Error("Expecting ) in while statement"); } pc.Advance(); var result = new CodeIterationStatement(new CodeSnippetStatement().SetLoc(l, c, p), test, new CodeSnippetStatement().SetLoc(l, c, p)).Mark(l, c, p); result.Statements.AddRange(_ParseStatementOrBlock(pc)); return(result); }
static CodeTypeReference _ParseTypeGenerics(_PC pc, CodeTypeReference result = null) { _SkipComments(pc); if (null == result) { result = new CodeTypeReference(); } //result.UserData["slang:unresolved"] = true; while (ST.gt != pc.SymbolId) { _SkipComments(pc); if (!pc.Advance()) { throw new ArgumentException("Unterminated generic specification", "input"); } _SkipComments(pc); var tp = _ParseTypeRef(pc); tp.Options = CodeTypeReferenceOptions.GenericTypeParameter; result.TypeArguments.Add(tp); if (ST.gt != pc.SymbolId && ST.comma != pc.SymbolId) { throw new ArgumentException("Invalid token in generic specification", "input"); } } if (ST.gt != pc.SymbolId) { throw new ArgumentException("Unterminated generic specification", "input"); } _SkipComments(pc); pc.Advance(); return(result); }
static CodeMemberField _ParseEnumField(_PC pc, CodeTypeReference enumType) { _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Expecting enum field declaration", "input"); } IList <KeyValuePair <string, CodeAttributeDeclaration> > custAttrs = null; if (ST.lbracket == pc.SymbolId) { custAttrs = _ParseCustomAttributes(pc); } _SkipComments(pc); if (pc.IsEnded || ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting enum field declaration", "input"); } var result = new CodeMemberField(); result.Name = pc.Value; _AddCustomAttributes(custAttrs, null, result.CustomAttributes); _AddCustomAttributes(custAttrs, "field", result.CustomAttributes); if (null != custAttrs && custAttrs.Count > result.CustomAttributes.Count) { throw new ArgumentException("Invalid custom attribute targets", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded || (ST.eq != pc.SymbolId && ST.comma != pc.SymbolId && ST.rbrace != pc.SymbolId)) { throw new ArgumentException("Expecting enum field value, }, or ,", "input"); } if (ST.eq == pc.SymbolId) { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Expecting enum field value", "input"); } result.InitExpression = _ParseExpression(pc); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Expecting , or } in enum declaration", "input"); } } if (ST.comma == pc.SymbolId) { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Expecting enum field value", "input"); } } return(result); }
static CodeStatement _ParseIfStatement(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; if (ST.ifKeyword != pc.SymbolId) { pc.Error("Expecting if"); } pc.Advance(); if (ST.lparen != pc.SymbolId) { pc.Error("Expecting ( in if statement"); } pc.Advance(); var test = _ParseExpression(pc); if (ST.rparen != pc.SymbolId) { pc.Error("Expecting ) in if statement"); } pc.Advance(); var result = new CodeConditionStatement(test).Mark(l, c, p); result.TrueStatements.AddRange(_ParseStatementOrBlock(pc)); if (ST.elseKeyword == pc.SymbolId) { pc.Advance(); result.FalseStatements.AddRange(_ParseStatementOrBlock(pc)); } return(result); }
static CodeAttributeArgumentCollection _ParseCustomAttributeArguments(_PC pc) { var result = new CodeAttributeArgumentCollection(); if (ST.lparen != pc.SymbolId) { return(result); } if (!pc.Advance()) { throw new ArgumentException("Unterminated argument list", "input"); } var named = false; while (ST.rparen != pc.SymbolId) { var arg = new CodeAttributeArgument(); if (ST.identifier == pc.SymbolId) { var s = pc.Value; var pc2 = pc.GetLookAhead(); pc2.EnsureStarted(); pc2.Advance(); _SkipComments(pc2); if (ST.eq == pc2.SymbolId) { pc.Advance(); _SkipComments(pc); pc.Advance(); arg.Name = s; arg.Value = _ParseExpression(pc); result.Add(arg); named = true; continue; } } if (named) { throw new ArgumentException("Named custom attribute arguments must follow the unnamed arguments.", "input"); } var exp = _ParseExpression(pc); _SkipComments(pc); arg.Value = exp; result.Add(arg); if (ST.comma == pc.SymbolId) { if (!pc.Advance()) { throw new ArgumentException("Unterminated argument list.", "input"); } } } if (ST.rparen != pc.SymbolId) { throw new ArgumentException("Unterminated argument list.", "input"); } pc.Advance(); return(result); }
static CodeStatement _ParseForStatement(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; if (ST.forKeyword != pc.SymbolId) { pc.Error("Expecting for"); } pc.Advance(); if (ST.lparen != pc.SymbolId) { pc.Error("Expecting ( in for statement"); } pc.Advance(); var init = _ParseStatement(pc, false); var test = _ParseExpression(pc); if (ST.semi != pc.SymbolId) { pc.Error("Expecting ; in for statement"); } pc.Advance(); CodeStatement inc = null; CodeExpression ince = null; if (ST.rparen != pc.SymbolId) { ince = _ParseExpression(pc); } if (ST.rparen != pc.SymbolId) { pc.Error("Expecting ) in for statement"); } if (null == ince) { inc = new CodeSnippetStatement().SetLoc(pc); } else { var bo = ince as CodeBinaryOperatorExpression; if (null != bo && CodeBinaryOperatorType.Assign == bo.Operator) { // probably not an attach or detach statement but we can't rule it out var ur = bo.UserData.Contains("slang:unresolved"); inc = new CodeAssignStatement(bo.Left, bo.Right).Mark(ince, ur); } else { inc = new CodeExpressionStatement(ince).Mark(ince); } } pc.Advance(); var result = new CodeIterationStatement(init, test, inc).Mark(l, c, p); result.Statements.AddRange(_ParseStatementOrBlock(pc)); return(result); }
// these aren't true expressions, they're just part of method and indexer parameter declarations // that's why we parse them here static CodeParameterDeclarationExpression _ParseParamDecl(_PC pc, bool allowDirection = true) { var attrs = new CodeAttributeDeclarationCollection(); if (ST.lbracket == pc.SymbolId) { _AddCustomAttributes(_ParseCustomAttributes(pc), null, attrs); } FieldDirection d = FieldDirection.In; _SkipComments(pc); if (allowDirection) { if (ST.keyword == pc.SymbolId) { switch (pc.Value) { case "out": d = FieldDirection.Out; pc.Advance(); _SkipComments(pc); break; case "ref": d = FieldDirection.Ref; pc.Advance(); _SkipComments(pc); break; default: break; } } } var ctr = _ParseTypeRef(pc); _SkipComments(pc); if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in parameter declaration", "input"); } var result = new CodeParameterDeclarationExpression(ctr, pc.Value); result.Direction = d; if (null != attrs) { result.CustomAttributes.AddRange(attrs); } pc.Advance(); return(result); }
static CodeTypeReference _ParseArrayTypeModifiers(CodeTypeReference type, _PC pc) { var mods = new List <int>(); var result = type; _SkipComments(pc); var t = pc.Current; var ai = 1; var inBrace = true; while (pc.Advance()) { _SkipComments(pc); t = pc.Current; if (inBrace && ST.comma == t.SymbolId) { ++ai; continue; } else if (ST.rbracket == t.SymbolId) { mods.Add(ai); ai = 1; if (!pc.Advance()) { break; } inBrace = false; if (ST.lbracket != pc.SymbolId) { break; } else { inBrace = true; } } else { break; } } for (var i = mods.Count - 1; -1 < i; --i) { var ctr = new CodeTypeReference(); ctr.ArrayElementType = result; ctr.ArrayRank = mods[i]; result = ctr; } return(result); }
internal static CodeStatement ParseStatement(IEnumerable <Token> tokenizer, bool includeComments = false) { var pc = new _PC(tokenizer); pc.Advance(false); return(_ParseStatement(pc, includeComments)); }
internal static CodeCompileUnit ParseCompileUnit(IEnumerable <Token> tokenizer) { var pc = new _PC(tokenizer); pc.Advance(false); return(_ParseCompileUnit(pc)); }
static HashSet <string> _ParseTypeAttributes(_PC pc) { var result = new HashSet <string>(); _SkipComments(pc); var more = true; while (more && !pc.IsEnded && ST.keyword == pc.SymbolId) { switch (pc.Value) { case "static": case "abstract": case "protected": case "internal": case "public": case "private": result.Add(pc.Value); pc.Advance(); _SkipComments(pc); break; default: more = false; break; } } return(result); }
static CodeCommentStatement _ParseCommentStatement(_PC pc) { // expects to be on comment var s = pc.Value; if (ST.lineComment == pc.SymbolId) { pc.Advance(); if (s.StartsWith("///")) { return(new CodeCommentStatement(s.Substring(3).Trim(), true)); } return(new CodeCommentStatement(s.Substring(2).Trim())); } pc.Advance(); return(new CodeCommentStatement(s.Substring(2, s.Length - 4).Trim())); }
static void _SkipComments(_PC pc) { Token t; while ((ST.blockComment == (t = pc.Current).SymbolId || ST.lineComment == t.SymbolId) && pc.Advance()) { ; } }
static CodeTypeDeclaration _ParseEnum(_PC pc, CodeTypeDeclaration result) { var bt = new CodeTypeReference(typeof(int)); if (ST.colon == pc.SymbolId) { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated enum declaration", "input"); } bt = _ParseTypeRef(pc); result.BaseTypes.Add(bt); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated enum declaration", "input"); } } if (ST.lbrace != pc.SymbolId) { throw new ArgumentException("Expecting enum body", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated enum declaration", "input"); } while (ST.rbrace != pc.SymbolId) { _SkipComments(pc); result.Members.Add(_ParseEnumField(pc, bt)); } if (ST.rbrace != pc.SymbolId) { throw new ArgumentException("Unterminated enum declaration", "input"); } pc.Advance(); return(result); }
static CodeParameterDeclarationExpressionCollection _ParseParamDecls(_PC pc, int endSym = ST.rparen, bool allowDirection = true) { var result = new CodeParameterDeclarationExpressionCollection(); while (!pc.IsEnded && endSym != pc.SymbolId) { var p = _ParseParamDecl(pc, allowDirection); result.Add(p); if (ST.comma != pc.SymbolId) { break; } pc.Advance(); _SkipComments(pc); } if (endSym != pc.SymbolId) { throw new ArgumentException("Unterminated parameter declarations", "input"); } pc.Advance(); return(result); }
static CodeStatementCollection _ParseStatementOrBlock(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; CodeStatementCollection result; if (ST.lbrace == pc.SymbolId) { pc.Advance(); result = _ParseStatements(pc, true); if (ST.rbrace != pc.SymbolId) { pc.Error("Unterminated statement block", l, c, p); } pc.Advance(); return(result); } result = new CodeStatementCollection(); result.Add(_ParseStatement(pc, false)); return(result); }
internal static CodeStatementCollection ParseStatements(IEnumerable <Token> tokenizer, bool includeComments = false) { var pc = new _PC(tokenizer); pc.Advance(false); var result = new CodeStatementCollection(); while (!pc.IsEnded && ST.rbrace != pc.SymbolId) { result.Add(_ParseStatement(pc, includeComments)); } return(result); }
static CodeCatchClause _ParseCatchClause(_PC pc) { if (ST.catchKeyword != pc.SymbolId) { pc.Error("Expecting catch"); } pc.Advance(); if (ST.lparen != pc.SymbolId) { pc.Error("Expecting ( in catch clause"); } pc.Advance(); var result = new CodeCatchClause(); result.CatchExceptionType = _ParseType(pc); if (ST.rparen != pc.SymbolId) { result.LocalName = _ParseIdentifier(pc); } if (ST.rparen != pc.SymbolId) { pc.Error("Expecting ) in catch clause"); } pc.Advance(); if (ST.lbrace != pc.SymbolId) { pc.Error("Expecting { in catch clause"); } pc.Advance(); result.Statements.AddRange(_ParseStatements(pc, true)); if (ST.rbrace != pc.SymbolId) { pc.Error("Expecting } in catch clause"); } pc.Advance(); return(result); }
static string _ParseNamespaceName(_PC pc) { var result = ""; while (ST.identifier == pc.SymbolId) { if (0 < result.Length) { result = string.Concat(result, ".", pc.Value); } else { result = pc.Value; } pc.Advance(); _SkipComments(pc); if (ST.dot == pc.SymbolId) { pc.Advance(); _SkipComments(pc); } } return(result); }
static CodeStatement _ParseTryCatchFinallyStatement(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; if (ST.tryKeyword != pc.SymbolId) { pc.Error("Expecting try"); } pc.Advance(); var result = new CodeTryCatchFinallyStatement().Mark(l, c, p); if (ST.lbrace != pc.SymbolId) { pc.Error("Expecting { in try statement"); } pc.Advance(); result.TryStatements.AddRange(_ParseStatements(pc, true)); if (ST.rbrace != pc.SymbolId) { pc.Error("Expecting } in try statement"); } pc.Advance(); while (ST.catchKeyword == pc.SymbolId) { result.CatchClauses.Add(_ParseCatchClause(pc)); } if (0 == result.CatchClauses.Count && ST.finallyKeyword != pc.SymbolId) { pc.Error("Expecting catch or finally"); } if (ST.finallyKeyword == pc.SymbolId) { pc.Advance(); if (ST.lbrace != pc.SymbolId) { pc.Error("Expecting { in finally statement"); } pc.Advance(); result.FinallyStatements.AddRange(_ParseStatements(pc, true)); if (ST.rbrace != pc.SymbolId) { pc.Error("Expecting } in finally statement"); } pc.Advance(); } return(result); }
static string _ParseNamespaceName(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; var result = ""; while (!pc.IsEnded && ST.lbrace != pc.SymbolId && ST.semi != pc.SymbolId) { if (0 < result.Length) { result += "."; } result += _ParseIdentifier(pc); if (ST.lbrace == pc.SymbolId || ST.semi == pc.SymbolId) { break; } var l2 = pc.Line; var c2 = pc.Column; var p2 = pc.Position; if (ST.dot != pc.SymbolId) { pc.Error("Expecting . in namespace name"); } pc.Advance(); if (ST.lbrace == pc.SymbolId || ST.semi == pc.SymbolId) { pc.Error("Expecting identifier in namespace name", l2, c2, p2); } } if ("" == result) { pc.Error("Expecting identifier in namespace name", l, c, p); } return(result); }
static CodeCompileUnit _ParseCompileUnit(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; var result = new CodeCompileUnit().Mark(l, c, p); var ns = new CodeNamespace().Mark(l, c, p); result.Namespaces.Add(ns); while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { switch (pc.SymbolId) { case ST.directive: var d = _ParseDirective(pc) as CodeDirective; if (null != d) { result.StartDirectives.Add(d); } break; case ST.blockComment: ns.Comments.Add(_ParseCommentStatement(pc)); break; case ST.lineComment: ns.Comments.Add(_ParseCommentStatement(pc, true)); break; } } while (ST.usingKeyword == pc.SymbolId) { while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { pc.Advance(false); } var l2 = pc.Line; var c2 = pc.Column; var p2 = pc.Position; pc.Advance(); var nsi = new CodeNamespaceImport(_ParseNamespaceName(pc)).SetLoc(l2, c2, p2); if (ST.semi != pc.SymbolId) { pc.Error("Expecting ; in using declaration"); } pc.Advance(false); ns.Imports.Add(nsi); } while (ST.lbracket == pc.SymbolId) { var pc2 = pc.GetLookAhead(true); pc2.Advance(); if (ST.assemblyKeyword != pc2.SymbolId) { break; } result.AssemblyCustomAttributes.AddRange(_ParseAttributeGroup(pc, false).Value); } while (!pc.IsEnded) { var startDirs = new CodeDirectiveCollection(); var comments = new CodeCommentStatementCollection(); CodeLinePragma lp = null; while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { switch (pc.SymbolId) { case ST.directive: var d = _ParseDirective(pc); var llp = d as CodeLinePragma; if (null != llp) { lp = llp; } else if (null != d) { startDirs.Add(d as CodeDirective); } break; case ST.blockComment: comments.Add(_ParseCommentStatement(pc)); break; case ST.lineComment: comments.Add(_ParseCommentStatement(pc, true)); break; } } if (ST.namespaceKeyword == pc.SymbolId) { var nns = _ParseNamespace(pc); nns.Comments.AddRange(comments); result.Namespaces.Add(nns); } else { var t = _ParseTypeDecl(pc, false, pc.Line, pc.Column, pc.Position, null); t.Comments.AddRange(comments); t.StartDirectives.AddRange(startDirs); t.LinePragma = lp; ns.Types.Add(t); } } return(result); }
static CodeNamespace _ParseNamespace(_PC pc) { var l = pc.Line; var c = pc.Column; var p = pc.Position; var result = new CodeNamespace().Mark(l, c, p); while (ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId || ST.directive == pc.SymbolId) { if (ST.directive != pc.SymbolId) { result.Comments.Add(_ParseCommentStatement(pc, true)); } } if (ST.namespaceKeyword != pc.SymbolId) { pc.Error("Expecting namespace"); } pc.Advance(); result.Name = _ParseNamespaceName(pc); if (ST.lbrace != pc.SymbolId) { pc.Error("Expecing { in namespace declaration"); } pc.Advance(false); if (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { var pc2 = pc.GetLookAhead(true); if (ST.usingKeyword == pc2.SymbolId) { pc.Advance(); } } while (ST.usingKeyword == pc.SymbolId) { while (ST.directive == pc.SymbolId || ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { pc.Advance(false); } var l2 = pc.Line; var c2 = pc.Column; var p2 = pc.Position; pc.Advance(); var nsi = new CodeNamespaceImport(_ParseNamespaceName(pc)).SetLoc(l2, c2, p2); if (ST.semi != pc.SymbolId) { pc.Error("Expecting ; in using declaration"); } pc.Advance(false); result.Imports.Add(nsi); } while (ST.rbrace != pc.SymbolId) { result.Types.Add(_ParseTypeDecl(pc, false, pc.Line, pc.Column, pc.Position, null)); } if (ST.rbrace != pc.SymbolId) { pc.Error("Unterminated namespace declaration", l, c, p); } pc.Advance(false); return(result); }
static CodeTypeDeclaration _ParseType(_PC pc, bool isNested = false) { var result = new CodeTypeDeclaration(); IList <KeyValuePair <string, CodeAttributeDeclaration> > custAttrs = null; HashSet <string> attrs = null; if (!isNested) { var comments = new CodeCommentStatementCollection(); while (ST.lineComment == pc.SymbolId || ST.blockComment == pc.SymbolId) { comments.Add(_ParseCommentStatement(pc)); } custAttrs = _ParseCustomAttributes(pc); attrs = _ParseTypeAttributes(pc); if (attrs.Contains("static")) { throw new NotSupportedException("Explicitly static classes are not supported."); } result.Attributes = _BuildMemberAttributes(attrs); result.TypeAttributes = (isNested)?_BuildNestedTypeAttributes(attrs): _BuildTopLevelTypeAttributes(attrs); result.Comments.AddRange(comments); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (ST.keyword == pc.SymbolId && "partial" == pc.Value) { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } result.IsPartial = true; } _AddCustomAttributes(custAttrs, null, result.CustomAttributes); if (null != custAttrs && custAttrs.Count > result.CustomAttributes.Count) { throw new ArgumentException("Invalid custom attribute targets", "input"); } } if (ST.keyword != pc.SymbolId) { throw new ArgumentException("Expecting class, struct, enum, or interface", "input"); } switch (pc.Value) { case "class": result.IsClass = true; break; case "struct": result.IsStruct = true; break; case "enum": if (result.IsPartial) { throw new ArgumentException("Enums cannot be partial", "input"); } result.IsEnum = true; break; case "interface": result.IsInterface = true; break; default: throw new ArgumentException("Expecting class, struct, enum, or interface", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in type declaration", "input"); } result.Name = pc.Value; pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (result.IsEnum) { return(_ParseEnum(pc, result)); } if (ST.lt == pc.SymbolId) { // parse the generic type arguments pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated generic type parameter specification", "input"); } if (ST.gt == pc.SymbolId) { throw new ArgumentException("Generic type parameter specification cannot be empty", "input"); } while (!pc.IsEnded && ST.gt != pc.SymbolId) { var custAttrs2 = _ParseCustomAttributes(pc); if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in type parameter specification", "input"); } var tp = new CodeTypeParameter(pc.Value); _AddCustomAttributes(custAttrs2, null, tp.CustomAttributes); if (tp.CustomAttributes.Count < custAttrs2.Count) { throw new ArgumentException("Invalid target in custom attribute declaration on generic type parameter", "input"); } result.TypeParameters.Add(tp); pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated generic type parameter specification", "input"); } if (ST.comma != pc.SymbolId) { break; } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated generic type parameter specification", "input"); } } if (pc.IsEnded) { throw new ArgumentException("Unterminated generic type parameter specification", "input"); } if (ST.gt != pc.SymbolId) { throw new ArgumentException("Illegal generic type parameter specification", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated generic type parameter specification", "input"); } } if (ST.colon == pc.SymbolId) // parse base types { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (ST.lbrace == pc.SymbolId || (ST.identifier == pc.SymbolId && "where" == pc.Value)) { throw new ArgumentException("Empty base type specifiers", "input"); } while (!pc.IsEnded && !(ST.lbrace == pc.SymbolId || (ST.identifier == pc.SymbolId && "where" == pc.Value))) { result.BaseTypes.Add(_ParseTypeRef(pc)); _SkipComments(pc); } _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } } if (ST.identifier == pc.SymbolId && "where" == pc.Value) // parse type constrants { pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type constraint", "input"); } var moved = false; while (!pc.IsEnded && ST.lbrace != pc.SymbolId) { moved = true; if (ST.identifier != pc.SymbolId) { throw new ArgumentException("Expecting identifier in type constraint", "input"); } var cp = _LookupTypeParameter(result.TypeParameters, pc.Value); pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type constraint", "input"); } if (ST.colon != pc.SymbolId) { throw new ArgumentException("Expecting : in type constraint", "input"); } pc.Advance(); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type constraint", "input"); } cp.Constraints.Add(_ParseTypeRef(pc)); _SkipComments(pc); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (ST.comma == pc.SymbolId) { pc.Advance(); _SkipComments(pc); if (ST.lbrace == pc.SymbolId) { throw new ArgumentException("Unterminated type constraint", "input"); } } } if (!moved) { throw new ArgumentException("Unterminated type constraint", "input"); } } if (ST.lbrace != pc.SymbolId) { throw new ArgumentException("Expecting { in type definition", "input"); } pc.Advance(); if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } while (!pc.IsEnded && ST.rbrace != pc.SymbolId) { result.Members.Add(_ParseMember(pc, result.Name)); } if (pc.IsEnded) { throw new ArgumentException("Unterminated type declaration", "input"); } if (ST.rbrace != pc.SymbolId) { throw new ArgumentException("Illegal member declaration in type", "input"); } pc.Advance(); return(result); }