510 lines
7.5 KiB
C++
510 lines
7.5 KiB
C++
/*-----------------------------------------------------------------------------------------------
|
|
The MIT License (MIT)
|
|
|
|
Copyright (c) 2014-2020 Kim Kulling
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
-----------------------------------------------------------------------------------------------*/
|
|
#pragma once
|
|
|
|
#include <openddlparser/OpenDDLCommon.h>
|
|
|
|
BEGIN_ODDLPARSER_NS
|
|
|
|
template <class T>
|
|
inline bool isUpperCase(T in) {
|
|
return (in >= 'A' && in <= 'Z');
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isLowerCase(T in) {
|
|
return (in >= 'a' && in <= 'z');
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isSpace(const T in) {
|
|
return (' ' == in || '\t' == in);
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isNewLine(const T in) {
|
|
return ('\n' == in || ('\r' == in));
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isSeparator(T in) {
|
|
if (isSpace(in) || ',' == in || '{' == in || '}' == in || '[' == in || '(' == in || ')' == in) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const size_t CharTableSize = 256;
|
|
|
|
static const unsigned char chartype_table[CharTableSize] = {
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 0-15
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 16-31
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 32-47
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 48-63
|
|
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 64-79
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 80-95
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 96-111
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // 112-127
|
|
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0, // > 127
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
};
|
|
|
|
template <class T>
|
|
inline bool isNumeric(const T in) {
|
|
if (static_cast<size_t>(in) >= CharTableSize) {
|
|
return '\0';
|
|
}
|
|
|
|
size_t idx = static_cast<size_t>(in);
|
|
return idx < sizeof(chartype_table) && (chartype_table[idx] == 1);
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isNotEndOfToken(T *in, T *end) {
|
|
return ('}' != *in && ',' != *in && !isSpace(*in) && ')' != *in && in != end);
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isInteger(T *in, T *end) {
|
|
if (in != end) {
|
|
if (*in == '-') {
|
|
++in;
|
|
}
|
|
}
|
|
|
|
bool result(false);
|
|
while (isNotEndOfToken(in, end)) {
|
|
result = isNumeric(*in);
|
|
if (!result) {
|
|
break;
|
|
}
|
|
++in;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isFloat(T *in, T *end) {
|
|
if (in != end) {
|
|
if (*in == '-') {
|
|
++in;
|
|
}
|
|
}
|
|
|
|
// check for <1>.0f
|
|
bool result(false);
|
|
while (isNotEndOfToken(in, end)) {
|
|
if (*in == '.') {
|
|
result = true;
|
|
break;
|
|
}
|
|
result = isNumeric(*in);
|
|
if (!result) {
|
|
return false;
|
|
}
|
|
++in;
|
|
}
|
|
|
|
// check for 1<.>0f
|
|
if (*in == '.') {
|
|
++in;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
// check for 1.<0>f
|
|
while (isNotEndOfToken(in, end)) {
|
|
result = isNumeric(*in);
|
|
if (!result) {
|
|
return false;
|
|
}
|
|
++in;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isCharacter(const T in) {
|
|
return ((in >= 'a' && in <= 'z') || (in >= 'A' && in <= 'Z'));
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isStringLiteral(const T in) {
|
|
return (in == '\"');
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isHexLiteral(T *in, T *end) {
|
|
if (*in == '0') {
|
|
if (in + 1 != end) {
|
|
if (*(in + 1) == 'x' || *(in + 1) == 'X') {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isReference(T *in, T *end) {
|
|
if (*in == 'r') {
|
|
if (*(in + 1) == 'e') {
|
|
if (*(in + 2) == 'f') {
|
|
if ((in + 2) != end) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isEndofLine(const T in) {
|
|
return ('\n' == in);
|
|
}
|
|
|
|
template <class T>
|
|
inline static T *getNextSeparator(T *in, T *end) {
|
|
while (in != end && !isSeparator(*in)) {
|
|
++in;
|
|
}
|
|
return in;
|
|
}
|
|
|
|
static const int ErrorHex2Decimal = 9999999;
|
|
|
|
inline int hex2Decimal(char in) {
|
|
if (isNumeric(in)) {
|
|
return (in - 48);
|
|
}
|
|
|
|
char hexCodeLower('a'), hexCodeUpper('A');
|
|
for (int i = 0; i < 16; i++) {
|
|
if (in == hexCodeLower + i || in == hexCodeUpper + i) {
|
|
return (i + 10);
|
|
}
|
|
}
|
|
|
|
return ErrorHex2Decimal;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isComment(T *in, T *end) {
|
|
if (*in == '/') {
|
|
if (in + 1 != end) {
|
|
if (*(in + 1) == '/') {
|
|
char *drive((in + 2));
|
|
if ((isUpperCase<T>(*drive) || isLowerCase<T>(*drive)) && *(drive + 1) == '/') {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isCommentOpenTag(T *in, T *end) {
|
|
if (*in == '/') {
|
|
if (in + 1 != end) {
|
|
if (*(in + 1) == '*') {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <class T>
|
|
inline bool isCommentCloseTag(T *in, T *end) {
|
|
if (*in == '*') {
|
|
if (in + 1 != end) {
|
|
if (*(in + 1) == '/') {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
END_ODDLPARSER_NS
|