private Token Number() { SkipWhitespaces(); if (_source.IsEndOfFile) { return null; } Token token = null; var state = NumberParseState.InPrimaryPart; using (var lookahead = _source.BeginLookahead()) { _buffer.Clear(); var startPosition = _source.Position; while (!_source.IsEndOfFile) { var ch = _source.Peek(); if (char.IsDigit(ch)) { if (state == NumberParseState.BeginFractionalPart) { state = NumberParseState.InFractionalPart; } _buffer.Append(ch); _source.MoveNext(); if (_source.IsEndOfFile && (state == NumberParseState.InPrimaryPart || state == NumberParseState.InFractionalPart)) { lookahead.Accept(); token = new Token(_buffer.ToString(), TokenKind.Number, new SourceLocation(startPosition)); break; } } else if (ch == '.') { state = NumberParseState.BeginFractionalPart; _buffer.Append(ch); _source.MoveNext(); } else { if (state == NumberParseState.BeginFractionalPart) { _context.AddError("Missing fractional part.", new SourceLocation(_source.Position)); break; } else { lookahead.Accept(); token = new Token(_buffer.ToString(), TokenKind.Number, new SourceLocation(startPosition)); break; } } } } return token; }
private Token Identifier() { _source.SkipWhile(char.IsWhiteSpace); if (_source.IsEndOfFile) { return null; } _buffer.Clear(); Token token = null; using (var lookahead = _source.BeginLookahead()) { var startPosition = _source.Position; var ch = _source.Read(); // identifier must start with a letter or _ if (char.IsLetter(ch) || ch == '_') { _buffer.Append(ch); while (!_source.IsEndOfFile) { ch = _source.Peek(); // We will allow '.' char, because we want to allow this parameter syntax: Order.BillingAddress.Country if (char.IsDigit(ch) || char.IsLetter(ch) || ch == '_' || ch == '.') { _buffer.Append(ch); _source.MoveNext(); } else { lookahead.Accept(); var tokenValue = _buffer.ToString(); var tokenKind = TokenKind.Identifier; if (tokenValue.Equals("AND", StringComparison.OrdinalIgnoreCase)) { tokenKind = TokenKind.AND; } else if (tokenValue.Equals("OR", StringComparison.OrdinalIgnoreCase)) { tokenKind = TokenKind.OR; } token = new Token(tokenValue, tokenKind, new SourceLocation(startPosition)); break; } } } } return token; }