public static WhileStatement Parse(Scope scope, KeywordToken whileToken) { var code = scope.Code; var ret = new WhileStatement(scope, whileToken); scope = scope.Clone(); scope.BreakOwner = ret; scope.ContinueOwner = ret; // Expression var expressionScope = scope.Clone(); expressionScope.Hint |= ScopeHint.SuppressDataType | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl; ret._expressionToken = ExpressionToken.TryParse(scope, null); if (ret._expressionToken != null) { ret.AddToken(ret._expressionToken); if (code.PeekExact('{')) { var bodyScope = scope.Clone(); bodyScope.Hint |= ScopeHint.SuppressFunctionDefinition; ret.AddToken(ret._bodyToken = BracesToken.Parse(bodyScope, null)); } } return(ret); }
private static void ParseFunctionAttributes(ExpressionToken exp, Scope scope, CompositeToken funcToken) { var code = scope.Code; string word; ExpressionToken exp2; while (true) { word = code.PeekWordR(); switch (word) { case "description": case "prompt": case "comment": case "accel": funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text)); exp2 = ExpressionToken.TryParse(scope, _functionAttribsEndTokens); if (exp2 != null) { funcToken.AddToken(exp2); } break; case "nomenu": funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text)); break; case "BEGINHLP": funcToken.AddToken(new KeywordToken(scope, code.MovePeekedSpan(), code.Text)); while (code.ReadStringLiteral()) { funcToken.AddToken(new StringLiteralToken(scope, code.Span, code.Text)); } if (code.ReadExactWholeWord("ENDHLP")) { funcToken.AddToken(new KeywordToken(scope, code.Span, code.Text)); } break; case "tag": if (code.ReadTagName()) { funcToken.AddToken(new KeywordToken(scope, code.Span, code.Text)); } exp2 = ExpressionToken.TryParse(scope, _functionAttribsEndTokens); if (exp2 != null) { funcToken.AddToken(exp2); } break; default: return; } } }
public static ArrayBracesToken Parse(Scope scope) { var code = scope.Code; if (!code.ReadExact('[')) { throw new InvalidOperationException("ArrayBracesToken.Parse expected next char to be '['."); } var openBracketSpan = code.Span; var indentScope = scope.CloneIndentNonRoot(); indentScope.Hint |= ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressStatementStarts; var ret = new ArrayBracesToken(scope); ret.AddToken(ret._openToken = new ArrayBraceToken(scope, openBracketSpan, ret, true)); while (!code.EndOfFile) { if (code.ReadExact(']')) { ret.AddToken(ret._closeToken = new ArrayBraceToken(scope, code.Span, ret, false)); break; } if (code.ReadExact(',')) { ret.AddToken(new DelimiterToken(indentScope, code.Span)); continue; } var exp = ExpressionToken.TryParse(indentScope, _endTokens); if (exp != null) { ret.AddToken(exp); } else { break; } } return(ret); }
/// <summary> /// Parses a set of brackets containing arguments. /// </summary> /// <param name="scope">The scope for this token.</param> /// <param name="openBracketToken">The open bracket token.</param> /// <param name="sig">(optional) A signature for the function being called.</param> /// <returns>A new argument token.</returns> /// <remarks>This function assumes the opening bracket has already been read from the stream.</remarks> public static ArgsToken Parse(Scope scope, OperatorToken openBracketToken, FunctionSignature sig) { var code = scope.Code; var ret = new ArgsToken(scope, openBracketToken); var argIndex = 0; scope = scope.Clone(); scope.Hint |= ScopeHint.SuppressStatementStarts; ret._sig = sig; var args = sig != null?sig.Arguments.ToArray() : ArgumentDescriptor.EmptyArray; while (code.SkipWhiteSpace()) { code.Peek(); if (code.Text == ")") { ret.AddToken(new OperatorToken(scope, code.MovePeekedSpan(), ")")); ret._terminated = true; return(ret); } if (code.Text == ",") { ret.AddToken(new OperatorToken(scope, code.MovePeekedSpan(), ",")); argIndex++; continue; } var dataType = argIndex < args.Length ? args[argIndex].DataType : null; var exp = ExpressionToken.TryParse(scope, _endTokens, expectedDataType: dataType); if (exp != null) { ret.AddToken(exp); } else { break; } } return(ret); }
public static IfStatement Parse(Scope scope, KeywordToken ifToken) { var code = scope.Code; var ret = new IfStatement(scope); ret.AddToken(ifToken); var scopeIndent = scope.Clone(); scopeIndent.Hint |= ScopeHint.NotOnRoot | ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressVarDecl; ret._condition = ExpressionToken.TryParse(scopeIndent, null); if (ret._condition != null) { ret.AddToken(ret._condition); } if (code.PeekExact('{')) { ret.AddToken(ret._trueBody = BracesToken.Parse(scopeIndent, null)); if (code.ReadExactWholeWord("else")) { ret.AddToken(ret._elseToken = new KeywordToken(scopeIndent, code.Span, "else")); if (code.PeekExact('{')) { ret.AddToken(ret._falseBody = BracesToken.Parse(scopeIndent, null)); } else if (code.ReadExactWholeWord("if")) { var ifToken2 = new KeywordToken(scopeIndent, code.Span, "if"); ret.AddToken(ret._falseBody = IfStatement.Parse(scopeIndent, ifToken2)); } } } 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); }
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); }
public static ArgsToken ParseAndChooseArguments(Scope scope, OperatorToken openBracketToken, Definition[] sigDefs, out Definition selectedDef) { #if DEBUG if (sigDefs == null) { throw new ArgumentNullException("sigDefs"); } if (sigDefs.Length == 0) { throw new ArgumentException("sigDefs must contain at least one signature definition."); } #endif if (sigDefs.Length == 1) { selectedDef = sigDefs[0]; return(Parse(scope, openBracketToken, sigDefs[0].ArgumentsSignature)); } var code = scope.Code; var ret = new ArgsToken(scope, openBracketToken); scope = scope.Clone(); scope.Hint |= ScopeHint.SuppressStatementStarts; var tokens = new List <Token>(); var dataTypes = new List <DataType>(); List <Token> bestTokens = null; var bestConfidence = 0.0f; Definition bestSigDef = null; var codeResetPos = code.Position; foreach (var sigDef in sigDefs) { var args = sigDef.Arguments.ToArray(); var argIndex = 0; var expectingDataType = true; tokens.Clear(); dataTypes.Clear(); code.Position = codeResetPos; while (code.SkipWhiteSpace()) { code.Peek(); if (code.Text == ")") { tokens.Add(new OperatorToken(scope, code.MovePeekedSpan(), ")")); ret._terminated = true; break; } else if (code.Text == ",") { tokens.Add(new OperatorToken(scope, code.MovePeekedSpan(), ",")); argIndex++; expectingDataType = true; continue; } var exp = ExpressionToken.TryParse(scope, _endTokens, expectedDataType: argIndex < args.Length ? args[argIndex].DataType : null); if (exp != null) { tokens.Add(exp); if (expectingDataType) { dataTypes.Add(exp.ValueDataType); } expectingDataType = false; } else { break; } } if (dataTypes.Count == args.Length) { var confidence = 1.0f; for (int i = 0, ii = args.Length; i < ii; i++) { confidence *= DataType.CalcArgumentCompatibility(args[i].DataType, dataTypes[i]); } if (confidence > bestConfidence) { bestConfidence = confidence; bestTokens = tokens; bestSigDef = sigDef; } } else if (bestTokens == null) { bestTokens = tokens; bestConfidence = 0.0f; bestSigDef = sigDef; } } ret.AddTokens(bestTokens); ret._sig = bestSigDef.ArgumentsSignature; ret._sigAlternatives = (from s in sigDefs where s.ArgumentsSignature != ret._sig select s.ArgumentsSignature).ToArray(); selectedDef = bestSigDef; return(ret); }
public static BracketsToken Parse(Scope scope, DataType expectedDataType) { var code = scope.Code; if (!code.ReadExact('(')) { throw new InvalidOperationException("BracketsToken.Parse expected next char to be '('."); } var openBracketSpan = code.Span; var indentScope = scope.CloneIndentNonRoot(); indentScope.Hint |= ScopeHint.SuppressFunctionDefinition | ScopeHint.SuppressControlStatements | ScopeHint.SuppressStatementStarts; var ret = new BracketsToken(scope); ret.AddToken(ret._openToken = new OpenBracketToken(scope, openBracketSpan, ret)); List <Token> dataTypeTokens = null; var dataType = DataType.TryParse(new DataType.ParseArgs { Code = code, Scope = scope, DataTypeCallback = name => { return(indentScope.DefinitionProvider.GetAny <Defs.DataTypeDefinition>(openBracketSpan.End, name).FirstOrDefault()); }, VariableCallback = name => { return(indentScope.DefinitionProvider.GetAny <Defs.VariableDefinition>(openBracketSpan.End, name).FirstOrDefault()); }, TableFieldCallback = (tableName, fieldName) => { foreach (var tableDef in indentScope.DefinitionProvider.GetGlobalFromFile(tableName)) { if (tableDef.AllowsChild) { foreach (var fieldDef in tableDef.GetChildDefinitions(fieldName)) { return(new Defs.Definition[] { tableDef, fieldDef }); } } } return(null); }, TokenCreateCallback = token => { if (dataTypeTokens == null) { dataTypeTokens = new List <Token>(); } dataTypeTokens.Add(token); }, VisibleModel = scope.Visible }); if (dataType != null && code.ReadExact(')')) { ret._cast = dataType; if (dataTypeTokens != null) { foreach (var token in dataTypeTokens) { ret.AddToken(token); } } ret.AddToken(ret._closeToken = new CloseBracketToken(scope, code.Span, ret)); } else { while (!code.EndOfFile) { if (code.ReadExact(')')) { ret.AddToken(ret._closeToken = new CloseBracketToken(scope, code.Span, ret)); break; } var exp = ExpressionToken.TryParse(indentScope, _endTokens, expectedDataType: expectedDataType); if (exp != null) { ret._innerTokens.Add(exp); ret.AddToken(exp); } else { break; } } } return(ret); }