-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLanguage.java
156 lines (141 loc) · 5.54 KB
/
Language.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package com.randommurican.Parsemer;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* The Language class handles most of the functionality
*
* @author ej Byrne
*/
public class Language {
private List<Lexeme> lexemes;
private List<Kind> kinds; // List of patterns we look for
private boolean wasError;
private int currentLexeme;
/**
* Declaration of the language that turns the grammar file into
* regEx statements
*
* @param grammar
* @throws FileNotFoundException
*/
Language() {
lexemes = new ArrayList<Lexeme>();
kinds = new ArrayList<Kind>();
wasError = false;
currentLexeme = 0;
// Hardcoding the grammar for simplicity
kinds.add(new Kind("lessThan", "<", false));
kinds.add(new Kind("equal", "=", false));
kinds.add(new Kind("plus", "\\+", false));
kinds.add(new Kind("minus", "-", false));
kinds.add(new Kind("multiply", "\\*", false));
kinds.add(new Kind("divide", "/", false));
kinds.add(new Kind("or", "or", false));
kinds.add(new Kind("and", "and", false));
kinds.add(new Kind("not", "not", false));
kinds.add(new Kind("openParentheses", "\\(", false));
kinds.add(new Kind("closeParentheses", "\\)", false));
kinds.add(new Kind("true", "(true)", false));
kinds.add(new Kind("false", "(false)", false));
kinds.add(new Kind("ID", "[a-zA-Z]([a-zA-Z]|[0-9]|(_))*", true));
kinds.add(new Kind("NUM", "[0-9]+", true));
}
/**
* Takes input and turns it into a list of lexemes
*
* @param input
* @throws FileNotFoundException
*/
public void parse(File input) throws FileNotFoundException {
wasError = false; // Reset to default error state
Scanner inputScanner = new Scanner(input); // Start reading the input
lexemes.clear(); // Delete any data from previous reads
int line = 1, start = 1;
while(inputScanner.hasNextLine() && !wasError) { // While the file has more text
String lexemeString = "", str = inputScanner.nextLine();
for(int i = 0; i <= str.length(); i++) { // traverse the line
if(lexemeString.equals("/") && str.charAt(i) == '/') { // If the indexed character is a comment
i = str.length(); // move to the next line
lexemeString = "";
} else if(i < str.length() && str.charAt(i) != ' ' && str.charAt(i) != '\t') { // If the indexed character isn't white space
if( str.charAt(i) == '(' || str.charAt(i) == ')') { // and we found parentheses
if(lexemeString != "") { // and there was something before the parentheses
if(!addLexeme(lexemeString, line, start)) // attempt to add the lexeme before the parentheses
i = str.length();
lexemeString = "";
}
if(!wasError) { // if no error occurred
if(!addLexeme(String.valueOf(str.charAt(i)), line, start)) // attempt to add the parentheses as a lexeme
i = str.length();
lexemeString = "";
}
} else { // if the character wasn't a parentheses
lexemeString += str.charAt(i); // add the character to the lexemeString
if(lexemeString.length() == 1) { // if that was the first addition to the string
start = i; // mark this position as the start of the lexeme
}
}
} else if(lexemeString != "") { // if the indexed character was a space or end of line and we have a lexemeString
if(!addLexeme(lexemeString, line, start)) // attempt to add lexeme
i = str.length();
lexemeString = "";
}
}
line++; // move to the next line and repeat the for loop
}
inputScanner.close();
}
/**
* attempts to create a new lexeme and add it to the lexeme list
*
* @param lexeme
* @param line
* @param pos
* @return success
*/
public boolean addLexeme(String lexeme, int line, int pos) {
lexemes.add(new Lexeme(lexeme, kinds, line, pos+1));
if(!lexemes.get(lexemes.size()-1).getSuccess()) // if the added lexeme wasn't supported by the grammar
wasError = true; // indicate an error
return !wasError;
}
/**
* Outputs the lexemes in order in the terminal
*/
public void print() {
if(!wasError && lexemes.size() > 0) { // Check that there wasn't an error and we actually have lexemes (file wasn't empty)
do { // Since there is at least 1 lexeme, print first ask questions later
if(!(value() == null))
System.out.println(position() + ", " + kind() + ", " + value()); // Print with value
else
System.out.println(position() + ", " + kind()); // Print without value
} while ( next() != null ); // attempt to pull the next lexeme and stop if we get an error otherwise loop
}
}
/*
* Project Requirements
*/
public Lexeme next() {
Lexeme temp; // Good practice to avoid sending the real object
if(currentLexeme < lexemes.size() - 1) { // If there is a next lexeme
currentLexeme++; // select it
temp = lexemes.get(currentLexeme); // copy it
return temp; // and return it
} else
return null; // otherwise return a null
}
public String kind() {
return lexemes.get(currentLexeme).getKind();
}
public String value() {
return lexemes.get(currentLexeme).getValue();
}
public String position() {
return lexemes.get(currentLexeme).getPos();
}
public int getCurrentLexeme() {return currentLexeme;}
public int getLexemeCount() {return lexemes.size();}
}