public static Token Parse(Scope scope, InsertStartToken insertToken) { var code = scope.Code; var ret = new InsertToken(scope); var scopeIndent = scope.CloneIndent(); ret.AddToken(ret._startToken = insertToken); var done = false; while (!done && !code.EndOfFile) { var token = StatementToken.TryParse(scopeIndent, t => { if (t is InsertEndToken) { ret._endToken = t as InsertEndToken; done = true; } }); if (token != null) { ret.AddToken(token); } } return(ret); }
public void Parse(CodeSource source, string fileName, IEnumerable <string> parentFiles, bool visible) { if (source == null) { throw new ArgumentNullException("source"); } _source = source; _code = new CodeParser(_source.Text); _fileName = fileName; _parentFiles = parentFiles.ToArray(); FunctionFileScanning.FFUtil.FileNameIsClass(_fileName, out _className); var scope = new Scope(this, 0, ScopeHint.None, visible, _model.DefinitionProvider); scope.ClassName = _className; Scope = scope; while (_code.SkipWhiteSpace()) { var stmt = StatementToken.TryParse(scope); if (stmt != null) { AddToken(stmt); } } Span = new Span(0, _code.Length); }
/// <summary> /// Parses a set of braces from the file. /// </summary> /// <param name="scope">The current scope.</param> /// <param name="ownerDef">(optional) A definition of an object (e.g. function) that owns these braces.</param> /// <param name="funcOutliningStart">(optional) To specify a custom outlining region start position. Function use this to get the outlining to appear at the end of the previous line.</param> /// <returns>The braces token.</returns> public static BracesToken Parse(Scope scope, Definition ownerDef, int funcOutliningStart = -1) { if (ownerDef != null) { scope = scope.CloneIndent(); scope.ReturnDataType = ownerDef.DataType; } var code = scope.Code; if (!code.ReadExact('{')) { throw new InvalidOperationException("BracesToken.Parse expected next char to be '{'."); } var openBraceSpan = code.Span; var indentScope = scope.CloneIndentNonRoot(); indentScope.Hint |= ScopeHint.SuppressFunctionDefinition; var ret = new BracesToken(scope); ret._funcOutliningStart = funcOutliningStart; ret._openToken = new BraceToken(scope, openBraceSpan, ret, true); ret.AddToken(ret._openToken); while (!code.EndOfFile) { if (code.ReadExact('}')) { ret._closeToken = new BraceToken(scope, code.Span, ret, false); ret.AddToken(ret._closeToken); return(ret); } var stmt = StatementToken.TryParse(scope); if (stmt != null) { ret.AddToken(stmt); } } return(ret); }
public static ReplaceToken Parse(Scope scope, ReplaceStartToken startToken) { #if DEBUG if (startToken == null) { throw new ArgumentNullException("replaceToken"); } #endif var scopeIndent = scope.CloneIndent(); var ret = new ReplaceToken(scope, startToken); var done = false; while (!done && !scope.Code.EndOfFile) { var stmt = StatementToken.TryParse(scopeIndent, t => { if (t is ReplaceEndToken) { ret._endToken = t as ReplaceEndToken; ret._endToken.ReplaceToken = ret; done = true; } else if (ret._withToken == null) { if (t is ReplaceWithToken) { ret._withToken = t as ReplaceWithToken; ret._withToken.ReplaceToken = ret; } else { ret._oldTokens.Add(t); } } else { ret._newTokens.Add(t); } }); } return(ret); }
public static StatementToken TryParse(Scope scope, StatementParseCallback callback = null) { var code = scope.Code; if (!code.SkipWhiteSpace()) { return(null); } var ret = new StatementToken(scope); if (!code.Peek()) { return(null); } switch (code.Type) { case CodeType.Word: switch (code.Text) { case "alter": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = CreateStatement.ParseAlter(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "break": if (scope.BreakOwner != null) { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var breakToken = BreakStatement.Parse(scope, keywordToken); ret.AddToken(breakToken); if (callback != null) { callback(breakToken); } scope.BreakOwner.OnBreakAttached(breakToken); return(ret); } break; case "create": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = CreateStatement.ParseCreate(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "col": case "row": case "colff": case "page": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = RowColStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "continue": if (scope.ContinueOwner != null) { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var continueToken = ContinueStatement.Parse(scope, keywordToken); ret.AddToken(continueToken); if (callback != null) { callback(continueToken); } scope.ContinueOwner.OnContinueAttached(continueToken); return(ret); } break; case "extern": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = ExternStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "extract": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = ExtractStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "footer": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = FooterStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "for": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = ForStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "format": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = FormatStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "header": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = HeaderStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "if": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = IfStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "public": case "private": case "protected": if (scope.Model.FileContext.IsClass()) { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); ret.AddToken(keywordToken); if (callback != null) { callback(keywordToken); } return(ret); } else { break; } case "return": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = ReturnStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "select": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = SelectStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "switch": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = SwitchStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "while": { var keywordToken = new KeywordToken(scope, code.MovePeekedSpan(), code.Text); var token = WhileStatement.Parse(scope, keywordToken); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } } break; case CodeType.Preprocessor: switch (code.Text) { case "#insert": { var token = InsertToken.Parse(scope, new InsertStartToken(scope, code.MovePeekedSpan())); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "#endinsert": { var token = new InsertEndToken(scope, code.MovePeekedSpan()); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "#replace": { var token = ReplaceToken.Parse(scope, new ReplaceStartToken(scope, code.MovePeekedSpan())); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "#with": { var token = new ReplaceWithToken(scope, code.MovePeekedSpan()); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "#endreplace": { var token = new ReplaceEndToken(scope, code.MovePeekedSpan()); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "#include": { var token = IncludeToken.Parse(scope, new PreprocessorToken(scope, code.MovePeekedSpan(), code.Text)); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } default: { var token = new PreprocessorToken(scope, code.MovePeekedSpan(), code.Text); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } } case CodeType.Operator: switch (code.Text) { case "{": { // Start of a 'scope'. This is not allowed in PROBE/WBDK but allow it here anyway. var token = BracesToken.Parse(scope, null); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } case "}": { // Unmatched '}'. This is a syntax error, but since it's a statement breaking token, add it here and end the statement. var token = new OperatorToken(scope, code.MovePeekedSpan(), "}"); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } } break; } var exp = ExpressionToken.TryParse(scope, null); if (exp != null) { ret.AddToken(exp); if (callback != null) { callback(exp); } code.SkipWhiteSpace(); } if (code.ReadExact(';')) { // Empty statement. This is not allowed in PROBE/WBDK, but allow it here anyway. var token = new StatementEndToken(scope, code.Span); ret.AddToken(token); if (callback != null) { callback(token); } return(ret); } return(ret); }
private static Token ProcessWord(ExpressionToken exp, Scope scope, string word, Span wordSpan) { // Global keyword that take effect anywhere. switch (word) { case "static": return(new KeywordToken(scope, wordSpan, word)); } var code = scope.Code; if (code.PeekExact('.')) { var dotSpan = code.MovePeekedSpan(); var word2 = code.PeekWordR(); if (!string.IsNullOrEmpty(word2)) { var word2Span = code.MovePeekedSpan(); var argsPresent = (scope.Hint & ScopeHint.SuppressFunctionCall) == 0 && code.PeekExact('('); var argsOpenBracketSpan = argsPresent ? code.MovePeekedSpan() : Span.Empty; foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word)) { if (def.AllowsChild) { // When arguments are present, take only the definitions that accept arguments var childDefs = def.GetChildDefinitions(word2).Where(x => argsPresent ? x.ArgumentsRequired : true).ToArray(); if (childDefs.Any()) { ArgsToken argsToken = null; Definition childDef = null; if (argsPresent) { var openBracketToken = new OperatorToken(scope, argsOpenBracketSpan, "("); argsToken = ArgsToken.ParseAndChooseArguments(scope, openBracketToken, childDefs, out childDef); } else { childDef = childDefs[0]; } var word1Token = new IdentifierToken(scope, wordSpan, word, def); var dotToken = new DotToken(scope, dotSpan); var word2Token = new IdentifierToken(scope, word2Span, word2, childDef); var compToken = new CompositeToken(scope, childDef.DataType); compToken.AddToken(word1Token); compToken.AddToken(dotToken); compToken.AddToken(word2Token); if (argsToken != null) { compToken.AddToken(argsToken); } return(compToken); } } } } else { code.Position = dotSpan.Start; return(new UnknownToken(scope, wordSpan, word)); } } if ((scope.Hint & ScopeHint.SuppressFunctionCall) == 0 && code.PeekExact('(')) { var argsOpenBracketSpan = code.MovePeekedSpan(); foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word)) { if (def.ArgumentsRequired) { var wordToken = new IdentifierToken(scope, wordSpan, word, def); var openBracketToken = new OperatorToken(scope, argsOpenBracketSpan, "("); var argsToken = ArgsToken.Parse(scope, openBracketToken, def.Signature); var compToken = new CompositeToken(scope, def.DataType); compToken.AddToken(wordToken); compToken.AddToken(argsToken); if (def.AllowsFunctionBody && (scope.Hint & ScopeHint.SuppressFunctionDefinition) == 0) { ParseFunctionAttributes(exp, scope, compToken); if (code.PeekExact('{')) { compToken.AddToken(BracesToken.Parse(scope, def, argsToken.Span.End + 1)); } } return(compToken); } } } foreach (var def in scope.DefinitionProvider.GetAny(wordSpan.Start, word)) { if (def.ArgumentsRequired || def.RequiresChild) { continue; } return(new IdentifierToken(scope, wordSpan, word, def)); } if (StatementToken.IsStatementBreakingWord(scope, word)) { // There could be a statement without a terminating ';' before this. // This can happen if it's a macro that already includes the ';'. return(null); } if (Constants.HighlightKeywords.Contains(word)) { return(new KeywordToken(scope, wordSpan, word)); } return(new UnknownToken(scope, wordSpan, word)); }
public static SwitchStatement Parse(Scope scope, KeywordToken switchToken) { var ret = new SwitchStatement(scope, switchToken); scope = scope.Clone(); scope.BreakOwner = ret; var code = scope.Code; var expressionScope = scope.Clone(); expressionScope.Hint |= ScopeHint.SuppressDataType | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl; ret._expressionToken = ExpressionToken.TryParse(expressionScope, null); if (ret._expressionToken != null) { ret.AddToken(ret._expressionToken); } if (code.ReadExact('{')) { var bodyScope = scope.Clone(); bodyScope.Hint |= ScopeHint.SuppressFunctionDefinition; ret._bodyToken = new BracesToken(bodyScope, code.Span); ret.AddToken(ret._bodyToken); var switchDataType = ret.ExpressionDataType; while (true) { if (code.ReadExact('}')) { ret._bodyToken.AddClose(code.Span); return(ret); } if (code.ReadExactWholeWord("case")) { ret.AddToken(new KeywordToken(scope, code.Span, "case")); var caseExp = ExpressionToken.TryParse(scope, _caseEndTokens, expectedDataType: switchDataType); if (caseExp != null) { ret.AddToken(caseExp); } if (code.ReadExact(':')) { ret.AddToken(new OperatorToken(scope, code.Span, ":")); } continue; } if (code.ReadExactWholeWord("default")) { ret.AddToken(new KeywordToken(scope, code.Span, "default")); if (code.ReadExact(':')) { ret.AddToken(new OperatorToken(scope, code.Span, ":")); } continue; } var stmt = StatementToken.TryParse(bodyScope); if (stmt != null) { ret._bodyToken.AddToken(stmt); } else { break; } } } return(ret); }
public static SelectStatement Parse(Scope parentScope, KeywordToken selectToken) { var ret = new SelectStatement(parentScope, selectToken); var scope = parentScope.Clone(); scope.BreakOwner = ret; scope.ContinueOwner = ret; var code = scope.Code; if (code.ReadStringLiteral()) { ret.AddToken(new StringLiteralToken(scope, code.Span, code.Text)); } if (code.ReadExact('*')) { ret.AddToken(new OperatorToken(scope, code.Span, "*")); } if (!code.ReadExactWholeWord("from")) { return(ret); } ret.AddToken(new KeywordToken(scope, code.Span, "from")); ExtractTableDefinition extractDef = null; DkDict.Table table = null; if (code.ReadWord()) { if ((table = DkDict.Dict.GetTable(code.Text)) != null) { ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition)); } else if ((extractDef = scope.DefinitionProvider.GetAny <ExtractTableDefinition>(code.TokenStartPostion, code.Text).FirstOrDefault()) != null) { ret.AddToken(new IdentifierToken(scope, code.Span, code.Text, extractDef)); } else { ret.AddToken(new UnknownToken(scope, code.Span, code.Text)); } } if (code.ReadExactWholeWord("of")) { ret.AddToken(new KeywordToken(scope, code.Span, "of")); if (code.ReadWord()) { if ((table = DkDict.Dict.GetTable(code.Text)) != null) { ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition)); } else { ret.AddToken(new UnknownToken(scope, code.Span, code.Text)); } } } else if (code.ReadExact(',')) { ret.AddToken(new DelimiterToken(scope, code.Span)); var expectingComma = false; while (!code.EndOfFile) { if (code.PeekExact('{')) { break; } if (expectingComma) { if (code.ReadExact(',')) { ret.AddToken(new DelimiterToken(scope, code.Span)); expectingComma = false; } else { break; } } else if (code.ReadWord()) { if ((table = DkDict.Dict.GetTable(code.Text)) != null) { ret.AddToken(new TableToken(scope, code.Span, code.Text, table.Definition)); } else { ret.AddToken(new UnknownToken(scope, code.Span, code.Text)); } expectingComma = true; } else { break; } } } // WHERE and ORDER BY var gotWhere = false; var gotOrderBy = false; while (!code.EndOfFile) { if (code.PeekExact('{')) { break; } if (!gotWhere && code.ReadExactWholeWord("where")) { ret.AddToken(new KeywordToken(scope, code.Span, code.Text)); gotWhere = true; var exp = ExpressionToken.TryParse(scope, _whereEndTokens); if (exp != null) { ret.AddToken(exp); } else { break; } } else if (!gotOrderBy && code.ReadExactWholeWord("order")) { ret.AddToken(new KeywordToken(scope, code.Span, code.Text)); gotOrderBy = true; if (!code.ReadExactWholeWord("by")) { break; } ret.AddToken(new KeywordToken(scope, code.Span, code.Text)); while (!code.EndOfFile) { if (code.PeekExact('{')) { break; } if (code.ReadExact(',')) { ret.AddToken(new DelimiterToken(scope, code.Span)); continue; } if (code.ReadExactWholeWord("asc") || code.ReadExactWholeWord("desc")) { ret.AddToken(new KeywordToken(scope, code.Span, code.Text)); continue; } if (TryParseColumn(scope, ret, true, extractDef)) { continue; } break; } } else { break; } } // Body if (code.ReadExact('{')) { var braces = new BracesToken(scope); braces.AddOpen(code.Span); ret.AddToken(braces); while (!code.EndOfFile) { if (code.ReadExact('}')) { braces.AddClose(code.Span); break; } if (code.ReadExactWholeWord("for")) { braces.AddToken(new KeywordToken(scope, code.Span, "for")); if (!code.ReadExactWholeWord("each")) { continue; } braces.AddToken(new KeywordToken(scope, code.Span, "each")); if (!code.ReadExact(':')) { continue; } braces.AddToken(new OperatorToken(scope, code.Span, ":")); } else if (code.ReadExactWholeWord("before") || code.ReadExactWholeWord("after")) { braces.AddToken(new KeywordToken(scope, code.Span, code.Text)); if (!code.ReadExactWholeWord("group")) { continue; } braces.AddToken(new KeywordToken(scope, code.Span, "group")); if (code.ReadExactWholeWord("all")) { braces.AddToken(new KeywordToken(scope, code.Span, "all")); if (!code.ReadExact(':')) { continue; } braces.AddToken(new OperatorToken(scope, code.Span, ":")); } else if (TryParseColumn(scope, braces, false, extractDef)) { if (!code.ReadExact(':')) { continue; } braces.AddToken(new OperatorToken(scope, code.Span, ":")); } } else if (code.ReadExactWholeWord("default")) { braces.AddToken(new KeywordToken(scope, code.Span, "default")); if (!code.ReadExact(':')) { continue; } braces.AddToken(new OperatorToken(scope, code.Span, ":")); } else { var stmt = StatementToken.TryParse(scope); if (stmt != null) { braces.AddToken(stmt); } } } } return(ret); }