package com.scanner;
import java.io.*;
import java.util.ArrayList;
import java.util.stream.*;
import java.util.Arrays;
import java.util.List;
public class JScanner {
/**
* @param file имя файла из которого необходимо считать код
*/
public JScanner(String file) {
this.path = pathToFolder + file;
}
private void init(){
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
String line;
while ((line = reader.readLine()) != null) {
inputCode += line + "\n";
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void scan() throws IOException{
init();
int state = 0;
for (int i = 0; i < inputCode.length(); i++) {
state = automatic(inputCode.charAt(i), state);
if (state == -1) {
state = 0;
i -= 1;
}
}
}
/**
* @param elem
* @param state
* @return
*/
private int automatic(char elem, int state) {
int s = 0;
switch (state) {
case 0:
if (elem == ' ') {
s = 0;
}
if (isNum(elem)) {
s = 1;
int temp = Character.getNumericValue(elem);
numberBuf.add(temp);
}
if (isChar(elem)) {
s = 2;
charBuf.add(elem);
}
if (elem == '/') {
s = 3;
}
if (spliterTable.contains(elem)) {
int numInTable = parsingSpliterTable(elem);
int num = Special.SPLITER.ordinal() + 1;
ResultNumbers temp = new ResultNumbers(num, numInTable);
result.add(temp);
}
break;
case 1:
if (isNum(elem)) {
s = 1;
int temp = Character.getNumericValue(elem);
numberBuf.add(temp);
}
else {
s = -1;
String t = numberBuf.stream()
.map(n -> n.toString())
.collect(Collectors.joining(""));
int tempNum = Integer.parseInt(t);
int num = Special.NUMBER.ordinal() + 1;
int numInTable = numberInConstTable(tempNum);
ResultNumbers temp = new ResultNumbers(num, numInTable);
result.add(temp);
numberBuf.clear();
}
break;
case 2:
if (isChar(elem)) {
s = 2;
charBuf.add(elem);
}
else {
String temp = charBuf.stream().map(ch -> ch.toString()).collect(Collectors.joining(""));
charBuf.clear();
if (parsingKeywordTable(temp)) {
s = 0;
int num = Special.KEYWORD.ordinal() + 1;
int numInTable = keywordTable.indexOf(temp) + 1;
ResultNumbers t = new ResultNumbers(num, numInTable);
result.add(t);
}
else {
s = -1;
int num = Special.IDENTIFIACTOR.ordinal() + 1;
int numInTable = numberInNameTable(temp);
ResultNumbers t = new ResultNumbers(num, numInTable);
result.add(t);
}
}
break;
case 3:
if (elem == '/') {
s = 4;
}
else {
s = -1;
int num = Special.SPLITER.ordinal() + 1;
int numInTable = parsingSpliterTable('/');
ResultNumbers t = new ResultNumbers(num, numInTable);
result.add(t);
}
break;
case 4:
if (elem != '\n') {
s = 4;
}
else {
s = 0;
int num = Special.COMMENTS.ordinal() + 1;
int numInTable = -1;
ResultNumbers t = new ResultNumbers(num, numInTable);
result.add(t);
}
break;
}
return s;
}
private int parsingSpliterTable(char ch) {
return spliterTable.indexOf(ch) + 1;
}
private boolean parsingKeywordTable(String str) {
return keywordTable.contains(str);
}
private int numberInConstTable(int cnst) {
if (constantTable.contains(cnst)) {
return constantTable.indexOf(cnst) + 1;
}
else {
constantTable.add(cnst);
return constantTable.indexOf(cnst) + 1;
}
}
private int numberInNameTable(String name) {
if (nameTable.contains(name)) {
return nameTable.indexOf(name);
}
else {
nameTable.add(name);
return nameTable.indexOf(name);
}
}
private boolean isChar(char ch) {
return ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
}
private boolean isNum(char ch) {
return (ch >= '0' && ch <= '9');
}
public void printResult() {
result.forEach(e -> System.out.println(e.getNumbers()));
}
private String path;
private String inputCode = "";
private final List<Character> spliterTable = Arrays.asList(';', '+', '-', '*', '=', '/', '(', ')', '{', '}');
private final List<String> keywordTable = Arrays.asList("for", "if", "else", "int");
private ArrayList<Integer> constantTable = new ArrayList<>();
private ArrayList<String> nameTable = new ArrayList<>();
private ArrayList<ResultNumbers> result = new ArrayList<>();
private ArrayList<Integer> numberBuf = new ArrayList<>();
private ArrayList<Character> charBuf = new ArrayList<>();
public ArrayList<String> getNameTable() {
return nameTable;
}
public ArrayList<Integer> getConstantTable() {
return constantTable;
}
private class ResultNumbers {
public ResultNumbers(int first, int second) {
this.first = first;
this.second = second;
}
public String getNumbers() {
return String.format("[%d, %d]", first, second);
}
private int first;
private int second;
}
private enum Special {NUMBER, SPLITER, KEYWORD, IDENTIFIACTOR, COMMENTS};
private final String pathToFolder = "/Users/nikita/IdeaProjects/Scanner/data/";
}