import java.io.;
import java.util.;
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.out.println("Usage: java Project1Parser <filename>");
return;
}
String content = new String(Files.readAllBytes(Paths.get(args[0])));
Project1Parser parser = new Project1Parser();
parser.run(content, args[0]);
}
void run(String input, String filename) {
this.input = input;
System.out.println("Testing: " + filename + "\n");
// Lexical analysis
tokenize();
System.out.println("Tokens:");
tokens.forEach(System.out::println);
System.out.println();
// Syntax analysis
boolean valid = parse();
System.out.println(valid ?
"The Test Source Code is generated by the grammar" :
"The Test Source Code cannot be generated by the Project1 EBNF Defined Language");
}
void tokenize() {
while (pos < input.length()) {
char c = input.charAt(pos);
if (Character.isWhitespace(c)) { pos++; continue; }
if (Character.isLetter(c)) {
String word = readWord();
if (word.equals("int") || word.equals("while") || word.equals("void")) {
tokens.add(new Token("KEYWORD", word));
} else {
tokens.add(new Token("IDENT", word));
}
} else if (Character.isDigit(c)) {
tokens.add(new Token("CONST", readNumber()));
} else {
switch (c) {
case '(': tokens.add(new Token("LPAREN", "(")); break;
case ')': tokens.add(new Token("RPAREN", ")")); break;
case '{': tokens.add(new Token("LBRACE", "{")); break;
case '}': tokens.add(new Token("RBRACE", "}")); break;
case ';': tokens.add(new Token("SEMICOLON", ";")); break;
case '=': tokens.add(new Token("ASSIGN", "=")); break;
case '+': tokens.add(new Token("PLUS", "+")); break;
case '<':
if (pos + 1 < input.length() && input.charAt(pos + 1) == '=') {
tokens.add(new Token("LESS_EQUAL", "<=")); pos++;
} else {
tokens.add(new Token("LESS", "<"));
}
break;
default: tokens.add(new Token("UNKNOWN", String.valueOf(c)));
}
pos++;
}
}
}
String readWord() {
StringBuilder sb = new StringBuilder();
while (pos < input.length() && Character.isLetterOrDigit(input.charAt(pos))) {
sb.append(input.charAt(pos++));
}
return sb.toString();
}
String readNumber() {
StringBuilder sb = new StringBuilder();
while (pos < input.length() && Character.isDigit(input.charAt(pos))) {
sb.append(input.charAt(pos++));
}
return sb.toString();
}
boolean parse() {
int index = 0;
try {
// <program> -> <keyword> <ident> ( ) { <declares> <loop><assignment>}
if (!match("KEYWORD", index)) return false; index++;
if (!match("IDENT", index)) return false; index++;
if (!match("LPAREN", index)) return false; index++;
if (!match("RPAREN", index)) return false; index++;
if (!match("LBRACE", index)) return false; index++;
if (!parseDeclares(index)) return false; index += 4; // keyword ident = const;
if (!parseLoop(index)) return false; index += 5; // keyword ( ident <= const )
if (!parseAssignment(index)) return false; index += 5; // ident = ident + ident;
if (!match("RBRACE", index)) return false;
return index == tokens.size() - 1;
} catch (Exception e) {
return false;
}
}
boolean parseDeclares(int start) {
return match("KEYWORD", start) && match("IDENT", start + 1) &&
match("ASSIGN", start + 2) && match("CONST", start + 3) &&
match("SEMICOLON", start + 4);
}
boolean parseLoop(int start) {
return match("KEYWORD", start) && match("LPAREN", start + 1) &&
match("IDENT", start + 2) && match("LESS_EQUAL", start + 3) &&
match("CONST", start + 4) && match("RPAREN", start + 5);
}
boolean parseAssignment(int start) {
return match("IDENT", start) && match("ASSIGN", start + 1) &&
match("IDENT", start + 2) && match("PLUS", start + 3) &&
match("IDENT", start + 4) && match("SEMICOLON", start + 5);
}
boolean match(String type, int index) {
return index < tokens.size() && tokens.get(index).type.equals(type);
}
import java.io.;
import java.util.;
class Token {
String type, value;
public Token(String t, String v) { type = t; value = v; }
public String toString() { return "[" + type + ", " + value + "]"; }
}
public class Project1Parser {
private String input;
private int pos = 0;
private List tokens = new ArrayList<>();
}