/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.compiler;
import avt.lang.math.*;
import ru.malik.elaborarer.avtoo.lang.*;
public class LanguageLexer(Lexer, AVTOOConstants)
{
private static final long UCMP = 0x8000000000000000L;
private static final long BLIMIT = 0x8000000000000000L;
private static final long OLIMIT = 0x2000000000000000L;
private static final long DLIMIT = 0x1999999999999999L;
private static final long XLIMIT = 0x1000000000000000L;
private static final long ILIMIT = 0x0000000100000000L;
private static final char[] symbols;
private static final String[] lexemes;
private static final DocumentLexer defaultDocumentationLexer;
private static {
symbols = ".,:;`?=()[]{}<>!~&^|+-*/%#@".toCharArray();
lexemes = new String[LEXEMES_LENGTH];
lexemes[PRIVATE ] = "private";
lexemes[PACKAGE ] = "package";
lexemes[PROTECTED ] = "protected";
lexemes[PUBLIC ] = "public";
lexemes[PUBLISHED ] = "published";
lexemes[IMPORT ] = "import";
lexemes[UNION ] = "union";
lexemes[ABSTRACT ] = "abstract";
lexemes[FINAL ] = "final";
lexemes[CLASS ] = "class";
lexemes[STRUCT ] = "struct";
lexemes[SERVICE ] = "service";
lexemes[INTERFACE ] = "interface";
lexemes[HELPER ] = "helper";
lexemes[STATIC ] = "static";
lexemes[NATIVE ] = "native";
lexemes[INTERRUPT ] = "interrupt";
lexemes[SYNCHRONIZED ] = "synchronized";
lexemes[OPERATOR ] = "operator";
lexemes[THROWS ] = "throws";
lexemes[FALSE ] = "false";
lexemes[TRUE ] = "true";
lexemes[NULL ] = "null";
lexemes[NEW ] = "new";
lexemes[SUPER ] = "super";
lexemes[THIS ] = "this";
lexemes[INSTANCEOF ] = "instanceof";
lexemes[VOID ] = "void";
lexemes[BOOLEAN ] = "boolean";
lexemes[CHAR ] = "char";
lexemes[REAL ] = "real";
lexemes[DOUBLE ] = "double";
lexemes[DOUBLE2 ] = "double2";
lexemes[DOUBLE4 ] = "double4";
lexemes[DOUBLE8 ] = "double8";
lexemes[FLOAT ] = "float";
lexemes[FLOAT2 ] = "float2";
lexemes[FLOAT4 ] = "float4";
lexemes[FLOAT8 ] = "float8";
lexemes[BYTE ] = "byte";
lexemes[BYTE2 ] = "byte2";
lexemes[BYTE4 ] = "byte4";
lexemes[BYTE8 ] = "byte8";
lexemes[SHORT ] = "short";
lexemes[SHORT2 ] = "short2";
lexemes[SHORT4 ] = "short4";
lexemes[SHORT8 ] = "short8";
lexemes[INT ] = "int";
lexemes[INT2 ] = "int2";
lexemes[INT4 ] = "int4";
lexemes[INT8 ] = "int8";
lexemes[LONG ] = "long";
lexemes[LONG2 ] = "long2";
lexemes[LONG4 ] = "long4";
lexemes[LONG8 ] = "long8";
lexemes[WITH ] = "with";
lexemes[IF ] = "if";
lexemes[ELSE ] = "else";
lexemes[SWITCH ] = "switch";
lexemes[CASE ] = "case";
lexemes[DEFAULT ] = "default";
lexemes[DO ] = "do";
lexemes[FOR ] = "for";
lexemes[WHILE ] = "while";
lexemes[BREAK ] = "break";
lexemes[CONTINUE ] = "continue";
lexemes[RETURN ] = "return";
lexemes[THROW ] = "throw";
lexemes[TRY ] = "try";
lexemes[CATCH ] = "catch";
lexemes[FINALLY ] = "finally";
lexemes[INC_LOCAL ] = "++";
lexemes[DEC_LOCAL ] = "--";
lexemes[BOOL_NOT ] = "!";
lexemes[BOOL_AND ] = "&&";
lexemes[BOOL_OR ] = "||";
lexemes[O_BIT_NOT ] = "~";
lexemes[O_BIT_AND ] = "&";
lexemes[O_BIT_OR ] = "|";
lexemes[O_BIT_XOR ] = "^";
lexemes[O_SCAL_MUL ] = "*";
lexemes[O_SCAL_DIV ] = "/";
lexemes[O_SCAL_DIVU ] = "//";
lexemes[O_SCAL_REM ] = "%";
lexemes[O_SCAL_REMU ] = "%%";
lexemes[O_SCAL_ADD ] = "+";
lexemes[O_SCAL_SUB ] = "-";
lexemes[O_SCAL_SHR ] = ">>";
lexemes[O_SCAL_SHRU ] = ">>>";
lexemes[O_SCAL_SHL ] = "<<";
lexemes[O_SCAL_GT ] = ">";
lexemes[O_SCAL_GE ] = ">=";
lexemes[O_SCAL_LT ] = "<";
lexemes[O_SCAL_LE ] = "<=";
lexemes[O_SCAL_EQ ] = "==";
lexemes[O_SCAL_NE ] = "!=";
lexemes[O_VECT_LUP ] = "####";
lexemes[O_VECT_UUP ] = "^^^^";
lexemes[O_VECT_PCK ] = "@@@@";
lexemes[O_VECT_MUL ] = "****";
lexemes[O_VECT_DIV ] = "////";
lexemes[O_VECT_ADD ] = "++++";
lexemes[O_VECT_SUB ] = "----";
lexemes[O_VECT_SHR ] = ">>>>";
lexemes[O_VECT_SHRU ] = ">>>>>";
lexemes[O_VECT_SHL ] = "<<<<";
lexemes[O_VECT_GT ] = "|>>|";
lexemes[O_VECT_GE ] = "|>=|";
lexemes[O_VECT_LT ] = "|<<|";
lexemes[O_VECT_LE ] = "|<=|";
lexemes[O_VECT_EQ ] = "|==|";
lexemes[O_VECT_NE ] = "|!=|";
lexemes[O_VECT_HMUL ] = "|**|";
lexemes[O_VECT_HMULU ] = "#**#";
lexemes[O_VECT_SADD ] = "|++|";
lexemes[O_VECT_SADDU ] = "#++#";
lexemes[O_VECT_SSUB ] = "|--|";
lexemes[O_VECT_SSUBU ] = "#--#";
lexemes[A_BIT_AND ] = "&=";
lexemes[A_BIT_OR ] = "|=";
lexemes[A_BIT_XOR ] = "^=";
lexemes[A_SCAL_MUL ] = "*=";
lexemes[A_SCAL_DIV ] = "/=";
lexemes[A_SCAL_DIVU ] = "//=";
lexemes[A_SCAL_REM ] = "%=";
lexemes[A_SCAL_REMU ] = "%%=";
lexemes[A_SCAL_ADD ] = "+=";
lexemes[A_SCAL_SUB ] = "-=";
lexemes[A_SCAL_SHR ] = ">>=";
lexemes[A_SCAL_SHRU ] = ">>>=";
lexemes[A_SCAL_SHL ] = "<<=";
lexemes[A_VECT_MUL ] = "****=";
lexemes[A_VECT_DIV ] = "////=";
lexemes[A_VECT_ADD ] = "++++=";
lexemes[A_VECT_SUB ] = "----=";
lexemes[A_VECT_SHR ] = ">>>>=";
lexemes[A_VECT_SHRU ] = ">>>>>=";
lexemes[A_VECT_SHL ] = "<<<<=";
lexemes[A_VECT_GT ] = "|>>|=";
lexemes[A_VECT_GE ] = "|>=|=";
lexemes[A_VECT_LT ] = "|<<|=";
lexemes[A_VECT_LE ] = "|<=|=";
lexemes[A_VECT_EQ ] = "|==|=";
lexemes[A_VECT_NE ] = "|!=|=";
lexemes[A_VECT_HMUL ] = "|**|=";
lexemes[A_VECT_HMULU ] = "#**#=";
lexemes[A_VECT_SADD ] = "|++|=";
lexemes[A_VECT_SADDU ] = "#++#=";
lexemes[A_VECT_SSUB ] = "|--|=";
lexemes[A_VECT_SSUBU ] = "#--#=";
lexemes[PARENTH_OPENED] = "(";
lexemes[PARENTH_CLOSED] = ")";
lexemes[BRACKET_OPENED] = "[";
lexemes[BRACKET_CLOSED] = "]";
lexemes[CURLY_OPENED ] = "{";
lexemes[CURLY_CLOSED ] = "}";
lexemes[EQUALS ] = "=";
lexemes[QUESTION ] = "?";
lexemes[REVERSE ] = "`";
lexemes[PERIOD ] = ".";
lexemes[COMMA ] = ",";
lexemes[COLON ] = ":";
lexemes[SEMICOLON ] = ";";
defaultDocumentationLexer = new DocumentLexer() { lineEndingEnabled = true };
}
private static int parseName(int lineIndex, char[] line, int charIndex, char chr, LexemeSequence sequence) throws TextSourceException {
if((chr < 'A' || chr > 'Z') && (chr < 'a' || chr > 'z') && (chr != '_')) return charIndex;
int result = charIndex + 1;
int length = 1;
for(; (chr = line[result]) >= 'A' && chr <= 'Z' || chr >= 'a' && chr <= 'z' || chr >= '0' && chr <= '9' || chr == '_'; result++) if(++length > LIMIT_NAME_LENGTH)
{
throw new TextSourceException(package.getResourceString("lexer.name.too-long")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
label0:
{
if(length <= 12) for(int index = KEYWORDS_LENGTH; (index = Array.lastIndexOfNon(null, lexemes, index - 1, 0)) >= 0; )
{
String lexeme = lexemes[index];
if(lexeme.length == length && lexeme.contentEquals(line, charIndex)) switch(index)
{
case TRUE:
case FALSE:
sequence.appendLexeme(lineIndex, charIndex, L_BOOLEAN, index != FALSE);
break label0;
default:
sequence.appendLexeme(lineIndex, charIndex, index, lexeme);
break label0;
}
}
sequence.appendLexeme(lineIndex, charIndex, L_NAME, new String(line, charIndex, length));
}
return result;
}
private static int parseChar(int lineIndex, char[] line, int charIndex, char chr, LexemeSequence sequence) throws TextSourceException {
if(chr != '\u0027') return charIndex;
int result = charIndex + 1;
int2 ic = parseStringChar(line, result, line[result]);
int code = ic[1];
result = ic[0];
if(code < 0 || line[result++] != '\u0027')
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "char" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
sequence.appendLexeme(lineIndex, charIndex, L_CHAR, (char) code);
return result;
}
private static int parseString(int lineIndex, char[] line, int charIndex, char chr, LexemeSequence sequence) throws TextSourceException {
if(chr != '\u0022') return charIndex;
int result = charIndex + 1;
int length = 0;
int capacity = 0x7f;
char[] buffer = new char[capacity];
while((chr = line[result]) != '\u0022')
{
int2 ic = parseStringChar(line, result, chr);
int code = ic[1];
result = ic[0];
if(code < 0)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { PACKNAME_LANG + "." + TYPENAME_STRING })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if(length == capacity)
{
if(length == (Short.MAX_VALUE << 1 | 1))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.too-long"), new Object[] { PACKNAME_LANG + "." + TYPENAME_STRING })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
Array.copy(buffer, 0, buffer = new char[capacity = capacity << 1 | 1], 0, length);
}
buffer[length++] = (char) code;
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_STRING, new String(buffer, 0, length));
return result;
}
private static int parseNumeric(int lineIndex, char[] line, int charIndex, char chr, LexemeSequence sequence) throws TextSourceException {
if((chr < '0' || chr > '9') && (chr != '.')) return charIndex;
boolean hasOverflow = false;
int result = charIndex + 1;
long rawNumber = 0L; /* беззнаковое значение */
/* префикс системы счисления */
label0: if(chr == '0')
{
label1:
{
label2: switch(line[result])
{
case 'B':
case 'b':
if((chr = line[result + 1]) < '0' || chr > '1')
{
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, 0);
return result;
}
if(chr == '1' && line[result + 2] == '.') for(int shift = 63, chr = line[result += 3]; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '1')
{
digit = chr - '0';
}
else if(chr == 'p' || chr == 'P')
{
break label1;
}
else
{
throw new TextSourceException(package.getResourceString("lexer.literal.numeric")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if(shift >= 0)
{
rawNumber |= (long) digit << shift;
shift--;
}
}
for(result++; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '1')
{
digit = chr - '0';
}
else
{
break label2;
}
if(rawNumber + UCMP >= BLIMIT + UCMP)
{
hasOverflow = true;
} else
{
rawNumber = rawNumber << 1 | digit;
}
}
case 'O':
case 'o':
if((chr = line[result + 1]) < '0' || chr > '7')
{
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, 0);
return result;
}
if(chr == '1' && line[result + 2] == '.') for(int shift = 61, chr = line[result += 3]; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '7')
{
digit = chr - '0';
}
else if(chr == 'p' || chr == 'P')
{
break label1;
}
else
{
throw new TextSourceException(package.getResourceString("lexer.literal.numeric")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if(shift >= 0)
{
rawNumber |= (long) digit << shift;
shift -= 3;
}
}
for(result++; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '7')
{
digit = chr - '0';
}
else
{
break label2;
}
if(rawNumber + UCMP >= OLIMIT + UCMP)
{
hasOverflow = true;
} else
{
rawNumber = rawNumber << 3 | digit;
}
}
case 'X':
case 'x':
if(((chr = line[result + 1]) < '0' || chr > '9') && (chr < 'a' || chr > 'f') && (chr < 'A' || chr > 'F'))
{
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, 0);
return result;
}
if(chr == '1' && line[result + 2] == '.') for(int shift = 60, chr = line[result += 3]; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '9')
{
digit = chr - '0';
}
else if(chr >= 'a' && chr <= 'f')
{
digit = chr - ('a' - 0x0a);
}
else if(chr >= 'A' && chr <= 'F')
{
digit = chr - ('A' - 0x0a);
}
else if(chr == 'p' || chr == 'P')
{
break label1;
}
else
{
throw new TextSourceException(package.getResourceString("lexer.literal.numeric")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if(shift >= 0)
{
rawNumber |= (long) digit << shift;
shift -= 4;
}
}
for(result++; ; chr = line[++result])
{
int digit;
if(chr >= '0' && chr <= '9')
{
digit = chr - '0';
}
else if(chr >= 'a' && chr <= 'f')
{
digit = chr - ('a' - 0x0a);
}
else if(chr >= 'A' && chr <= 'F')
{
digit = chr - ('A' - 0x0a);
}
else
{
break label2;
}
if(rawNumber + UCMP >= XLIMIT + UCMP)
{
hasOverflow = true;
} else
{
rawNumber = rawNumber << 4 | digit;
}
}
default:
break label0;
}
/* тип целого числа */
switch(chr)
{
case 'S':
case 's':
if(rawNumber + UCMP >= ILIMIT + UCMP || (rawNumber = (int) rawNumber) < Short.MIN_VALUE || rawNumber > Short.MAX_VALUE)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "short" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, (short) rawNumber);
break;
case 'I':
case 'i':
if(rawNumber + UCMP >= ILIMIT + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "int" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_INT, (int) rawNumber);
break;
case 'L':
case 'l':
if(hasOverflow)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "long" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_LONG, rawNumber);
break;
default:
if(rawNumber + UCMP >= ILIMIT + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "int" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if((rawNumber = (int) rawNumber) >= Byte.MIN_VALUE && rawNumber <= Byte.MAX_VALUE)
{
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, (byte) rawNumber);
break;
}
if(rawNumber >= Short.MIN_VALUE && rawNumber <= Short.MAX_VALUE)
{
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, (short) rawNumber);
break;
}
sequence.appendLexeme(lineIndex, charIndex, L_INT, (int) rawNumber);
}
return result;
}
/* порядок действительного числа */
int order = 0;
{
boolean isNegative = (chr = line[++result]) == '-';
boolean isSigned = isNegative || chr == '+';
if(isSigned || chr >= '0' && chr <= '9')
{
int index = !isSigned ? result : result + 1;
char dgt = line[index];
if(dgt >= '0' && dgt <= '9')
{
do if((order = (order * 10) + (dgt - '0')) > 99999)
{
throw new TextSourceException(package.getResourceString("lexer.literal.numeric")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
} while((dgt = line[++index]) >= '0' && dgt <= '9');
if(isNegative) order = -order;
result = index;
chr = dgt;
}
}
}
/* само действительное число */
real realNumber = Long2.toRealBits(new long2 { 1L << 63 | rawNumber >> 1, 0x3fffL }) * pow2(order);
/* тип действительного числа */
switch(chr)
{
case 'F':
case 'f':
float floatNumber = (float) realNumber;
if(Float.isInfinite(floatNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "float" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_FLOAT, floatNumber);
break;
case 'D':
case 'd':
double doubleNumber = (double) realNumber;
if(Double.isInfinite(doubleNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "double" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_DOUBLE, doubleNumber);
break;
case 'R':
case 'r':
result++;
/* падение через */
default:
if(Real.isInfinite(realNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "real" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
}
return result;
}
/* точка */
boolean hasFractionPart = false;
int lengthOfFractionPart = 0;
if(chr == '.')
{
if((chr = line[result]) < '0' || chr > '9')
{
sequence.appendLexeme(lineIndex, charIndex, PERIOD, lexemes[PERIOD]);
return result;
}
lengthOfFractionPart = 1;
hasFractionPart = true;
result++;
}
/* мантисса числа */
for(boolean isRounded = false, rawNumber = chr - '0'; ; result++)
{
if((chr = line[result]) == '.')
{
if(hasFractionPart) break;
hasFractionPart = true;
continue;
}
if(chr < '0' || chr > '9') break;
int digit = chr - '0';
if(rawNumber + UCMP < DLIMIT + UCMP || rawNumber == DLIMIT && digit < 6)
{
rawNumber = rawNumber * 10L + digit;
if(hasFractionPart) lengthOfFractionPart++;
continue;
}
if(hasFractionPart)
{
if(!isRounded && digit >= 5 && rawNumber != 0xffffffffffffffffL) rawNumber++;
isRounded = true;
continue;
}
hasOverflow = true;
lengthOfFractionPart--;
}
/* порядок числа */
boolean hasOrder = false;
int order = 0;
if(chr == 'e' || chr == 'E')
{
boolean isNegative = false;
int index = result + 1;
char dgt = line[index];
switch(dgt)
{
case '-':
isNegative = true;
/* падение через */
case '+':
dgt = line[++index];
}
if(dgt >= '0' && dgt <= '9')
{
do if((order = (order * 10) + (dgt - '0')) > 9999)
{
throw new TextSourceException(package.getResourceString("lexer.literal.numeric")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
} while((dgt = line[++index]) >= '0' && dgt <= '9');
if(isNegative) order = -order;
hasOrder = true;
result = index;
chr = dgt;
}
}
/* само число */
if((hasFractionPart || hasOrder) && rawNumber != 0L) for(; rawNumber %% 10L == 0L; rawNumber //= 10L) lengthOfFractionPart--;
real realNumber = RealRepresenter.pow10((real) (rawNumber + UCMP) - (real) UCMP, order - lengthOfFractionPart);
/* тип числа */
switch(chr)
{
case 'S':
case 's':
if(hasFractionPart || hasOrder || hasOverflow || rawNumber + UCMP > Short.MAX_VALUE + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "short" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, (short) rawNumber);
break;
case 'I':
case 'i':
if(hasFractionPart || hasOrder || hasOverflow || rawNumber + UCMP > Int.MAX_VALUE + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "int" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_INT, (int) rawNumber);
break;
case 'L':
case 'l':
if(hasFractionPart || hasOrder || hasOverflow || rawNumber + UCMP > Long.MAX_VALUE + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "long" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_LONG, rawNumber);
break;
case 'F':
case 'f':
float floatNumber = (float) realNumber;
if(Float.isInfinite(floatNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "float" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_FLOAT, floatNumber);
break;
case 'D':
case 'd':
double doubleNumber = (double) realNumber;
if(Double.isInfinite(doubleNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "double" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_DOUBLE, doubleNumber);
break;
case 'R':
case 'r':
if(Real.isInfinite(realNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "real" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
result++;
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
break;
default:
if(hasFractionPart || hasOrder)
{
if(Real.isInfinite(realNumber))
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "real" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
sequence.appendLexeme(lineIndex, charIndex, L_REAL, realNumber);
break;
}
if(rawNumber + UCMP > Int.MAX_VALUE + UCMP)
{
throw new TextSourceException(String.format(package.getResourceString("lexer.literal.type"), new Object[] { "int" })) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
if(rawNumber <= Byte.MAX_VALUE)
{
sequence.appendLexeme(lineIndex, charIndex, L_BYTE, (byte) rawNumber);
break;
}
if(rawNumber <= Short.MAX_VALUE)
{
sequence.appendLexeme(lineIndex, charIndex, L_SHORT, (short) rawNumber);
break;
}
sequence.appendLexeme(lineIndex, charIndex, L_INT, (int) rawNumber);
}
return result;
}
private static int parseOperator(int lineIndex, char[] line, int charIndex, char chr, LexemeSequence sequence) throws TextSourceException {
if(Array.indexOf(chr, symbols, 0, 0) < 0) return charIndex;
int result = charIndex + 1;
int length = 1;
for(chr = line[result]; length < 6 && Array.indexOf(chr, symbols, 0, 0) >= 0; length++) chr = line[++result];
label0: for(; length > 0; length--)
{
for(int index = LEXEMES_LENGTH; (index = Array.lastIndexOfNon(null, lexemes, index - 1, 0)) >= KEYWORDS_LENGTH; )
{
String lexeme = lexemes[index];
if(lexeme.length == length && lexeme.contentEquals(line, charIndex))
{
sequence.appendLexeme(lineIndex, charIndex, index, lexeme);
break label0;
}
}
if(--result == charIndex)
{
throw new TextSourceException(package.getResourceString("lexer.operator")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
}
return result;
}
private static int2 parseStringChar(char[] line, int charIndex, char chr) {
switch(chr)
{
default:
return new int2 { charIndex + 1, chr };
case '\0':
case '\"':
case '\'':
return new int2 { charIndex, -1 };
case '\\':
}
int result = charIndex + 1;
switch(line[result++])
{
default:
return new int2 { charIndex, -1 };
case '0':
return new int2 { result, 0x0000 };
case 'b':
return new int2 { result, 0x0008 };
case 't':
return new int2 { result, 0x0009 };
case 'n':
return new int2 { result, 0x000a };
case 'f':
return new int2 { result, 0x000c };
case 'r':
return new int2 { result, 0x000d };
case '\"':
return new int2 { result, 0x0022 };
case '\'':
return new int2 { result, 0x0027 };
case '\\':
return new int2 { result, 0x005c };
case 'u':
}
int code = 0;
for(int cci = 4; cci-- > 0; )
{
int digit;
if((chr = line[result++]) >= '0' && chr <= '9')
{
digit = chr - '0';
}
else if(chr >= 'a' && chr <= 'f')
{
digit = chr - ('a' - 0x0a);
}
else if(chr >= 'A' && chr <= 'F')
{
digit = chr - ('A' - 0x0a);
}
else
{
return new int2 { charIndex, -1 };
}
code = code << 4 | digit;
}
return new int2 { result, code };
}
private static real pow2(int power) {
return (power += 0x3fff) < -62 ? (
0
) : power < 0x0001 ? (
Long2.toRealBits(new long2 { 1L << (power + 62), 0L })
) : power < 0x7fff ? (
Long2.toRealBits(new long2 { 1L << 63, (long) power })
) : (
Real.POSITIVE_INFINITY
);
}
protected boolean fldDocumentationEnabled;
protected DocumentLexer fldDocumentationLexer;
public () { }
public (DocumentLexer documentationLexer) { fldDocumentationLexer = documentationLexer; }
public void split(char[][] text, int2 locationBegin, int2 locationEnd, LexemeSequence sequence) throws TextSourceException {
if(text == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "text" }));
}
if(sequence == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "sequence" }));
}
int limit = text.length;
if(limit-- <= 0)
{
sequence.appendLexeme(0, 0, L_END);
return;
}
int lineIndexBegin = locationBegin[0];
int charIndexBegin = locationBegin[1];
int lineIndexEnd = locationEnd[0];
int charIndexEnd = locationEnd[1];
int count = text[limit].length - 1;
if(lineIndexBegin < 0)
{
lineIndexBegin = 0;
charIndexBegin = 0;
}
if(lineIndexBegin > limit)
{
lineIndexBegin = limit;
charIndexBegin = count;
}
if(lineIndexEnd < 0)
{
lineIndexEnd = 0;
charIndexEnd = 0;
}
if(lineIndexEnd > limit)
{
lineIndexEnd = limit;
charIndexEnd = count;
}
if(charIndexBegin < 0)
{
charIndexBegin = 0;
}
if(charIndexBegin > (count = text[lineIndexBegin].length - 1))
{
charIndexBegin = count;
}
if(charIndexEnd < 0)
{
charIndexEnd = 0;
}
if(charIndexEnd > (count = text[lineIndexEnd].length - 1))
{
charIndexEnd = count;
}
char[] last = text[lineIndexEnd];
if(charIndexEnd < last.length - 1)
{
Array.copy(last, 0, last = new char[charIndexEnd + 1], 0, charIndexEnd);
}
for(int lineIndex = lineIndexBegin; lineIndex <= lineIndexEnd; lineIndex++)
{
int charIndex = lineIndex <= lineIndexBegin ? charIndexBegin : 0;
char[] line = lineIndex >= lineIndexEnd ? last : text[lineIndex];
label0: for(char chr = line[charIndex]; chr > 0x00; )
{
while(chr <= 0x20) if((chr = line[++charIndex]) <= 0x00) break label0;
int2 location = parseComment(text, lineIndex, lineIndexEnd, last, line, charIndex, chr, sequence);
if((new int2 { lineIndex, charIndex } |<<| location) != 0)
{
lineIndex = location[0];
charIndex = location[1];
chr = (line = lineIndex >= lineIndexEnd ? last : text[lineIndex])[charIndex];
continue;
}
if(
charIndex < (charIndex = parseName(lineIndex, line, charIndex, chr, sequence)) ||
charIndex < (charIndex = parseChar(lineIndex, line, charIndex, chr, sequence)) ||
charIndex < (charIndex = parseString(lineIndex, line, charIndex, chr, sequence)) ||
charIndex < (charIndex = parseNumeric(lineIndex, line, charIndex, chr, sequence)) ||
charIndex < (charIndex = parseOperator(lineIndex, line, charIndex, chr, sequence))
)
{
chr = line[charIndex];
continue;
}
throw new TextSourceException(package.getResourceString("lexer.character")) {
source = !(sequence instanceof TextSource) ? null : (TextSource) sequence,
lineIndex = lineIndex,
charIndex = charIndex
};
}
}
sequence.appendLexeme(lineIndexEnd, charIndexEnd, L_END);
}
public boolean documentationEnabled { read = fldDocumentationEnabled, write = fldDocumentationEnabled }
public DocumentLexer documentationLexer { read = fldDocumentationLexer, write = fldDocumentationLexer }
protected LexemeSequence newDocumentLexemeSequence() { return null; }
private int2 parseComment(char[][] text, int lineIndex, int lineIndexEnd, char[] last, char[] line, int charIndex, char chr, LexemeSequence sequence) {
if(chr != '/' || line[charIndex + 1] != '*') return new int2 { lineIndex, charIndex };
int charIndexContent = charIndex + 2;
int lineIndexResult = lineIndex;
int charIndexResult = charIndexContent;
boolean isDocumentation = line[charIndexResult] == '*' && line[charIndexResult + 1] != '/';
label0: for(; lineIndexResult <= lineIndexEnd; charIndexResult = 0, line = ++lineIndexResult >= lineIndexEnd ? last : text[lineIndexResult]) do
{
int charIndexEnd = Array.indexOf('*', line, charIndexResult, 0);
if(charIndexEnd < 0)
{
if(lineIndexResult < lineIndexEnd) break;
charIndexResult = line.length - 1;
break label0;
}
if(line[charIndexEnd + 1] == '/')
{
charIndexResult = charIndexEnd;
break label0;
}
charIndexResult = charIndexEnd + 1;
} while(true);
if(isDocumentation && fldDocumentationEnabled)
{
DocumentLexer lexer = fldDocumentationLexer;
if(lexer == null) lexer = defaultDocumentationLexer;
LexemeSequence documentation = newDocumentLexemeSequence();
if(documentation == null) documentation = new LexemeSequence();
lexer.split(text, new int2 { lineIndex, charIndexContent }, new int2 { lineIndexResult, charIndexResult }, documentation);
sequence.appendLexeme(lineIndex, charIndex, L_DOC, documentation);
}
if(line[charIndexResult] == '*') charIndexResult += 2;
return new int2 { lineIndexResult, charIndexResult };
}
}