1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.parser; 27 28/** 29 * Utility for scanning thru a char array. 30 * 31 */ 32public class Scanner { 33 /** Characters to scan. */ 34 protected final char[] content; 35 36 /** Position in content. */ 37 protected int position; 38 39 /** Scan limit. */ 40 protected final int limit; 41 42 /** Current line number. */ 43 protected int line; 44 45 /** Current character in stream */ 46 protected char ch0; 47 /** 1 character lookahead */ 48 protected char ch1; 49 /** 2 character lookahead */ 50 protected char ch2; 51 /** 3 character lookahead */ 52 protected char ch3; 53 54 /** 55 * Constructor 56 * 57 * @param content content to scan 58 * @param line start line number 59 * @param start position index in content where to start 60 * @param length length of input 61 */ 62 protected Scanner(final char[] content, final int line, final int start, final int length) { 63 this.content = content; 64 this.position = start; 65 this.limit = start + length; 66 this.line = line; 67 68 reset(position); 69 } 70 71 /** 72 * Constructor 73 * 74 * Scan content from beginning to end. Content given as a string 75 * 76 * @param content content to scan 77 */ 78 protected Scanner(final String content) { 79 this(content.toCharArray(), 0, 0, content.length()); 80 } 81 82 /** 83 * Copy constructor 84 * 85 * @param scanner scanner 86 * @param state state, the state is a tuple {position, limit, line} only visible internally 87 */ 88 Scanner(final Scanner scanner, final State state) { 89 content = scanner.content; 90 position = state.position; 91 limit = state.limit; 92 line = state.line; 93 94 reset(position); 95 } 96 97 /** 98 * Information needed to restore previous state. 99 */ 100 static class State { 101 /** Position in content. */ 102 public final int position; 103 104 /** Scan limit. */ 105 public int limit; 106 107 /** Current line number. */ 108 public final int line; 109 110 State(final int position, final int limit, final int line) { 111 this.position = position; 112 this.limit = limit; 113 this.line = line; 114 } 115 116 /** 117 * Change the limit for a new scanner. 118 * @param limit New limit. 119 */ 120 void setLimit(final int limit) { 121 this.limit = limit; 122 } 123 124 boolean isEmpty() { 125 return position == limit; 126 } 127 } 128 129 /** 130 * Save the state of the scan. 131 * @return Captured state. 132 */ 133 State saveState() { 134 return new State(position, limit, line); 135 } 136 137 /** 138 * Restore the state of the scan. 139 * @param state Captured state. 140 */ 141 void restoreState(final State state) { 142 position = state.position; 143 line = state.line; 144 145 reset(position); 146 } 147 148 /** 149 * Returns true of scanner is at end of input 150 * @return true if no more input 151 */ 152 protected final boolean atEOF() { 153 return position == limit; 154 } 155 156 /** 157 * Get the ith character from the content. 158 * @param i Index of character. 159 * @return ith character or '\0' if beyond limit. 160 */ 161 protected final char charAt(final int i) { 162 // Get a character from the content, '\0' if beyond the end of file. 163 return i < limit ? content[i] : '\0'; 164 } 165 166 /** 167 * Reset to a character position. 168 * @param i Position in content. 169 */ 170 protected final void reset(final int i) { 171 ch0 = charAt(i); 172 ch1 = charAt(i + 1); 173 ch2 = charAt(i + 2); 174 ch3 = charAt(i + 3); 175 position = i < limit? i : limit; 176 } 177 178 /** 179 * Skip ahead a number of characters. 180 * @param n Number of characters to skip. 181 */ 182 protected final void skip(final int n) { 183 if (n == 1 && !atEOF()) { 184 ch0 = ch1; 185 ch1 = ch2; 186 ch2 = ch3; 187 ch3 = charAt(position + 4); 188 position++; 189 } else if (n != 0) { 190 reset(position + n); 191 } 192 } 193} 194