static T SetLoc <T>(this T obj, _PC pc) where T : CodeObject { obj.UserData["slang:line"] = pc.Line; obj.UserData["slang:column"] = pc.Column; obj.UserData["slang:position"] = pc.Position; return(obj); }
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 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 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 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 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); }
internal static CodeCompileUnit ParseCompileUnit(IEnumerable <Token> tokenizer) { var pc = new _PC(tokenizer); pc.Advance(false); return(_ParseCompileUnit(pc)); }
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 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 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 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 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); }
internal static CodeStatement ParseStatement(IEnumerable <Token> tokenizer, bool includeComments = false) { var pc = new _PC(tokenizer); pc.Advance(false); return(_ParseStatement(pc, includeComments)); }
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 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); }
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); }
public static CodeCompileUnit ParseCompileUnit(string text, int line, int column, long position) { var tokenizer = new SlangTokenizer(text); var pc = new _PC(tokenizer); pc.SetLocation(line, column, position); return(_ParseCompileUnit(pc)); }
public static CodeStatement ParseStatement(string text, int line, int column, long position, bool includeComments = false) { var tokenizer = new SlangTokenizer(text); var pc = new _PC(tokenizer); pc.SetLocation(line, column, position); return(_ParseStatement(pc, includeComments)); }
public static CodeCompileUnit ReadCompileUnitFrom(Stream stream, int line, int column, long position) { var tokenizer = new SlangTokenizer(stream); var pc = new _PC(tokenizer); pc.SetLocation(line, column, position); return(_ParseCompileUnit(pc)); }
public static CodeStatementCollection ReadStatementsFrom(Stream stream, int line, int column, long position, bool includeComments = false) { var tokenizer = new SlangTokenizer(stream); var pc = new _PC(tokenizer); pc.SetLocation(line, column, position); return(_ParseStatements(pc, includeComments)); }
static CodeCompileUnit _ParseCompileUnit(_PC pc) { var result = new CodeCompileUnit(); while (!pc.IsEnded) { result.Namespaces.Add(_ParseNamespace(pc)); } return(result); }
public _PC GetLookAhead() { if ((null == this._el)) { throw new NotSupportedException("This parser context does not support lookahead."); } _PC result = new _PC(this._el.LookAhead.GetEnumerator(), true); return(result); }
static void _SkipComments(_PC pc) { Token t; while ((ST.blockComment == (t = pc.Current).SymbolId || ST.lineComment == t.SymbolId) && pc.Advance()) { ; } }
public _PC GetLookAhead(bool start) { _PC result = this.GetLookAhead(); if (start) { result.EnsureStarted(); } return(result); }
static T Mark <T>(this T obj, _PC pc, bool unresolved = false) where T : CodeObject { obj.UserData["codedomgokit:visit"] = true; if (unresolved) { obj.UserData["slang:unresolved"] = true; } SetLoc(obj, pc); return(obj); }
static CodeStatementCollection _ParseStatements(_PC pc, bool includeComments = false) { var result = new CodeStatementCollection(); pc.EnsureStarted(); while (!pc.IsEnded && ST.rbrace != pc.SymbolId) { result.Add(_ParseStatement(pc, includeComments)); } return(result); }
static KeyValuePair <string, string> _ParseDirectiveKvp(_PC pc) { var s = pc.Value; var i = s.IndexOfAny(new char[] { ' ', '\t' }); if (0 > i) { return(new KeyValuePair <string, string>(s, null)); } return(new KeyValuePair <string, string>(s.Substring(0, i), s.Substring(i + 1).Trim())); }
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); }
// 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); }