private DataType _dataType; // Can be null /// <summary> /// Creates a function call token. /// </summary> /// <param name="scope">(required) Current scope</param> /// <param name="classToken">(optional) Class name token</param> /// <param name="dotToken">(optional) Dot delimiter between class and function name</param> /// <param name="nameToken">(required) Function name</param> /// <param name="argsToken">(required) Function args</param> /// <param name="def">(optional) Existing function definition</param> public FunctionCallToken(Scope scope, ClassToken classToken, DotToken dotToken, IdentifierToken nameToken, BracketsToken argsToken, FunctionDefinition def) : base(scope) { #if DEBUG if (nameToken == null) { throw new ArgumentNullException("nameToken"); } if (argsToken == null) { throw new ArgumentNullException("argsToken"); } #endif AddToken(_classToken = classToken); AddToken(dotToken); AddToken(_nameToken = nameToken); _nameToken.SourceDefinition = def; AddToken(_argsToken = argsToken); _dataType = def.DataType; }
public static ExpressionToken TryParse(Scope scope, IEnumerable <string> endTokens, WordTokenCallback wordCallback = null, DataType expectedDataType = null) { var code = scope.Code; code.SkipWhiteSpace(); var startPos = code.Position; // Statement breaking tokens if (code.PeekExact(';') || code.PeekExact('{') || code.PeekExact('}')) { return(null); } // Caller-specific end tokens if (endTokens != null) { code.Peek(); if (endTokens.Contains(code.Text)) { return(null); } } var exp = new ExpressionToken(scope); var dataTypeArgs = new DataType.ParseArgs { Code = code, DataTypeCallback = (name) => { return(scope.DefinitionProvider.GetAny <DataTypeDefinition>(code.Position, name).FirstOrDefault()); }, VariableCallback = (name) => { return(scope.DefinitionProvider.GetLocal <VariableDefinition>(code.Position, name).FirstOrDefault()); }, Scope = scope, TokenCreateCallback = (token) => { exp.AddToken(token); }, VisibleModel = true }; var abortParsing = false; var parseDataType = expectedDataType; while (!code.EndOfFile && !abortParsing) { // Statement breaking tokens if (code.PeekExact(';') || code.PeekExact('{') || code.PeekExact('}')) { break; } if (endTokens != null && code.Peek() && endTokens.Contains(code.Text)) { break; } if (!code.Read()) { break; } switch (code.Type) { case CodeType.Word: { var word = code.Text; var wordSpan = code.Span; Token token; if (wordCallback != null && (token = wordCallback(word, wordSpan)) != null) { exp.AddToken(token); } else if (parseDataType != null && parseDataType.HasCompletionOptions && parseDataType.IsValidEnumOption(word)) { exp.AddToken(new EnumOptionToken(scope, wordSpan, word, parseDataType)); } else { var oldPos = code.Position; code.Position = wordSpan.Start; // DataType.TryParse() needs to be before the first word var dt = DataType.TryParse(dataTypeArgs); if (dt == null) { code.Position = oldPos; var wordToken = ProcessWord(exp, scope, word, wordSpan); if (wordToken != null) { exp.AddToken(wordToken); } else { code.Position = wordSpan.Start; abortParsing = true; } } } } break; case CodeType.Number: exp.AddToken(new NumberToken(scope, code.Span, code.Text)); break; case CodeType.StringLiteral: if (parseDataType != null && parseDataType.HasCompletionOptions && parseDataType.IsValidEnumOption(code.Text)) { exp.AddToken(new EnumOptionToken(scope, code.Span, code.Text, parseDataType)); } else { exp.AddToken(new StringLiteralToken(scope, code.Span, code.Text)); } break; case CodeType.Operator: switch (code.Text) { case "(": { code.Position = code.Span.Start; var bracketsToken = BracketsToken.Parse(scope, parseDataType); if (bracketsToken.IsCast) { exp.AddToken(Statements.CastStatement.Parse(scope, bracketsToken, endTokens)); } else { exp.AddToken(bracketsToken); } } break; case "{": code.Position = code.Span.Start; exp.AddToken(BracesToken.Parse(scope, null)); break; case "[": code.Position = code.Span.Start; exp.AddToken(ArrayBracesToken.Parse(scope)); break; case ",": exp.AddToken(new DelimiterToken(scope, code.Span)); break; case ".": exp.AddToken(new DotToken(scope, code.Span)); break; case "&": exp.AddToken(new ReferenceToken(scope, code.Span)); break; case "==": case "!=": case "<": case "<=": case ">": case ">=": if ((scope.Hint & ScopeHint.SuppressLogic) == 0) { if (exp.ChildrenCount > 0) { var dataType = exp.LastChild.ValueDataType; if (dataType != null) { parseDataType = dataType; } } exp.AddToken(ComparisonOperator.Parse(scope, exp.LastChild, new OperatorToken(scope, code.Span, code.Text), endTokens)); } else { exp.AddToken(new OperatorToken(scope, code.Span, code.Text)); } break; case "=": if ((scope.Hint & ScopeHint.SuppressLogic) == 0) { if (exp.ChildrenCount > 0) { var dataType = exp.LastChild.ValueDataType; if (dataType != null) { parseDataType = dataType; } } exp.AddToken(AssignmentOperator.Parse(scope, exp.LastChild, new OperatorToken(scope, code.Span, code.Text), endTokens)); } else { exp.AddToken(new OperatorToken(scope, code.Span, code.Text)); } break; case "+=": case "-=": case "*=": case "/=": case "%=": if ((scope.Hint & ScopeHint.SuppressLogic) == 0) { exp.AddToken(AssignmentOperator.Parse(scope, exp.LastChild, new OperatorToken(scope, code.Span, code.Text), endTokens)); } else { exp.AddToken(new OperatorToken(scope, code.Span, code.Text)); } break; case "?": parseDataType = expectedDataType; exp.AddToken(ConditionalOperator.Parse(scope, exp.LastChild, new OperatorToken(scope, code.Span, code.Text), endTokens, parseDataType)); break; default: exp.AddToken(new OperatorToken(scope, code.Span, code.Text)); break; } break; case CodeType.Preprocessor: exp.AddToken(new PreprocessorToken(scope, code.Span, code.Text)); break; default: exp.AddToken(new UnknownToken(scope, code.Span, code.Text)); break; } } if (exp.ChildrenCount == 0) { return(null); } return(exp); }
public FunctionPlaceholderToken(Scope scope, Span span, string text, IdentifierToken nameToken, BracketsToken argsToken, FunctionDefinition sourceDef) : base(scope) { #if DEBUG if (nameToken == null) { throw new ArgumentNullException("nameToken"); } if (argsToken == null) { throw new ArgumentNullException("argsToken"); } if (sourceDef == null) { throw new ArgumentNullException("sourceDef"); } #endif AddToken(nameToken); AddToken(argsToken); nameToken.SourceDefinition = sourceDef; _bodyStart = sourceDef.BodyStartPosition; _argsEnd = sourceDef.ArgsEndPosition; }
public InterfaceMethodCallToken(Scope scope, VariableToken intVarToken, DotToken dotToken, IdentifierToken nameToken, BracketsToken argsToken, InterfaceMethodDefinition def) : base(scope) { #if DEBUG if (intVarToken == null) { throw new ArgumentNullException("intVarToken"); } if (dotToken == null) { throw new ArgumentNullException("dotToken"); } if (nameToken == null) { throw new ArgumentNullException("nameToken"); } if (argsToken == null) { throw new ArgumentNullException("argsToken"); } if (def == null) { throw new ArgumentNullException("def"); } #endif AddToken(intVarToken); AddToken(dotToken); AddToken(_nameToken = nameToken); AddToken(argsToken); _methodDef = def; _nameToken.SourceDefinition = def; }
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); }
public CloseBracketToken(Scope scope, Span span, BracketsToken bracketsToken) : base(scope, span, bracketsToken) { }
public BracketToken(Scope scope, Span span, BracketsToken bracketsToken) : base(scope, span) { _bracketsToken = bracketsToken; ClassifierType = Classifier.ProbeClassifierType.Operator; }