private static NFA generateNFA(Character operator, NFA operand1, NFA operand2) { NFA resultantNFA = null; switch (operator) { case '.': resultantNFA = NFABuilder.concat(operand1, operand2); break; case '|': resultantNFA = NFABuilder.or(operand1, operand2); break; case '*': resultantNFA = NFABuilder.kleeneStar(operand1); break; case '+': try { resultantNFA = NFABuilder.kleenePlus(operand1); } catch (CloneNotSupportedException e) { e.printStackTrace(); } break; } return resultantNFA; }
public static NFAState getRulesNFA(String filePath) throws Exception { tokeNames = new HashMap<String, String>(); int lineNumber = 0; try (BufferedReader br = new BufferedReader(new FileReader(filePath))) { String line = br.readLine(); while (line != null) { lineNumber++; // Read line, separate on four cases { , [ , expression, definition if (line.charAt(0) == '{') { String lineWithoutBrackets = line.substring(1, line.length() - 1).trim(); for (String token : lineWithoutBrackets.split(" ")) { NFA stringNFA = NFABuilder.s(token); expressions.put(token, stringNFA); tokeNames.put(token, token.toUpperCase()); stringNFA.getOutputState().setAcceptingString(0 + " " + token); } } else if (line.charAt(0) == '[') { for (int i = 1; i < line.length() - 1; i++) { char parsedChar = line.charAt(i); if (parsedChar != '\\' && parsedChar != ' ') { NFA punctuationNFA = NFABuilder.c(parsedChar); tokeNames.put(parsedChar + "", parsedChar + "_PUNCT"); expressions.put(parsedChar + "", punctuationNFA); punctuationNFA.getOutputState().setAcceptingString(0 + " " + parsedChar); } } } else { // Expressions OR Definitions Boolean isDefinition; String LHSName; if ((line.indexOf('=') != -1 && line.indexOf('=') < line.indexOf(':')) || line.indexOf(':') == -1) { isDefinition = true; } else { isDefinition = false; } if (isDefinition) { LHSName = line.substring(0, line.indexOf('=')).trim(); line = line.substring(line.indexOf('=') + 1); } else { LHSName = line.substring(0, line.indexOf(':')).trim(); line = line.substring(line.indexOf(':') + 1); } // Tokenize line, separate on operators or space ArrayList<String> lineTokens = tokenize(line); System.out.println(lineTokens); // Parse tokens with precedence String token; operands = new Stack<NFA>(); operators = new Stack<Character>(); for (int i = 0; i < lineTokens.size(); i++) { token = lineTokens.get(i); if (isOperator(token)) { // operator char operator = token.charAt(0); if (operator == ' ') { throw new Exception("CANNOT BE A SPACE AS OPERATOR!"); } else if (operator == '-') { // specially treated operator, no precedence rules, may be implemented in a neat way // later char begin = lineTokens.get(i - 1).charAt(0), end = lineTokens.get(i + 1).charAt(0); i++; char index = begin; ArrayList<Character> rangeChars = new ArrayList<>(); while (index <= end) { rangeChars.add(index); index = (char) (index + 1); } NFA tempNFA = NFABuilder.or(rangeChars.toArray()); operands.pop(); // remove the first character of the range operator from stack operands.push(tempNFA); } else { // operators: * + | ( ) . parseOperator(operator); } if (i + 1 < lineTokens.size()) { String nextToken = lineTokens.get(i + 1); // Check for concatenation after + * ) if (operator == '+' || operator == '*' || operator == ')') { if (!isOperator(nextToken) || nextToken.equals("(")) { parseOperator('.'); } } } } else { // operand NFA operandNFA = getOperandNFA(token); if (operandNFA != null) { operands.push(operandNFA); } // Check for concatenation operator after the operand if (i + 1 < lineTokens.size()) { String nextToken = lineTokens.get(i + 1); if (!isOperator(nextToken)) { parseOperator('.'); } else if (nextToken.equals("(")) { parseOperator('.'); } } } } // empty the operators stack executeStack(); NFA resultNFA = operands.pop(); if (isDefinition) { definitions.put(LHSName, resultNFA); } else { tokeNames.put(LHSName, LHSName.toUpperCase()); expressions.put(LHSName, resultNFA); resultNFA.getOutputState().setAcceptingString(lineNumber + " " + LHSName); } } line = br.readLine(); } // Combine each line's NFA in a single NFA // NFA resultantNFA = NFABuilder.or(expressions.values().toArray()); NFAState resultantNFAInitialState = NFABuilder.combine(expressions.values().toArray()); return resultantNFAInitialState; } catch (Exception e) { e.printStackTrace(); return null; } }