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