001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.ext.internal.parser; 021 022import static java.lang.Character.isWhitespace; 023import static java.lang.String.format; 024import static java.util.Objects.requireNonNull; 025 026/** 027 * Base class for all tokenizers. 028 * 029 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 030 * @since 7.1 031 * @version 7.1 032 */ 033public abstract class CharSequenceTokenizer implements Tokenizer<Token<String>> { 034 035 private static final char EOF = (char)-1; 036 037 private final CharSequence _input; 038 039 protected int pos = 0; 040 protected char c = EOF; 041 042 /** 043 * Create a new tokenizer from the given character sequence. 044 * 045 * @param input the input character sequence 046 * @throws NullPointerException if the given {@code input} is {@code null} 047 */ 048 protected CharSequenceTokenizer(final CharSequence input) { 049 requireNonNull(input); 050 051 if (!input.isEmpty()) { 052 c = input.charAt(0); 053 } 054 _input = input; 055 } 056 057 protected void match(final char ch) { 058 if (ch == c) { 059 consume(); 060 } else { 061 throw new ParsingException(format( 062 "Got invalid character '%s' at position '%d'; expected '%s'", 063 c, pos, ch 064 )); 065 } 066 } 067 068 protected void consume() { 069 if (pos + 1 >= _input.length()) { 070 c = EOF; 071 } else { 072 c = _input.charAt(++pos); 073 } 074 } 075 076 protected char LA(final int index) { 077 final int i = pos + index - 1; 078 return i < _input.length() && i >= 0 ? _input.charAt(i) : EOF; 079 } 080 081 public static boolean isNonEof(final char ch) { 082 return ch != EOF; 083 } 084 085 public static boolean isAlphabetic(final char c) { 086 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 087 } 088 089 protected void WS() { 090 do { 091 consume(); 092 } while (isNonEof(c) && isWhitespace(c)); 093 } 094 095}