1 /* 2 * Copyright (c) 2024, 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 26 #pragma once 27 #include <vector> 28 #include <cstring> 29 #include <iostream> 30 #include <iomanip> 31 #include <stack> 32 33 struct Cursor { 34 private: 35 std::stack<const char *> where; 36 public: 37 char *ptr; 38 Cursor(char *ptr): ptr(ptr) { 39 } 40 virtual ~Cursor() { 41 } 42 void in(const char * location){ 43 where.push(location); 44 } 45 void out(){ 46 where.pop(); 47 } 48 private: 49 Cursor *skipWhiteSpace() { 50 while (*ptr == ' ' || *ptr == '\n' || *ptr == '\t') { 51 step(1); 52 } 53 return this; 54 } 55 56 57 Cursor *skipIdentifier() { 58 while (peekAlpha() || peekDigit()) { 59 step(1); 60 } 61 return this; 62 } 63 public: 64 void step(int count) { 65 while (count--) { 66 ptr++; 67 } 68 } 69 70 bool peekAlpha() { 71 skipWhiteSpace(); 72 return (::isalpha(*ptr)); 73 } 74 75 bool peekDigit() { 76 skipWhiteSpace(); 77 return (::isdigit(*ptr)); 78 } 79 80 bool is(char ch) { 81 skipWhiteSpace(); 82 if (*ptr == ch) { 83 step(1); 84 return true; 85 } 86 return false; 87 } 88 bool isColon() { 89 return is(':'); 90 } 91 92 bool expect(char ch, const char *context, int line ) { 93 if (is(ch)){ 94 return true; 95 } 96 if (!where.empty()){ 97 std::cerr << where.top() << " "; 98 } 99 std::cerr << "@" << line << ": parse error expecting '" << ch << "' "<< context <<" looking at " << ptr << std::endl; 100 exit(1); 101 return false; 102 } 103 bool expect(char ch, int line ) { 104 return expect(ch, "", line); 105 } 106 bool expectDigit(const char *context, int line ) { 107 if (::isdigit(*ptr)){ 108 return true; 109 } 110 if (!where.empty()){ 111 std::cerr << where.top() << " "; 112 } 113 std::cerr << "@" << line << ": parse error expecting digit "<< context <<" looking at " << ptr << std::endl; 114 exit(1); 115 return false; 116 } 117 bool expectAlpha(const char *context, int line ) { 118 if (::isalpha(*ptr)){ 119 return true; 120 } 121 if (!where.empty()){ 122 std::cerr << where.top() << " "; 123 } 124 std::cerr << "@" << line << ": parse error expecting alpha "<< context <<" looking at " << ptr << std::endl; 125 exit(1); 126 return false; 127 } 128 bool isEither(char ch1, char ch2, char*actual) { 129 skipWhiteSpace(); 130 if (*ptr == ch1 || *ptr == ch2) { 131 step(1); 132 *actual = *ptr; 133 return true; 134 } 135 return false; 136 } 137 void expectEither(char ch1, char ch2, char*actual, int line) { 138 skipWhiteSpace(); 139 if (*ptr == ch1 || *ptr == ch2) { 140 step(1); 141 *actual = *ptr; 142 return; 143 } 144 if (!where.empty()){ 145 std::cerr << where.top() << " "; 146 } 147 std::cerr << "@" << line << ": parse error expecting '" << ch1 << "' or '"<<ch2<< "' looking at " << ptr << std::endl; 148 exit(1); 149 150 } 151 /*bool is(char *str) { 152 skipWhiteSpace(); 153 int count = 0; 154 char *safePtr = ptr; 155 while (*str && *ptr && *str == *ptr) { 156 ptr++; 157 str++; 158 count++; 159 } 160 if (count > 0 && *str == '\0') { 161 step(count); 162 return true; 163 } 164 ptr = safePtr; 165 return false; 166 }*/ 167 168 int getInt() { 169 int value = *ptr - '0'; 170 step(1); 171 if (peekDigit()) { 172 return value * 10 + getInt(); 173 } 174 return value; 175 } 176 177 long getLong() { 178 long value = *ptr - '0'; 179 step(1); 180 if (peekDigit()) { 181 return value * 10 + getLong(); 182 } 183 return value; 184 } 185 186 char *getIdentifier() { 187 char *identifierStart = ptr; 188 skipIdentifier(); 189 size_t len = ptr - identifierStart; 190 char *identifier = new char[len + 1]; 191 std::memcpy(identifier, identifierStart, len); 192 identifier[len] = '\0'; 193 return identifier; 194 } 195 196 void error(std::ostream &ostream, const char *file, int line, const char *str) { 197 ostream << file << ":" << "@" << line << ": parse error " << str << " looking at " << ptr << std::endl; 198 exit(1); 199 } 200 201 }; 202 ;