Skip to content

Commit

Permalink
Add full parser generator to pgen
Browse files Browse the repository at this point in the history
  • Loading branch information
Borjianamin98 authored and IYP-Programer-Yeah committed Sep 28, 2019
1 parent bf28ca3 commit 7f42519
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/main/java/ir/ac/sbu/controller/MainController.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.*;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class MainController {
@FXML
private ListView<GraphModel> list;
Expand Down Expand Up @@ -163,6 +167,30 @@ private void build(ActionEvent actionEvent) {
}
}

public void exportFullParser(ActionEvent actionEvent) {
renumber(null);
File directorySelected = DialogUtility.showDirectoryDialog(pane.getScene().getWindow());
try {
if (directorySelected != null) {
InputStream parserSource = ResourceUtility.getResourceAsStream("parser/Parser.code");
InputStream lexicalSource = ResourceUtility.getResourceAsStream("parser/Lexical.code");
InputStream codeGeneratorSource = ResourceUtility.getResourceAsStream("parser/CodeGenerator.code");
Path destination = Paths.get(directorySelected.getPath());

LLParserGenerator parser = new LLParserGenerator(graphs);
parser.buildTable(new File(destination + "/table.npt"));
Files.copy(parserSource, destination.resolve("Parser.java"), REPLACE_EXISTING);
Files.copy(lexicalSource, destination.resolve("Lexical.java"), REPLACE_EXISTING);
Files.copy(codeGeneratorSource, destination.resolve("CodeGenerator.java"), REPLACE_EXISTING);

DialogUtility.showSuccessDialog("Parser generated successfully");
}
} catch (TableException e) {
DialogUtility.showErrorDialog(e.getMessages());
} catch (IOException e) {
DialogUtility.showErrorDialog(e.getMessage());
}
}

