From 36e0911c6ec27707a74f0b90b1052a16374243ea Mon Sep 17 00:00:00 2001 From: bjculkin Date: Wed, 1 Mar 2017 10:13:41 -0500 Subject: Package reorganization --- dice-lang/src/bjc/dicelang/Parser.java | 167 +++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 dice-lang/src/bjc/dicelang/Parser.java (limited to 'dice-lang/src/bjc/dicelang/Parser.java') diff --git a/dice-lang/src/bjc/dicelang/Parser.java b/dice-lang/src/bjc/dicelang/Parser.java new file mode 100644 index 0000000..4733ced --- /dev/null +++ b/dice-lang/src/bjc/dicelang/Parser.java @@ -0,0 +1,167 @@ +package bjc.dicelang; + +import static bjc.dicelang.Errors.ErrorKey.*; +import static bjc.dicelang.Node.Type.*; +import static bjc.dicelang.Token.Type.*; + +import java.util.Deque; +import java.util.LinkedList; + +import bjc.utils.data.ITree; +import bjc.utils.data.Tree; +import bjc.utils.funcdata.IList; + +public class Parser { + public Parser() { + + } + + public boolean parseTokens(IList tokens, + IList> results) { + Deque> working = new LinkedList<>(); + + for(Token tk : tokens) { + switch(tk.type) { + case OBRACKET: + case OBRACE: + working.push(new Tree<>(new Node(OGROUP, tk))); + break; + case CBRACKET: + case CBRACE: + boolean sc = parseClosingGrouper(working, tk); + if(!sc) return false; + break; + case LET: + case BIND: + if(working.size() < 2) { + Errors.inst.printError(EK_PARSE_BINARY); + return false; + } else { + ITree right = working.pop(); + ITree left = working.pop(); + + ITree opNode = new Tree<>(new Node(BINOP, tk.type)); + + working.push(opNode); + } + break; + case ADD: + case SUBTRACT: + case MULTIPLY: + case DIVIDE: + case IDIVIDE: + case DICEGROUP: + case DICECONCAT: + case DICELIST: + if(working.size() == 0) { + Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString()); + return false; + } else if(working.size() == 1) { + ITree operand = working.pop(); + + ITree opNode = new Tree<>(new Node(UNARYOP, tk.type)); + + opNode.addChild(operand); + + working.push(opNode); + } else { + ITree right = working.pop(); + ITree left = working.pop(); + + ITree opNode = new Tree<>(new Node(BINOP, tk.type)); + + opNode.addChild(left); + opNode.addChild(right); + + working.push(opNode); + } + break; + case COERCE: + if(working.size() == 0) { + Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString()); + } else { + ITree operand = working.pop(); + ITree opNode = new Tree<>(new Node(UNARYOP, tk.type)); + + opNode.addChild(operand); + + working.push(opNode); + } + break; + case INT_LIT: + case FLOAT_LIT: + case STRING_LIT: + case VREF: + case DICE_LIT: + working.push(new Tree<>(new Node(TOKREF, tk))); + break; + default: + Errors.inst.printError(EK_PARSE_INVTOKEN, tk.type.toString()); + return false; + } + } + + for(ITree ast : working) { + results.add(ast); + } + + return true; + } + + private boolean parseClosingGrouper(Deque> working, Token tk) { + if(working.size() == 0) { + Errors.inst.printError(EK_PARSE_NOCLOSE); + return false; + } + + ITree groupNode = null; + switch(tk.type) { + case CBRACE: + groupNode = new Tree<>(new Node(GROUP, Node.GroupType.CODE)); + break; + case CBRACKET: + groupNode = new Tree<>(new Node(GROUP, Node.GroupType.ARRAY)); + break; + default: + break; + } + + Token matching = null; + if(tk.type == CBRACKET) { + matching = new Token(Token.Type.OBRACKET, tk.intValue); + } else if(tk.type == CBRACE) { + matching = new Token(Token.Type.OBRACE, tk.intValue); + } + + ITree matchNode = new Tree<>(new Node(OGROUP, matching)); + if(!working.contains(matchNode)) { + Errors.inst.printError(EK_PARSE_UNCLOSE, tk.toString(), matchNode.toString()); + + System.out.println("\tCurrent forest is: "); + + int treeNo = 1; + for(ITree ast : working) { + System.out.println("Tree " + treeNo++ + ": " + ast.toString()); + } + + return false; + } else { + Deque> childs = new LinkedList<>(); + + while(!working.peek().equals(matchNode)) { + childs.push(working.pop()); + } + + // Discard opener + working.pop(); + + for(ITree child : childs) { + groupNode.addChild(child); + } + + working.push(groupNode); + } + + return true; + } +} -- cgit v1.2.3