public ArrayBraceToken(Scope scope, Span span, ArrayBracesToken braces, bool open) : base(scope, span) { _braces = braces; _open = open; ClassifierType = Classifier.ProbeClassifierType.Operator; }
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); }
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); }