namespace Jtr.Parsing; public class ParserContext : ParsableStream.Token> where TToken : Enum { private readonly TToken _endOfSource; protected ParserContext(Memory.Token> tokens, TToken endOfSource) : base(tokens) { _endOfSource = endOfSource; } public bool Check(TToken type, int offset = 0) { if (Ended()) return false; if (Equals(Peek(offset).Type, _endOfSource)) return false; return Equals(Peek(offset).Type, type); } /// /// Checks whether the passed sequence can be matched against the current parsing context. /// /// /// public bool CheckSequence(params TToken[] sequence) { for (var i = 0; i < sequence.Length; i++) { if (!Check(sequence[i], i)) { return false; } } return true; } public override bool Ended() { return base.Ended() || Equals(Current.Type, _endOfSource); } public bool Match(TToken token) { var matched = Check(token); if (matched) Advance(); return matched; } public bool MatchAny(params TToken[] types) { for (var i = 0; i < types.Length; i++) { if (Check(types[i])) { Advance(); return true; } } return false; } public bool MatchSequence(params TToken[] sequence) { for (var i = 0; i < sequence.Length; i++) { if (!Check(sequence[i], i)) { return false; } } for (var i = 0; i < sequence.Length; i++) { Advance(); } return true; } public Lexer.Token Previous() { return Peek(-1); } public Lexer.Token Consume(TToken type, string message) { if (Check(type)) return Advance(); throw SyntaxException(message); } public Exception SyntaxException(string message) { return new SyntaxException(Report.FormatMessage(Current, message)); } public Exception SyntaxException(Lexer.Token token, string message) { return new SyntaxException(Report.FormatMessage(token, message)); } }