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