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 tokens; private int position; private int line; private char currentChar; public Lexer(String input) { this.input = input; this.tokens = new ArrayList(); 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 getTokens() { for (Token token : this.tokens) { token.adjustType(); } return this.tokens; } }