public void checkGraphs(ActionEvent actionEvent) {
renumber(null);
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/ir/ac/sbu/parser/LLParserGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,6 @@ private Pair<LLCell[][], Integer> buildTable() throws TableException {
Map<Integer, Set<String>> totalFirstSets = getTotalFirstSets();
Map<String, Set<String>> totalFollowSets = getTotalFollowSets(totalFirstSets);

System.out.println(totalFirstSets);
System.out.println(totalFollowSets);

int totalTokensVariables = tokenAsInt.size();
LLCell[][] table = new LLCell[allNodes.size()][totalTokensVariables];
for (int i = 0; i < allNodes.size(); i++) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/fxml/Main.fxml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<MenuItem fx:id="exportTableMenuItem" mnemonicParsing="false" text="Build Pretty Table"/>
<MenuItem fx:id="exportCSVTableMenuItem" mnemonicParsing="false" text="Build CSV Table"/>
<MenuItem fx:id="exportMenuItem" mnemonicParsing="false" text="Export Functions"/>
<MenuItem fx:id="exportLLParserMenuItem" onAction="#exportFullParser" mnemonicParsing="false" text="Export Full Parser"/>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<MenuItem fx:id="aboutMenuItem" mnemonicParsing="false" onAction="#aboutMenu" text="About"/>
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/parser/CodeGenerator.code
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public interface CodeGenerator {
void doSemantic(String sem);
}
3 changes: 3 additions & 0 deletions src/main/resources/parser/Lexical.code
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public interface Lexical {
String nextToken();
}
167 changes: 167 additions & 0 deletions src/main/resources/parser/Parser.code
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

enum Action {
ERROR, SHIFT, GOTO, PUSH_GOTO, REDUCE, ACCEPT
}

class LLCell {
private Action action;
private int target;
private String function;

public LLCell(Action action, int target, String function) {
this.action = action;
this.target = target;
this.function = function;
}

public Action getAction() {
return action;
}

public int getTarget() {
return target;
}

public String getFunction() {
return function;
}
}


public class Parser {
private Lexical lexical;
private CodeGenerator codeGenerator;

private String[] symbols;
private LLCell[][] parseTable;
private int startNode;
private Deque<Integer> parseStack = new ArrayDeque<>();

private List<String> recoveryState;

public Parser(Lexical lexical, CodeGenerator codeGenerator, String nptPath) {
this.lexical = lexical;
this.codeGenerator = codeGenerator;
this.recoveryState = new ArrayList<>();

if (!Files.exists(Paths.get(nptPath))) {
throw new RuntimeException("Parser table not found: " + nptPath);
}

try {
Scanner in = new Scanner(new FileInputStream(nptPath));
String[] tmpArr = in.nextLine().trim().split(" ");
int rowSize = Integer.valueOf(tmpArr[0]);
int colSize = Integer.valueOf(tmpArr[1]);
startNode = Integer.valueOf(in.nextLine());
symbols = in.nextLine().trim().split(" ");

parseTable = new LLCell[rowSize][colSize];
for (int i = 0; i < rowSize; i++) {
tmpArr = in.nextLine().trim().split(" ");
if (tmpArr.length != colSize * 3) {
throw new RuntimeException("Invalid .npt file");
}

for (int j = 0; j < colSize; j++) {
parseTable[i][j] = new LLCell(Action.values()[Integer.parseInt((tmpArr[j * 3]))],
Integer.parseInt(tmpArr[j * 3 + 1]),
tmpArr[j * 3 + 2]);
}
}
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
throw new RuntimeException("Invalid .npt file");
} catch (FileNotFoundException e) {
throw new RuntimeException("Unable to load .npt file", e);
}
}

public void parse() {
int tokenID = nextTokenID();
int currentNode = startNode;
boolean accepted = false;
while (!accepted) {
String tokenText = symbols[tokenID];
LLCell cell = parseTable[currentNode][tokenID];
switch (cell.getAction()) {
case ERROR:
updateRecoveryState(currentNode, tokenText);
generateError("Unable to parse input");
case SHIFT:
doSemantics(cell.getFunction());
tokenID = nextTokenID();
currentNode = cell.getTarget();
recoveryState.clear();
break;
case GOTO:
updateRecoveryState(currentNode, tokenText);
doSemantics(cell.getFunction());
currentNode = cell.getTarget();
break;
case PUSH_GOTO:
updateRecoveryState(currentNode, tokenText);
parseStack.push(currentNode);
currentNode = cell.getTarget();
break;
case REDUCE:
if (parseStack.size() == 0) {
generateError("Unable to Reduce: token=" + tokenText + " node=" + currentNode);
}
updateRecoveryState(currentNode, tokenText);
int graphToken = cell.getTarget();
int preNode = parseStack.pop();
doSemantics(parseTable[preNode][graphToken].getFunction());
currentNode = parseTable[preNode][graphToken].getTarget();
break;
case ACCEPT:
accepted = true;
break;
}
}
}

private void generateError(String message) {
for (String state : recoveryState) {
System.err.println(state);
}
throw new RuntimeException(message);
}

private void updateRecoveryState(int currentNode, String token) {
List<String> availableTokens = new ArrayList<>();
LLCell[] cellTokens = parseTable[currentNode];
for (int i = 0; i < cellTokens.length; i++) {
if (cellTokens[i].getAction() != Action.ERROR) {
availableTokens.add(symbols[i]);
}
}
recoveryState.add("At node " + currentNode + ": current token is " + token + " but except: " + availableTokens);
}

private int nextTokenID() {
String token = lexical.nextToken();
for (int i = 0; i < symbols.length; i++) {
if (symbols[i].equalsIgnoreCase(token)) {
return i;
}
}
throw new RuntimeException("Undefined token: " + token);
}

private void doSemantics(String semantics) {
if (semantics.equals("NoSem")) {
return;
}
semantics = semantics.substring(1);
String[] allFunctions = semantics.split("[;]");
for (String function : allFunctions) {
if (function.length() > 0) {
codeGenerator.doSemantic(function);
}
}
}
}

0 comments on commit 7f42519

Please sign in to comment.