/// <summary> /// Determines if current position is at a keyword or /// at a function name candidate. Function name candidate /// looks like 'identifier[whitespace](' sequence. /// </summary> /// <returns> /// True if it handled the sequence and it looked /// like either keyword or a function candidate. /// </returns> private void HandleKeywordOrIdentifier() { var start = _cs.Position; var s = this.GetIdentifier(); if (s.Length == 0) { AddToken(RTokenType.Unknown, start, 1); _cs.MoveToNextChar(); return; } if (s[0] == '`') { AddToken(RTokenType.Identifier, RTokenSubType.None, start, s.Length); } else if (Logicals.IsLogical(s)) { // Tell between F and F() var logical = true; if (s.Length == 1) { _cs.SkipWhitespace(); if (_cs.CurrentChar == '(') { logical = false; } } AddToken(logical ? RTokenType.Logical : RTokenType.Identifier, start, s.Length); } else if (s == "NULL") { AddToken(RTokenType.Null, RTokenSubType.BuiltinConstant, start, s.Length); } else if (s == "NA" || s == "NA_character_" || s == "NA_complex_" || s == "NA_integer_" || s == "NA_real_") { AddToken(RTokenType.Missing, RTokenSubType.BuiltinConstant, start, s.Length); } else if (s == "Inf") { AddToken(RTokenType.Infinity, RTokenSubType.BuiltinConstant, start, s.Length); } else if (s == "NaN") { AddToken(RTokenType.NaN, RTokenSubType.BuiltinConstant, start, s.Length); } else if (Builtins.IsBuiltin(s)) { AddToken(RTokenType.Identifier, RTokenSubType.BuiltinFunction, start, s.Length); } else if (s.StartsWith("as.", StringComparison.Ordinal) || s.StartsWith("is.", StringComparison.Ordinal)) { AddToken(RTokenType.Identifier, RTokenSubType.TypeFunction, start, s.Length); } else if (Keywords.IsKeyword(s)) { AddToken(RTokenType.Keyword, start, s.Length); } else { AddToken(RTokenType.Identifier, start, s.Length); } }