Files
MY_COMPILER/frontend/lexer/Lexer.java
2025-12-12 20:14:00 +08:00

246 lines
7.8 KiB
Java
Executable File

package frontend.lexer;
import java.util.ArrayList;
import error.Error;
import error.ErrorType;
import error.Errors;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
public class Lexer {
private String input;
private ArrayList<Token> tokens;
private int position;
private int line;
private char currentChar;
public Lexer(String input) {
this.input = input;
this.tokens = new ArrayList<Token>();
this.position = 0;
this.line = 1;
}
public void lex(Errors errors) {
int sigComment = 0;
while (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position);
if (currentChar == ' ' || currentChar == '\t') {
this.position++;
continue;
}
if (currentChar == '\n' || currentChar == '\r') {
if (currentChar == '\r') {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '\n') {
this.position++;
}
}
this.line++;
this.position++;
if (sigComment == 1) {
sigComment = 0;
}
continue;
}
if (sigComment == 0) {
if (currentChar == '/') {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '/') {
sigComment = 1;
this.position += 2;
continue;
}
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '*') {
sigComment = 2;
this.position += 2;
continue;
}
}
if (this.isIntCons()) {
lexInt();
continue;
}
if (this.isStrCons()) {
lexStr();
continue;
}
if (this.isIdenfr()) {
lexIdenfr();
continue;
}
lexOp(errors);
}
if (sigComment == 2) {
if (this.position + 1 < this.input.length() &&
this.currentChar == '*' && this.input.charAt(this.position + 1) == '/') {
sigComment = 0;
this.position += 2;
continue;
}
}
if (sigComment != 0) {
this.position++;
}
}
}
public boolean isIntCons() {
return Character.isDigit(this.currentChar);
}
public boolean isStrCons() {
return this.currentChar == '"';
}
public boolean isIdenfr() {
return Character.isLowerCase(this.currentChar) || Character.isUpperCase(this.currentChar)
|| this.currentChar == '_';
}
public boolean isNotWp() {
return !Character.isWhitespace(this.currentChar);
}
public boolean isOp() {
return !this.isIntCons() && !this.isStrCons() && !this.isIdenfr();
}
public void lexInt() {
StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && this.isIntCons()) {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexStr() {
StringBuilder sb = new StringBuilder();
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
while (this.position < this.input.length() && this.currentChar != '"') {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
if (this.position < this.input.length() && this.currentChar == '"') {
sb.append(this.currentChar);
this.position++;
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexIdenfr() {
StringBuilder sb = new StringBuilder();
while (this.position < this.input.length() && (this.isIdenfr() || this.isIntCons())) {
sb.append(this.currentChar);
this.position++;
updateCurrentChar();
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void lexOp(Errors errors) {
StringBuilder sb = new StringBuilder();
if (this.currentChar == '/' && this.position + 1 < this.input.length() &&
(this.input.charAt(this.position + 1) == '/' ||
this.input.charAt(this.position + 1) == '*')) {
return;
}
sb.append(this.currentChar);
switch (this.currentChar) {
case '&':
readAnd(sb);
break;
case '|':
readOr(sb);
break;
case '<':
readEq(sb);
break;
case '>':
readEq(sb);
break;
case '=':
readEq(sb);
break;
case '!':
readEq(sb);
break;
default:
break;
}
this.position++;
if (sb.toString().equals("&") || sb.toString().equals("|")) {
errors.addError(new Error(this.line, ErrorType.a));
}
this.tokens.add(new Token(sb.toString(), this.line));
}
public void readAnd(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '&') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void readOr(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '|') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void readEq(StringBuilder sb) {
if (this.position + 1 < this.input.length() &&
this.input.charAt(this.position + 1) == '=') {
this.position++;
currentChar = this.input.charAt(this.position);
sb.append(currentChar);
}
}
public void updateCurrentChar() {
if (this.position < this.input.length()) {
currentChar = this.input.charAt(this.position);
}
}
public void printTokens() {
for (Token token : this.tokens) {
token.adjustType();
System.out.println(token.getType() + " " + token.getValue() + " " + token.getLine());
}
}
public void writeToFile(String fileName) {
try {
StringBuilder sb = new StringBuilder();
for (Token token : this.tokens) {
token.adjustType();
sb.append(token.toString());
}
Files.write(Paths.get(fileName), sb.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public ArrayList<Token> getTokens() {
for (Token token : this.tokens) {
token.adjustType();
}
return this.tokens;
}
}