finished exercise

This commit is contained in:
2025-10-22 17:36:49 +02:00
parent b9174804cc
commit 433a22b6af

View File

@@ -1,15 +1,15 @@
package ssw.mj.impl;
import ssw.mj.Errors;
import ssw.mj.Interpreter;
import ssw.mj.scanner.Token;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static ssw.mj.scanner.Token.Kind.*;
import static ssw.mj.scanner.Token.Kind.number;
public class Scanner {
@@ -112,40 +112,60 @@ public class Scanner {
}
if (isDigit(ch)) {
final var number = readNumber();
final var stringNumber = readNumber();
var token = new Token(Token.Kind.number, ogLine, ogCol);
token.numVal = number;
token.val = number + "";
try {
final var number = Integer.parseInt(stringNumber);
return token;
var token = new Token(Token.Kind.number, ogLine, ogCol);
token.numVal = number;
token.val = stringNumber;
return token;
} catch (NumberFormatException exception) {
final var token = new Token(number, ogLine, ogCol);
error(token, Errors.Message.BIG_NUM, stringNumber);
return token;
}
}
if (ch == '\'') {
nextCh();
if (ch == '\r') {
nextCh();
}
var charContent = ch;
var lfEscaped = false;
var tickEscaped = false;
if (ch == '\\') {
nextCh();
final var charContent = switch (ch) {
charContent = switch (ch) {
case 'n' -> '\n';
case 'r' -> '\r';
case 't' -> '\t';
case '\\' -> '\\';
case '\'' -> '\'';
default -> ' ';
default -> '\0';
};
final var token = new Token(charConst, ogLine, ogCol);
token.val = charContent + "";
token.numVal = charContent;
nextCh();
nextCh();
return token;
if (charContent == '\n') {
lfEscaped = true;
}
if (charContent == '\'') {
tickEscaped = true;
}
if (charContent == '\0') {
final var token = new Token(charConst, ogLine, ogCol);
error(token, Errors.Message.UNDEFINED_ESCAPE, ch);
}
}
final var charContent = ch;
if (charContent == LF || charContent == EOF || charContent == '\'') {
if (charContent == LF && !lfEscaped || charContent == EOF || charContent == '\'' && !tickEscaped) {
final var token = new Token(charConst, ogLine, ogCol);
final var message = switch (charContent) {
case LF -> Errors.Message.ILLEGAL_LINE_END;
@@ -191,14 +211,19 @@ public class Scanner {
case '.' -> new Token(Token.Kind.period, ogLine, ogCol);
case '{' -> new Token(Token.Kind.lbrace, ogLine, ogCol);
case '}' -> new Token(Token.Kind.rbrace, ogLine, ogCol);
case '[' -> new Token(Token.Kind.lbrack, ogLine, ogCol);
case ']' -> new Token(Token.Kind.rbrack, ogLine, ogCol);
case '(' -> new Token(Token.Kind.lpar, ogLine, ogCol);
case ')' -> new Token(Token.Kind.rpar, ogLine, ogCol);
case (char) -1 -> new Token(Token.Kind.eof, ogLine, ogCol);
case '~' -> new Token(Token.Kind.tilde, ogLine, ogCol);
case '=' -> {
if (ch == '=') {
nextCh();
yield new Token(Token.Kind.eql, ogLine, ogCol);
}
yield new Token(Token.Kind.assign, line, col);
yield new Token(Token.Kind.assign, ogLine, ogCol);
}
case '+' -> {
if (ch == '=') {
@@ -240,6 +265,18 @@ public class Scanner {
yield new Token(Token.Kind.slashas, ogLine, ogCol);
}
if (ch == '*') {
nextCh();
final var success = skipComment();
if (success) {
yield next();
} else {
final var token = new Token(eof, ogLine, ogCol);
error(token, Errors.Message.EOF_IN_COMMENT);
yield next();
}
}
yield new Token(Token.Kind.slash, ogLine, ogCol);
}
case '%' -> {
@@ -256,8 +293,9 @@ public class Scanner {
yield new Token(Token.Kind.neq, ogLine, ogCol);
}
error(new Token(none, line, col), Errors.Message.INVALID_CHAR);
yield next();
final var token = new Token(none, ogLine, ogCol);
error(token, Errors.Message.INVALID_CHAR, ogChar);
yield token;
}
case '>' -> {
if (ch == '=') {
@@ -268,7 +306,7 @@ public class Scanner {
yield new Token(Token.Kind.gtr, ogLine, ogCol);
}
case '<' -> {
if (ch == '<') {
if (ch == '=') {
nextCh();
yield new Token(Token.Kind.leq, ogLine, ogCol);
}
@@ -281,21 +319,24 @@ public class Scanner {
yield new Token(Token.Kind.and, ogLine, ogCol);
}
error(new Token(none, line, col), Errors.Message.INVALID_CHAR);
yield next();
final var token = new Token(none, ogLine, ogCol);
error(token, Errors.Message.INVALID_CHAR, ogChar);
yield token;
}
case '|' -> {
if (ch == '|') {
nextCh();
yield new Token(Token.Kind.and, ogLine, ogCol);
yield new Token(Token.Kind.or, ogLine, ogCol);
}
error(new Token(none, line, col), Errors.Message.INVALID_CHAR);
yield next();
final var token = new Token(none, ogLine, ogCol);
error(token, Errors.Message.INVALID_CHAR, ogChar);
yield token;
}
default -> {
error(new Token(none, line, col), Errors.Message.INVALID_CHAR);
yield next();
final var token = new Token(none, ogLine, ogCol);
error(token, Errors.Message.INVALID_CHAR, ogChar);
yield token;
}
};
}
@@ -333,7 +374,7 @@ public class Scanner {
public String readName() {
final var builder = new StringBuilder();
while (isLetter(ch)) {
while (isLetter(ch) || ch == '_' || isDigit(ch)) {
builder.append(ch);
nextCh();
}
@@ -341,7 +382,7 @@ public class Scanner {
return builder.toString();
}
public int readNumber() {
public String readNumber() {
final var builder = new StringBuilder();
while (isDigit(ch)) {
@@ -349,7 +390,7 @@ public class Scanner {
nextCh();
}
return Integer.parseInt(builder.toString());
return builder.toString();
}
private Token getTokenByName(String name, int line, int col) {
@@ -364,6 +405,30 @@ public class Scanner {
return token;
}
private boolean skipComment() {
var commentCount = 1;
while (commentCount != 0) {
final var lastCh = ch;
nextCh();
if (lastCh == '/' && ch == '*') {
commentCount++;
nextCh();
}
if (lastCh == '*' && ch == '/') {
commentCount--;
nextCh();
}
if (ch == EOF && commentCount != 0) {
return false;
}
}
return true;
}
// ================================================
// ================================================
}