mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Added floating number scientific notation
This commit is contained in:
parent
2c0b19eb0a
commit
a87d5f7685
@ -164,6 +164,10 @@ public final class Lexer {
|
|||||||
if (current == '.') {
|
if (current == '.') {
|
||||||
if (hasDot) throw error("Invalid float number " + buffer);
|
if (hasDot) throw error("Invalid float number " + buffer);
|
||||||
hasDot = true;
|
hasDot = true;
|
||||||
|
} else if (current == 'e' || current == 'E') {
|
||||||
|
int exp = subTokenizeScientificNumber();
|
||||||
|
buffer.append(current).append(exp);
|
||||||
|
break;
|
||||||
} else if (!Character.isDigit(current)) {
|
} else if (!Character.isDigit(current)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -173,6 +177,34 @@ public final class Lexer {
|
|||||||
addToken(TokenType.NUMBER, buffer.toString(), startPos);
|
addToken(TokenType.NUMBER, buffer.toString(), startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int subTokenizeScientificNumber() {
|
||||||
|
int sign = 1;
|
||||||
|
switch (next()) {
|
||||||
|
case '-': sign = -1;
|
||||||
|
case '+': skip(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasValue = false;
|
||||||
|
char current = peek(0);
|
||||||
|
while (current == '0') {
|
||||||
|
hasValue = true;
|
||||||
|
current = next();
|
||||||
|
}
|
||||||
|
int result = 0;
|
||||||
|
int position = 0;
|
||||||
|
while (Character.isDigit(current)) {
|
||||||
|
result = result * 10 + (current - '0');
|
||||||
|
current = next();
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
if (position == 0 && !hasValue) throw error("Empty floating point exponent");
|
||||||
|
if (position >= 4) {
|
||||||
|
if (sign > 0) throw error("Float number too large");
|
||||||
|
else throw error("Float number too small");
|
||||||
|
}
|
||||||
|
return sign * result;
|
||||||
|
}
|
||||||
|
|
||||||
private void tokenizeHexNumber(int skipChars) {
|
private void tokenizeHexNumber(int skipChars) {
|
||||||
clearBuffer();
|
clearBuffer();
|
||||||
final Pos startPos = markPos();
|
final Pos startPos = markPos();
|
||||||
|
@ -26,6 +26,9 @@ public class LexerTest {
|
|||||||
public static Stream<Arguments> invalidData() {
|
public static Stream<Arguments> invalidData() {
|
||||||
return Stream.<Arguments>builder()
|
return Stream.<Arguments>builder()
|
||||||
.add(Arguments.of("Wrong float point", "3.14.15"))
|
.add(Arguments.of("Wrong float point", "3.14.15"))
|
||||||
|
.add(Arguments.of("Empty float exponent", "3e"))
|
||||||
|
.add(Arguments.of("Float number too small", "3e-00009000"))
|
||||||
|
.add(Arguments.of("Float number too large", "3e+00009000"))
|
||||||
.add(Arguments.of("Wrong HEX number", "0Xf7_p6_s5"))
|
.add(Arguments.of("Wrong HEX number", "0Xf7_p6_s5"))
|
||||||
.add(Arguments.of("HEX number ends with _", "0Xf7_"))
|
.add(Arguments.of("HEX number ends with _", "0Xf7_"))
|
||||||
.add(Arguments.of("Empty rest of HEX number", "#"))
|
.add(Arguments.of("Empty rest of HEX number", "#"))
|
||||||
@ -47,6 +50,16 @@ public class LexerTest {
|
|||||||
.containsExactly("0", "3.1415", "CAFEBABE", "f7d6c5", "FFFF");
|
.containsExactly("0", "3.1415", "CAFEBABE", "f7d6c5", "FFFF");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFloatNumbersExponent() {
|
||||||
|
String input = "4e+7 0.3E-19 2e0 5e0000000000000200 5E-000000089";
|
||||||
|
List<Token> result = Lexer.tokenize(input);
|
||||||
|
assertThat(result)
|
||||||
|
.allMatch(t -> t.type().equals(NUMBER))
|
||||||
|
.extracting(Token::text)
|
||||||
|
.containsExactly("4e7", "0.3E-19", "2e0", "5e200", "5E-89");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testString() {
|
public void testString() {
|
||||||
String input = "\"1\\\"2\"";
|
String input = "\"1\\\"2\"";
|
||||||
|
@ -25,6 +25,9 @@ public class LexerValidDataProvider {
|
|||||||
Arguments.of("Numbers",
|
Arguments.of("Numbers",
|
||||||
"12 7.8 90000000 10.03",
|
"12 7.8 90000000 10.03",
|
||||||
List.of(NUMBER, NUMBER, NUMBER, NUMBER)),
|
List.of(NUMBER, NUMBER, NUMBER, NUMBER)),
|
||||||
|
Arguments.of("Float notation",
|
||||||
|
"7e8",
|
||||||
|
List.of(NUMBER)),
|
||||||
Arguments.of("Hex numbers",
|
Arguments.of("Hex numbers",
|
||||||
"#FF 0xCA 0x12fb 0xFF",
|
"#FF 0xCA 0x12fb 0xFF",
|
||||||
List.of(HEX_NUMBER, HEX_NUMBER, HEX_NUMBER, HEX_NUMBER))
|
List.of(HEX_NUMBER, HEX_NUMBER, HEX_NUMBER, HEX_NUMBER))
|
||||||
@ -80,9 +83,6 @@ public class LexerValidDataProvider {
|
|||||||
|
|
||||||
private static List<Arguments> notSupported() {
|
private static List<Arguments> notSupported() {
|
||||||
return List.of(
|
return List.of(
|
||||||
Arguments.of("Float notation",
|
|
||||||
"7e8",
|
|
||||||
List.of(NUMBER, WORD)),
|
|
||||||
Arguments.of("Float hex numbers",
|
Arguments.of("Float hex numbers",
|
||||||
"0Xf7p6",
|
"0Xf7p6",
|
||||||
List.of(HEX_NUMBER, WORD))
|
List.of(HEX_NUMBER, WORD))
|
||||||
|
Loading…
Reference in New Issue
Block a user