diff --git a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java index a1184ad..50bf734 100644 --- a/AlgebraicDataflowArchitectureModel/src/parser/Parser.java +++ b/AlgebraicDataflowArchitectureModel/src/parser/Parser.java @@ -1,533 +1,492 @@ package parser; +import models.algebra.*; +import models.dataConstraintModel.*; +import models.dataFlowModel.DataTransferChannel; +import models.dataFlowModel.DataTransferModel; +import parser.exceptions.*; + import java.io.BufferedReader; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import models.algebra.Constant; -import models.algebra.Expression; -import models.algebra.Symbol; -import models.algebra.Term; -import models.algebra.Type; -import models.algebra.Variable; -import models.dataConstraintModel.ChannelMember; -import models.dataConstraintModel.DataConstraintModel; -import models.dataConstraintModel.JsonAccessor; -import models.dataConstraintModel.JsonTerm; -import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; -import models.dataConstraintModel.StateTransition; -import models.dataConstraintModel.StateTransitionTerm; -import models.dataFlowModel.DataTransferModel; -import models.dataFlowModel.DataTransferChannel; -import parser.exceptions.ExpectedAssignment; -import parser.exceptions.ExpectedChannel; -import parser.exceptions.ExpectedChannelName; -import parser.exceptions.ExpectedColon; -import parser.exceptions.ExpectedEquals; -import parser.exceptions.ExpectedInOrOutOrRefOrSubKeyword; -import parser.exceptions.ExpectedLeftCurlyBracket; -import parser.exceptions.ExpectedRHSExpression; -import parser.exceptions.ExpectedRightBracket; -import parser.exceptions.ExpectedRightCurlyBracket; -import parser.exceptions.ExpectedStateTransition; -import parser.exceptions.WrongJsonExpression; -import parser.exceptions.WrongLHSExpression; -import parser.exceptions.WrongPathExpression; -import parser.exceptions.WrongRHSExpression; +public class Parser { + protected TokenStream stream; -public class Parser { - protected TokenStream stream; + public static final String CHANNEL = "channel"; + public static final String INIT = "init"; + public static final String IN = "in"; + public static final String OUT = "out"; + public static final String REF = "ref"; + public static final String SUB_CHANNEL = "sub"; + public static final String NATIVE = "native"; + public static final String LEFT_CURLY_BRACKET = "{"; + public static final String RIGHT_CURLY_BRACKET = "}"; + public static final String LEFT_CURLY_BRACKET_REGX = "\\{"; + public static final String RIGHT_CURLY_BRACKET_REGX = "\\}"; + public static final String LEFT_BRACKET = "("; + public static final String RIGHT_BRACKET = ")"; + public static final String LEFT_BRACKET_REGX = "\\("; + public static final String RIGHT_BRACKET_REGX = "\\)"; + public static final String LEFT_SQUARE_BRACKET = "["; + public static final String RIGHT_SQUARE_BRACKET = "]"; + public static final String LEFT_SQUARE_BRACKET_REGX = "\\["; + public static final String RIGHT_SQUARE_BRACKET_REGX = "\\]"; + public static final String ADD = "+"; + public static final String MUL = "*"; + public static final String SUB = "-"; + public static final String DIV = "/"; + public static final String MOD = "%"; + public static final String MINUS = "-"; + public static final String EQ = "=="; + public static final String NEQ = "!="; + public static final String GT = ">"; + public static final String LT = "<"; + public static final String GE = ">="; + public static final String LE = "<="; + public static final String AND = "&&"; + public static final String OR = "||"; + public static final String NEG = "!"; + public static final String ADD_REGX = "\\+"; + public static final String MUL_REGX = "\\*"; + public static final String SUB_REGX = "\\-"; + public static final String DIV_REGX = "/"; + public static final String OR_REGX = "\\|\\|"; + public static final String EQUALS = "="; + public static final String ASSIGNMENT = "="; + public static final String COMMA = ","; + public static final String COLON = ":"; + public static final String DOT = "."; + public static final String DOT_REGX = "\\."; - public static final String CHANNEL = "channel"; - public static final String INIT = "init"; - public static final String IN = "in"; - public static final String OUT = "out"; - public static final String REF = "ref"; - public static final String SUB_CHANNEL = "sub"; - public static final String NATIVE = "native"; - public static final String LEFT_CURLY_BRACKET = "{"; - public static final String RIGHT_CURLY_BRACKET = "}"; - public static final String LEFT_CURLY_BRACKET_REGX = "\\{"; - public static final String RIGHT_CURLY_BRACKET_REGX = "\\}"; - public static final String LEFT_BRACKET = "("; - public static final String RIGHT_BRACKET = ")"; - public static final String LEFT_BRACKET_REGX = "\\("; - public static final String RIGHT_BRACKET_REGX = "\\)"; - public static final String LEFT_SQUARE_BRACKET = "["; - public static final String RIGHT_SQUARE_BRACKET = "]"; - public static final String LEFT_SQUARE_BRACKET_REGX = "\\["; - public static final String RIGHT_SQUARE_BRACKET_REGX = "\\]"; - public static final String ADD = "+"; - public static final String MUL = "*"; - public static final String SUB = "-"; - public static final String DIV = "/"; - public static final String MOD = "%"; - public static final String MINUS = "-"; - public static final String EQ = "=="; - public static final String NEQ = "!="; - public static final String GT = ">"; - public static final String LT = "<"; - public static final String GE = ">="; - public static final String LE = "<="; - public static final String AND = "&&"; - public static final String OR = "||"; - public static final String NEG = "!"; - public static final String ADD_REGX = "\\+"; - public static final String MUL_REGX = "\\*"; - public static final String SUB_REGX = "\\-"; - public static final String DIV_REGX = "/"; - public static final String OR_REGX = "\\|\\|"; - public static final String EQUALS = "="; - public static final String ASSIGNMENT = "="; - public static final String COMMA = ","; - public static final String COLON = ":"; - public static final String DOT = "."; - public static final String DOT_REGX = "\\."; + public Parser(final TokenStream stream) { + this.stream = stream; + } - public Parser(final TokenStream stream) { - this.stream = stream; - } + public Parser(final BufferedReader reader) { + this.stream = new TokenStream(); + try { + String line; + while ((line = reader.readLine()) != null) { + stream.addLine(line); + } + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } - public Parser(final BufferedReader reader) { - this.stream = new TokenStream(); - try { - String line; - while ((line = reader.readLine()) != null) { - stream.addLine(line); - } - reader.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public DataTransferModel doParse() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedRightCurlyBracket, - ExpectedInOrOutOrRefOrSubKeyword, ExpectedStateTransition, ExpectedEquals, - ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongPathExpression, WrongJsonExpression, ExpectedColon { - return parseDataFlowModel(); - } + public DataTransferModel doParse() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedRightCurlyBracket, ExpectedInOrOutOrRefOrSubKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongPathExpression, WrongJsonExpression, ExpectedColon { + return parseDataFlowModel(); + } - public DataTransferModel parseDataFlowModel() - throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedRightCurlyBracket, - ExpectedInOrOutOrRefOrSubKeyword, ExpectedStateTransition, ExpectedEquals, - ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongPathExpression, WrongJsonExpression, ExpectedColon { - DataTransferModel model = new DataTransferModel(); - DataTransferChannel channel; - while ((channel = parseChannel(model)) != null) { - if (channel.getInputChannelMembers().size() == 0) { - model.addInputChannel(channel); - } else { - model.addChannel(channel); - } - } - return model; - } + public DataTransferModel parseDataFlowModel() throws ExpectedRightBracket, ExpectedChannel, ExpectedChannelName, ExpectedLeftCurlyBracket, ExpectedRightCurlyBracket, ExpectedInOrOutOrRefOrSubKeyword, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedAssignment, WrongPathExpression, WrongJsonExpression, ExpectedColon { + DataTransferModel model = new DataTransferModel(); + DataTransferChannel channel; + while ((channel = parseChannel(model)) != null) { + if (channel.getInputChannelMembers().size() == 0) { + model.addInputChannel(channel); + } else { + model.addChannel(channel); + } + } + return model; + } - public DataTransferChannel parseChannel(DataTransferModel model) - throws ExpectedLeftCurlyBracket, ExpectedRightBracket, ExpectedRightCurlyBracket, ExpectedAssignment, - ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, - ExpectedChannel, ExpectedChannelName, ExpectedInOrOutOrRefOrSubKeyword, - ExpectedStateTransition, ExpectedEquals, WrongPathExpression, WrongJsonExpression, ExpectedColon { - if (!stream.hasNext()) return null; - if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; + public DataTransferChannel parseChannel(DataTransferModel model) throws ExpectedLeftCurlyBracket, ExpectedRightBracket, ExpectedRightCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, ExpectedChannel, ExpectedChannelName, ExpectedInOrOutOrRefOrSubKeyword, ExpectedStateTransition, ExpectedEquals, WrongPathExpression, WrongJsonExpression, ExpectedColon { + if (!stream.hasNext()) return null; + if (stream.checkNext().equals(RIGHT_CURLY_BRACKET)) return null; - boolean isNative = false; - String channelOrInitOrNativeKeyword = stream.next(); - if (channelOrInitOrNativeKeyword.equals(NATIVE)) { - // A native channel - isNative = true; - channelOrInitOrNativeKeyword = stream.next(); - } - if (!channelOrInitOrNativeKeyword.equals(CHANNEL) && !channelOrInitOrNativeKeyword.equals(SUB_CHANNEL)) { - if (!channelOrInitOrNativeKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); - parseInit(model); - channelOrInitOrNativeKeyword = stream.next(); - if (channelOrInitOrNativeKeyword.equals(NATIVE)) { - // A native channel - isNative = true; - channelOrInitOrNativeKeyword = stream.next(); - } - } - if (!stream.hasNext()) throw new ExpectedChannelName(stream.getLine()); + boolean isNative = false; + String channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { + // A native channel + isNative = true; + channelOrInitOrNativeKeyword = stream.next(); + } + if (!channelOrInitOrNativeKeyword.equals(CHANNEL) && !channelOrInitOrNativeKeyword.equals(SUB_CHANNEL)) { + if (!channelOrInitOrNativeKeyword.equals(INIT)) throw new ExpectedChannel(stream.getLine()); + parseInit(model); + channelOrInitOrNativeKeyword = stream.next(); + if (channelOrInitOrNativeKeyword.equals(NATIVE)) { + // A native channel + isNative = true; + channelOrInitOrNativeKeyword = stream.next(); + } + } + if (!stream.hasNext()) throw new ExpectedChannelName(stream.getLine()); - String channelName = stream.next(); - if (channelName.equals(LEFT_CURLY_BRACKET)) throw new ExpectedChannelName(stream.getLine()); + String channelName = stream.next(); + if (channelName.equals(LEFT_CURLY_BRACKET)) throw new ExpectedChannelName(stream.getLine()); - int fromLine = stream.getLine(); - DataTransferChannel channel = new DataTransferChannel(channelName); - if (isNative) { - channel.setNative(true); - } - String leftBracket = stream.next(); - if (leftBracket.equals(LEFT_BRACKET)) { - // has a selector - String selector = stream.next(); - Variable var = parseVariable(stream, model, selector); - channel.addSelector(var); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - leftBracket = stream.next(); - } - if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); + int fromLine = stream.getLine(); + DataTransferChannel channel = new DataTransferChannel(channelName); + if (isNative) { + channel.setNative(true); + } + String leftBracket = stream.next(); + if (leftBracket.equals(LEFT_BRACKET)) { + // has a selector + String selector = stream.next(); + Variable var = parseVariable(stream, model, selector); + channel.addSelector(var); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + leftBracket = stream.next(); + } + if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); - String inOrOutOrRefOrSub = null; - while (stream.hasNext() && !(inOrOutOrRefOrSub = stream.checkNext()).equals(RIGHT_CURLY_BRACKET)) { - ChannelMember channelMember = null; - if (inOrOutOrRefOrSub.equals(IN)) { - stream.next(); - channelMember = parseChannelMember(model, inOrOutOrRefOrSub); - if (channelMember != null) { - channel.addChannelMemberAsInput(channelMember); - } - } else if (inOrOutOrRefOrSub.equals(OUT)) { - stream.next(); - channelMember = parseChannelMember(model, inOrOutOrRefOrSub); - if (channelMember != null) { - channel.addChannelMemberAsOutput(channelMember); - } - } else if (inOrOutOrRefOrSub.equals(REF)) { - stream.next(); - channelMember = parseChannelMember(model, inOrOutOrRefOrSub); - if (channelMember != null) { - channel.addChannelMemberAsReference(channelMember); - } - } else if (inOrOutOrRefOrSub.equals(SUB_CHANNEL)) { - DataTransferChannel subChannel = parseChannel(model); - if (subChannel != null) { - channel.addChild(subChannel); - } - } else { - throw new ExpectedInOrOutOrRefOrSubKeyword(stream.getLine()); - } - } - if (stream.hasNext()) stream.next(); - int toLine = stream.getLine(); - channel.setSourceText(stream.getSourceText(fromLine, toLine)); - return channel; - } + String inOrOutOrRefOrSub = null; + while (stream.hasNext() && !(inOrOutOrRefOrSub = stream.checkNext()).equals(RIGHT_CURLY_BRACKET)) { + ChannelMember channelMember = null; + if (inOrOutOrRefOrSub.equals(IN)) { + stream.next(); + channelMember = parseChannelMember(model, inOrOutOrRefOrSub); + if (channelMember != null) { + channel.addChannelMemberAsInput(channelMember); + } + } else if (inOrOutOrRefOrSub.equals(OUT)) { + stream.next(); + channelMember = parseChannelMember(model, inOrOutOrRefOrSub); + if (channelMember != null) { + channel.addChannelMemberAsOutput(channelMember); + } + } else if (inOrOutOrRefOrSub.equals(REF)) { + stream.next(); + channelMember = parseChannelMember(model, inOrOutOrRefOrSub); + if (channelMember != null) { + channel.addChannelMemberAsReference(channelMember); + } + } else if (inOrOutOrRefOrSub.equals(SUB_CHANNEL)) { + DataTransferChannel subChannel = parseChannel(model); + if (subChannel != null) { + channel.addChild(subChannel); + } + } else { + throw new ExpectedInOrOutOrRefOrSubKeyword(stream.getLine()); + } + } + if (stream.hasNext()) stream.next(); + int toLine = stream.getLine(); + channel.setSourceText(stream.getSourceText(fromLine, toLine)); + return channel; + } - public void parseInit(DataTransferModel model) - throws ExpectedLeftCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongRHSExpression, - ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { - String leftBracket = stream.next(); - if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); - while (stream.hasNext() && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { - int fromLine = stream.getLine(); - ResourceHierarchy resourceHierarchy = parseResourceHierarchy(stream, model); + public void parseInit(DataTransferModel model) throws ExpectedLeftCurlyBracket, ExpectedAssignment, ExpectedRHSExpression, WrongRHSExpression, ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { + String leftBracket = stream.next(); + if (!leftBracket.equals(LEFT_CURLY_BRACKET)) throw new ExpectedLeftCurlyBracket(stream.getLine()); + while (stream.hasNext() && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { + int fromLine = stream.getLine(); + ResourceHierarchy resourceHierarchy = parseResourceHierarchy(stream, model); - if (!stream.hasNext()) throw new ExpectedAssignment(stream.getLine()); - String colon = stream.next(); - if (!colon.equals(COLON)) throw new ExpectedAssignment(stream.getLine()); - if (!stream.hasNext()) throw new ExpectedAssignment(stream.getLine()); - String equals = stream.next(); - if (!equals.equals(ASSIGNMENT)) throw new ExpectedAssignment(stream.getLine()); + if (!stream.hasNext()) throw new ExpectedAssignment(stream.getLine()); + String colon = stream.next(); + if (!colon.equals(COLON)) throw new ExpectedAssignment(stream.getLine()); + if (!stream.hasNext()) throw new ExpectedAssignment(stream.getLine()); + String equals = stream.next(); + if (!equals.equals(ASSIGNMENT)) throw new ExpectedAssignment(stream.getLine()); - int toLine = stream.getLine(); - Expression rightTerm = null; - if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); - rightTerm = parseTerm(stream, model); - if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); + int toLine = stream.getLine(); + Expression rightTerm = null; + if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); + rightTerm = parseTerm(stream, model); + if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); - resourceHierarchy.setInitialValue(rightTerm); - resourceHierarchy.setInitText(stream.getSourceText(fromLine, toLine)); - } - if (stream.hasNext()) stream.next(); - } + resourceHierarchy.setInitialValue(rightTerm); + resourceHierarchy.setInitText(stream.getSourceText(fromLine, toLine)); + } + if (stream.hasNext()) stream.next(); + } - public ChannelMember parseChannelMember(DataTransferModel model, final String inOrOutOrRef) - throws ExpectedRightBracket, ExpectedRightCurlyBracket, ExpectedStateTransition, ExpectedEquals, - ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, WrongPathExpression, WrongJsonExpression, ExpectedColon { - if (!stream.hasNext()) throw new ExpectedStateTransition(stream.getLine()); - StateTransitionTerm leftTerm = parseStateTransitionTerm(stream, model); - if (leftTerm == null || !(leftTerm instanceof Term)) throw new WrongLHSExpression(stream.getLine()); - Expression rightTerm = null; + public ChannelMember parseChannelMember(DataTransferModel model, final String inOrOutOrRef) throws ExpectedRightBracket, ExpectedRightCurlyBracket, ExpectedStateTransition, ExpectedEquals, ExpectedRHSExpression, WrongLHSExpression, WrongRHSExpression, WrongPathExpression, WrongJsonExpression, ExpectedColon { + if (!stream.hasNext()) throw new ExpectedStateTransition(stream.getLine()); + StateTransitionTerm leftTerm = parseStateTransitionTerm(stream, model); + if (leftTerm == null || !(leftTerm instanceof Term)) throw new WrongLHSExpression(stream.getLine()); + Expression rightTerm = null; - if (!inOrOutOrRef.equals(REF)) { - if (!stream.hasNext()) throw new ExpectedEquals(stream.getLine()); - String equals = stream.next(); - if (!equals.equals(EQUALS)) throw new ExpectedEquals(stream.getLine()); + if (!inOrOutOrRef.equals(REF)) { + if (!stream.hasNext()) throw new ExpectedEquals(stream.getLine()); + String equals = stream.next(); + if (!equals.equals(EQUALS)) throw new ExpectedEquals(stream.getLine()); - if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); - rightTerm = parseTerm(stream, model); - if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); - } + if (!stream.hasNext()) throw new ExpectedRHSExpression(stream.getLine()); + rightTerm = parseTerm(stream, model); + if (rightTerm == null) throw new WrongRHSExpression(stream.getLine()); + } - ResourcePath resourcePath = (ResourcePath) leftTerm.getSymbol(); - ChannelMember channelMember = new ChannelMember(resourcePath); - StateTransition stateTransition = new StateTransition(); - stateTransition.setCurStateExpression(((Term) leftTerm).getChild(0)); - stateTransition.setMessageExpression(((Term) leftTerm).getChild(1)); - if (!inOrOutOrRef.equals(REF)) stateTransition.setNextStateExpression(rightTerm); - channelMember.setStateTransition(stateTransition); - // for type definition - if (resourcePath.getResourceStateType() == null && ((Term) leftTerm).getChild(0) instanceof Variable) { - Variable stateVar = (Variable) ((Term) leftTerm).getChild(0); - if (stateVar.getType() != null) { - resourcePath.setResourceStateType(stateVar.getType()); - } - } - if (((Term) leftTerm).getChild(1) instanceof Term) { - Term messageTerm = (Term) ((Term) leftTerm).getChild(1); - if (messageTerm.getSymbol().getSignature() == null && messageTerm.getChildren().size() > 0) { - Type[] signature = new Type[messageTerm.getChildren().size() + 1]; - int i = 1; - for (Expression e: messageTerm.getChildren()) { - if (e instanceof Variable && ((Variable) e).getType() != null) { - signature[i] = ((Variable) e).getType(); - } - i++; - } - messageTerm.getSymbol().setSignature(signature); - } - } - return channelMember; - } + ResourcePath resourcePath = (ResourcePath) leftTerm.getSymbol(); + ChannelMember channelMember = new ChannelMember(resourcePath); + StateTransition stateTransition = new StateTransition(); + stateTransition.setCurStateExpression(((Term) leftTerm).getChild(0)); + stateTransition.setMessageExpression(((Term) leftTerm).getChild(1)); + if (!inOrOutOrRef.equals(REF)) stateTransition.setNextStateExpression(rightTerm); + channelMember.setStateTransition(stateTransition); + // for type definition + if (resourcePath.getResourceStateType() == null && ((Term) leftTerm).getChild(0) instanceof Variable) { + Variable stateVar = (Variable) ((Term) leftTerm).getChild(0); + if (stateVar.getType() != null) { + resourcePath.setResourceStateType(stateVar.getType()); + } + } + if (((Term) leftTerm).getChild(1) instanceof Term) { + Term messageTerm = (Term) ((Term) leftTerm).getChild(1); + if (messageTerm.getSymbol().getSignature() == null && messageTerm.getChildren().size() > 0) { + Type[] signature = new Type[messageTerm.getChildren().size() + 1]; + int i = 1; + for (Expression e : messageTerm.getChildren()) { + if (e instanceof Variable && ((Variable) e).getType() != null) { + signature[i] = ((Variable) e).getType(); + } + i++; + } + messageTerm.getSymbol().setSignature(signature); + } + } + return channelMember; + } - public Expression parseTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { - ArrayList expressions = new ArrayList<>(); - ArrayList operators = new ArrayList<>(); - String operator = null; - for (;;) { - String leftBracketOrMinusOrNeg = stream.next(); - if (leftBracketOrMinusOrNeg.equals(LEFT_BRACKET)) { - Expression exp = parseTerm(stream, model); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - expressions.add(exp); - } else if (leftBracketOrMinusOrNeg.equals(LEFT_CURLY_BRACKET)) { - Expression exp = parseJsonTerm(stream, model); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - expressions.add(exp); - } else if (leftBracketOrMinusOrNeg.equals(LEFT_SQUARE_BRACKET)) { - Expression exp = parseListTerm(stream, model); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_SQUARE_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - expressions.add(exp); - } else { - Symbol minusOrNeg = null; - String symbolName = null; - if (leftBracketOrMinusOrNeg.equals(MINUS)) { - minusOrNeg = DataTransferModel.minus; // not sub - symbolName = stream.next(); - } else if (leftBracketOrMinusOrNeg.equals(NEG)) { - minusOrNeg = DataTransferModel.neg; - symbolName = stream.next(); - } else { - symbolName = leftBracketOrMinusOrNeg; - } - Expression exp = null; - if (stream.checkNext() != null && stream.checkNext().equals(LEFT_BRACKET)) { - // a function symbol - Symbol symbol = model.getSymbol(symbolName); - if (symbol == null) { - symbol = new Symbol(symbolName); - model.addSymbol(symbol); - } - Term term = new Term(symbol); - int arity = 0; - do { - stream.next(); // LEFT_BRACKET or COMMA - if (stream.checkNext().equals(RIGHT_BRACKET)) break; - arity++; - Expression subTerm = parseTerm(stream, model); - term.addChild(subTerm, true); - if (!stream.hasNext()) throw new ExpectedRightBracket(stream.getLine()); - } while (stream.checkNext().equals(COMMA)); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - symbol.setArity(arity); - exp = term; - } else { - // constant or variable or json access - Symbol symbol = model.getSymbol(symbolName); - if (symbol != null && symbol.getArity() == 0) { - // a constant - exp = new Constant(symbol); - } else { - if (Character.isDigit(symbolName.charAt(0))) { - // maybe a numerical value - if (stream.checkNext() != null && stream.checkNext().equals(DOT)) { - // Because tokens are separated by a DOT. - stream.next(); - symbolName += DOT + stream.next(); // decimal fraction - } - Double d = Double.parseDouble(symbolName); - // a numerical value - if (symbolName.contains(DOT)) { - exp = new Constant(symbolName, DataTransferModel.typeDouble); - } else { - exp = new Constant(symbolName, DataTransferModel.typeInt); - } - } else if (symbolName.startsWith("\"") && symbolName.endsWith("\"")) { - // a string value - exp = new Constant(symbolName, DataTransferModel.typeString); - } else { - // a variable - exp = parseVariable(stream, model, symbolName); - } - } - } - if (minusOrNeg != null) { - Term minusOrNegTerm = new Term(minusOrNeg); - minusOrNegTerm.addChild(exp); - expressions.add(minusOrNegTerm); - } else { - expressions.add(exp); - } - } - operator = stream.checkNext(); - if (operator == null) { - break; - } else if (operator.equals(ADD)) { - operators.add(DataTransferModel.add); - stream.next(); - } else if (operator.equals(MUL)) { - operators.add(DataTransferModel.mul); - stream.next(); - } else if (operator.equals(SUB)) { - operators.add(DataTransferModel.sub); // not minus - stream.next(); - } else if (operator.equals(DIV)) { - operators.add(DataTransferModel.div); - stream.next(); - } else if (operator.equals(MOD)) { - operators.add(DataTransferModel.mod); - stream.next(); - } else if (operator.equals(EQ)) { - operators.add(DataTransferModel.eq); - stream.next(); - } else if (operator.equals(NEQ)) { - operators.add(DataTransferModel.neq); - stream.next(); - } else if (operator.equals(GT)) { - operators.add(DataTransferModel.gt); - stream.next(); - } else if (operator.equals(LT)) { - operators.add(DataTransferModel.lt); - stream.next(); - } else if (operator.equals(GE)) { - operators.add(DataTransferModel.ge); - stream.next(); - } else if (operator.equals(LE)) { - operators.add(DataTransferModel.le); - stream.next(); - } else if (operator.equals(AND)) { - operators.add(DataTransferModel.and); - stream.next(); - } else if (operator.equals(OR)) { - operators.add(DataTransferModel.or); - stream.next(); - } else if (operator.equals(DOT)) { - // json accessor - Expression exp = expressions.remove(0); - stream.next(); // DOT - if (stream.checkNext() == null) throw new WrongJsonExpression(stream.getLine()); - String literalOrLeftCurlyBracket = stream.next(); - Expression paramTerm = null; - if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { - // parameter - paramTerm = parseTerm(stream, model); - String rightCurlyBracket = stream.next(); - if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) throw new WrongJsonExpression(stream.getLine()); - } else { - // literal - paramTerm = new Constant(literalOrLeftCurlyBracket, DataTransferModel.typeString); - } - Type paramType = null; - if (paramTerm instanceof Variable) { - paramType = ((Variable) paramTerm).getType(); - } else if (paramTerm instanceof Term) { - paramType = ((Term) paramTerm).getType(); - } - Term term = null; - if (paramType != null && DataConstraintModel.typeInt.isAncestorOf(paramType)) { - term = new JsonAccessor(DataConstraintModel.dotParam); - } else { - term = new JsonAccessor(DataConstraintModel.dot); - } - term.addChild(exp); - term.addChild(paramTerm); - expressions.add(term); - operator = stream.checkNext(); - if (operator == null || !operator.equals(DOT)) break; - } else { - break; - } - } - if (expressions.size() == 1) { - // no arithmetic operators - return expressions.get(0); - } - ArrayList monomials = new ArrayList<>(); - ArrayList addSubs = new ArrayList<>(); - Expression first = expressions.get(0); - int i = 1; - Term rootTerm = null; - for (Symbol op: operators) { - Expression second = expressions.get(i); - if (op.getName().equals(MUL) || op.getName().equals(DIV) || op.getName().equals(MOD)) { - // higher priority than add and sub - Term term = new Term(op); - term.addChild(first); - term.addChild(second); - first = term; - } else if (op.getName().equals(EQ) || op.getName().equals(NEQ) || op.getName().equals(GT) || op.getName().equals(LT) - || op.getName().equals(GE) || op.getName().equals(LE) || op.getName().equals(AND) || op.getName().equals(OR)) { - // lower priority than add and sub - if (first != null) monomials.add(first); - Expression firstMonomial = monomials.get(0); - int j = 1; - for (Symbol op2: addSubs) { - Expression secondMonomial = monomials.get(j); - Term term = new Term(op2); - term.addChild(firstMonomial); - term.addChild(secondMonomial); - firstMonomial = term; - j++; - } - if (rootTerm == null) { - rootTerm = new Term(op); - rootTerm.addChild(firstMonomial); - } else { - rootTerm.addChild(firstMonomial); - firstMonomial = rootTerm; - rootTerm = new Term(op); - rootTerm.addChild(firstMonomial); - } - monomials.clear(); - addSubs.clear(); - first = second; - } else { - // add or sub ==> new monomial - monomials.add(first); - addSubs.add(op); - first = second; - } - i++; - } - if (first != null) monomials.add(first); - Expression firstMonomial = monomials.get(0); - i = 1; - for (Symbol op: addSubs) { - Expression secondMonomial = monomials.get(i); - Term term = new Term(op); - term.addChild(firstMonomial); - term.addChild(secondMonomial); - firstMonomial = term; - i++; - } - if (rootTerm == null) { - return firstMonomial; - } else { - rootTerm.addChild(firstMonomial); - return rootTerm; - } - } + public Expression parseTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { + ArrayList expressions = new ArrayList<>(); + ArrayList operators = new ArrayList<>(); + String operator = null; + for (; ; ) { + String leftBracketOrMinusOrNeg = stream.next(); + if (leftBracketOrMinusOrNeg.equals(LEFT_BRACKET)) { + Expression exp = parseTerm(stream, model); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); + } else if (leftBracketOrMinusOrNeg.equals(LEFT_CURLY_BRACKET)) { + Expression exp = parseJsonTerm(stream, model); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); + } else if (leftBracketOrMinusOrNeg.equals(LEFT_SQUARE_BRACKET)) { + Expression exp = parseListTerm(stream, model); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_SQUARE_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + expressions.add(exp); + } else { + Symbol minusOrNeg = null; + String symbolName = null; + if (leftBracketOrMinusOrNeg.equals(MINUS)) { + minusOrNeg = DataTransferModel.minus; // not sub + symbolName = stream.next(); + } else if (leftBracketOrMinusOrNeg.equals(NEG)) { + minusOrNeg = DataTransferModel.neg; + symbolName = stream.next(); + } else { + symbolName = leftBracketOrMinusOrNeg; + } + Expression exp = null; + if (stream.checkNext() != null && stream.checkNext().equals(LEFT_BRACKET)) { + // a function symbol + Symbol symbol = model.getSymbol(symbolName); + if (symbol == null) { + symbol = new Symbol(symbolName); + model.addSymbol(symbol); + } + Term term = new Term(symbol); + int arity = 0; + do { + stream.next(); // LEFT_BRACKET or COMMA + if (stream.checkNext().equals(RIGHT_BRACKET)) break; + arity++; + Expression subTerm = parseTerm(stream, model); + term.addChild(subTerm, true); + if (!stream.hasNext()) throw new ExpectedRightBracket(stream.getLine()); + } while (stream.checkNext().equals(COMMA)); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + symbol.setArity(arity); + exp = term; + } else { + // constant or variable or json access + Symbol symbol = model.getSymbol(symbolName); + if (symbol != null && symbol.getArity() == 0) { + // a constant + exp = new Constant(symbol); + } else { + if (Character.isDigit(symbolName.charAt(0))) { + // maybe a numerical value + if (stream.checkNext() != null && stream.checkNext().equals(DOT)) { + // Because tokens are separated by a DOT. + stream.next(); + symbolName += DOT + stream.next(); // decimal fraction + } + Double d = Double.parseDouble(symbolName); + // a numerical value + if (symbolName.contains(DOT)) { + exp = new Constant(symbolName, DataTransferModel.typeDouble); + } else { + exp = new Constant(symbolName, DataTransferModel.typeInt); + } + } else if (symbolName.startsWith("\"") && symbolName.endsWith("\"")) { + // a string value + exp = new Constant(symbolName, DataTransferModel.typeString); + } else { + // a variable + exp = parseVariable(stream, model, symbolName); + } + } + } + if (minusOrNeg != null) { + Term minusOrNegTerm = new Term(minusOrNeg); + minusOrNegTerm.addChild(exp); + expressions.add(minusOrNegTerm); + } else { + expressions.add(exp); + } + } + operator = stream.checkNext(); + if (operator == null) { + break; + } else if (operator.equals(ADD)) { + operators.add(DataTransferModel.add); + stream.next(); + } else if (operator.equals(MUL)) { + operators.add(DataTransferModel.mul); + stream.next(); + } else if (operator.equals(SUB)) { + operators.add(DataTransferModel.sub); // not minus + stream.next(); + } else if (operator.equals(DIV)) { + operators.add(DataTransferModel.div); + stream.next(); + } else if (operator.equals(MOD)) { + operators.add(DataTransferModel.mod); + stream.next(); + } else if (operator.equals(EQ)) { + operators.add(DataTransferModel.eq); + stream.next(); + } else if (operator.equals(NEQ)) { + operators.add(DataTransferModel.neq); + stream.next(); + } else if (operator.equals(GT)) { + operators.add(DataTransferModel.gt); + stream.next(); + } else if (operator.equals(LT)) { + operators.add(DataTransferModel.lt); + stream.next(); + } else if (operator.equals(GE)) { + operators.add(DataTransferModel.ge); + stream.next(); + } else if (operator.equals(LE)) { + operators.add(DataTransferModel.le); + stream.next(); + } else if (operator.equals(AND)) { + operators.add(DataTransferModel.and); + stream.next(); + } else if (operator.equals(OR)) { + operators.add(DataTransferModel.or); + stream.next(); + } else if (operator.equals(DOT)) { + // json accessor + Expression exp = expressions.remove(0); + stream.next(); // DOT + if (stream.checkNext() == null) throw new WrongJsonExpression(stream.getLine()); + String literalOrLeftCurlyBracket = stream.next(); + Expression paramTerm = null; + if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { + // parameter + paramTerm = parseTerm(stream, model); + String rightCurlyBracket = stream.next(); + if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) + throw new WrongJsonExpression(stream.getLine()); + } else { + // literal + paramTerm = new Constant(literalOrLeftCurlyBracket, DataTransferModel.typeString); + } + Type paramType = null; + if (paramTerm instanceof Variable) { + paramType = ((Variable) paramTerm).getType(); + } else if (paramTerm instanceof Term) { + paramType = ((Term) paramTerm).getType(); + } + Term term = null; + if (paramType != null && DataConstraintModel.typeInt.isAncestorOf(paramType)) { + term = new JsonAccessor(DataConstraintModel.dotParam); + } else { + term = new JsonAccessor(DataConstraintModel.dot); + } + term.addChild(exp); + term.addChild(paramTerm); + expressions.add(term); + operator = stream.checkNext(); + if (operator == null || !operator.equals(DOT)) break; + } else { + break; + } + } + if (expressions.size() == 1) { + // no arithmetic operators + return expressions.get(0); + } + ArrayList monomials = new ArrayList<>(); + ArrayList addSubs = new ArrayList<>(); + Expression first = expressions.get(0); + int i = 1; + Term rootTerm = null; + for (Symbol op : operators) { + Expression second = expressions.get(i); + if (op.getName().equals(MUL) || op.getName().equals(DIV) || op.getName().equals(MOD)) { + // higher priority than add and sub + Term term = new Term(op); + term.addChild(first); + term.addChild(second); + first = term; + } else if (op.getName().equals(EQ) || op.getName().equals(NEQ) || op.getName().equals(GT) || op.getName().equals(LT) || op.getName().equals(GE) || op.getName().equals(LE) || op.getName().equals(AND) || op.getName().equals(OR)) { + // lower priority than add and sub + if (first != null) monomials.add(first); + Expression firstMonomial = monomials.get(0); + int j = 1; + for (Symbol op2 : addSubs) { + Expression secondMonomial = monomials.get(j); + Term term = new Term(op2); + term.addChild(firstMonomial); + term.addChild(secondMonomial); + firstMonomial = term; + j++; + } + if (rootTerm == null) { + rootTerm = new Term(op); + rootTerm.addChild(firstMonomial); + } else { + rootTerm.addChild(firstMonomial); + firstMonomial = rootTerm; + rootTerm = new Term(op); + rootTerm.addChild(firstMonomial); + } + monomials.clear(); + addSubs.clear(); + first = second; + } else { + // add or sub ==> new monomial + monomials.add(first); + addSubs.add(op); + first = second; + } + i++; + } + if (first != null) monomials.add(first); + Expression firstMonomial = monomials.get(0); + i = 1; + for (Symbol op : addSubs) { + Expression secondMonomial = monomials.get(i); + Term term = new Term(op); + term.addChild(firstMonomial); + term.addChild(secondMonomial); + firstMonomial = term; + i++; + } + if (rootTerm == null) { + return firstMonomial; + } else { + rootTerm.addChild(firstMonomial); + return rootTerm; + } + } // private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { // Term jsonTerm = new Constant(DataConstraintModel.nil); @@ -549,329 +508,256 @@ // } // return jsonTerm; // } - - private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { - JsonTerm jsonTerm = new JsonTerm(); - while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { - String key = stream.next(); - if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) throw new ExpectedColon(stream.getLine()); - String colon = stream.next(); - Expression value = parseTerm(stream, model); - jsonTerm.addMember(key, value); - if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; - String comma = stream.next(); - } - return jsonTerm; - } - private Expression parseListTerm(TokenStream stream2, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { - Term listTerm = new Constant(DataConstraintModel.nil); - listTerm.setType(DataConstraintModel.typeList); - while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_SQUARE_BRACKET)) { - Expression element = parseTerm(stream, model); - Term nextTerm = new Term(DataConstraintModel.cons); - nextTerm.addChild(element); - nextTerm.addChild(listTerm); - listTerm = nextTerm; - if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; - String comma = stream.next(); - } - return listTerm; - } + private Expression parseJsonTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { + JsonTerm jsonTerm = new JsonTerm(); + while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_CURLY_BRACKET)) { + String key = stream.next(); + if (stream.checkNext() == null || !stream.checkNext().equals(COLON)) + throw new ExpectedColon(stream.getLine()); + String colon = stream.next(); + Expression value = parseTerm(stream, model); + jsonTerm.addMember(key, value); + if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; + String comma = stream.next(); + } + return jsonTerm; + } - private Variable parseVariable(TokenStream stream, DataTransferModel model, String symbolName) { - Variable var; - if (stream.checkNext() != null && stream.checkNext().equals(COLON)) { - // when a type is specified. - stream.next(); - String typeName = stream.next(); - Type type = model.getType(typeName); - if (type == null) { - type = new Type(typeName, typeName); - } - var = new Variable(symbolName, type); - } else { - var = new Variable(symbolName); - } - return var; - } - - public StateTransitionTerm parseStateTransitionTerm(TokenStream stream, DataTransferModel model) - throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { - ResourcePath resourcePath = parseResourcePath(stream, model); - StateTransitionTerm term = new StateTransitionTerm(resourcePath); - int arity = 0; - do { - stream.next(); // LEFT_BRACKET or COMMA - arity++; - Expression subTerm = parseTerm(stream, model); - term.addChild(subTerm, true); - if (!stream.hasNext()) throw new ExpectedRightBracket(stream.getLine()); - } while (stream.checkNext().equals(COMMA)); - String rightBracket = stream.next(); - if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); - resourcePath.setArity(arity); - return term; - } - - public ResourceHierarchy parseResourceHierarchy(TokenStream stream, DataTransferModel model) - throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression { - ResourceHierarchy hierarchy = null; - do { - String literalOrLeftCurlyBracket = stream.next(); - if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { - // No path parameter - String rightCurlyBracket = stream.next(); - if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightCurlyBracket(stream.getLine()); - hierarchy = new ResourceHierarchy(hierarchy, 1); - } else { - // Path literal - hierarchy = new ResourceHierarchy(hierarchy, literalOrLeftCurlyBracket); - } - if (!stream.hasNext()) throw new WrongPathExpression(stream.getLine()); - if (stream.checkNext().equals(LEFT_BRACKET)) break; - if (stream.checkNext().equals(COLON)) break; - } while (stream.next().equals(DOT)); - hierarchy = model.getOrPutResourceHierarchy(hierarchy); - return hierarchy; - } - - public ResourcePath parseResourcePath(TokenStream stream, DataTransferModel model) - throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { - ResourcePath path = null; - do { - String literalOrLeftCurlyBracket = stream.next(); - if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { - // Path parameter - Expression paramTerm = parseTerm(stream, model); - String rightCurlyBracket = stream.next(); - if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) throw new ExpectedRightCurlyBracket(stream.getLine()); - path = new ResourcePath(path, paramTerm); - } else { - // Path literal - if (path == null) { - path = new ResourcePath(literalOrLeftCurlyBracket); - } else { - path = new ResourcePath(path, literalOrLeftCurlyBracket); - } - } - if (!stream.hasNext()) throw new WrongPathExpression(stream.getLine()); - if (stream.checkNext().equals(LEFT_BRACKET)) break; - } while (stream.next().equals(DOT)); - model.addResourcePath(path); - return path; - } + private Expression parseListTerm(TokenStream stream2, DataTransferModel model) throws ExpectedRightBracket, WrongJsonExpression, ExpectedColon { + Term listTerm = new Constant(DataConstraintModel.nil); + listTerm.setType(DataConstraintModel.typeList); + while (stream.checkNext() != null && !stream.checkNext().equals(RIGHT_SQUARE_BRACKET)) { + Expression element = parseTerm(stream, model); + Term nextTerm = new Term(DataConstraintModel.cons); + nextTerm.addChild(element); + nextTerm.addChild(listTerm); + listTerm = nextTerm; + if (stream.checkNext() == null || !stream.checkNext().equals(COMMA)) break; + String comma = stream.next(); + } + return listTerm; + } - protected Boolean doesMatchToKeyword(final String token, final String specificTokenName) { - if(token == null) return false; - if(specificTokenName == null) return false; - return token.equals(specificTokenName); - } + private Variable parseVariable(TokenStream stream, DataTransferModel model, String symbolName) { + Variable var; + if (stream.checkNext() != null && stream.checkNext().equals(COLON)) { + // when a type is specified. + stream.next(); + String typeName = stream.next(); + Type type = model.getType(typeName); + if (type == null) { + type = new Type(typeName, typeName); + } + var = new Variable(symbolName, type); + } else { + var = new Variable(symbolName); + } + return var; + } - public static class TokenStream { - private ArrayList> tokens = new ArrayList<>(); - private ArrayList lines = new ArrayList<>(); - private int line = 0; - private int n = 0; + public StateTransitionTerm parseStateTransitionTerm(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { + ResourcePath resourcePath = parseResourcePath(stream, model); + StateTransitionTerm term = new StateTransitionTerm(resourcePath); + int arity = 0; + do { + stream.next(); // LEFT_BRACKET or COMMA + arity++; + Expression subTerm = parseTerm(stream, model); + term.addChild(subTerm, true); + if (!stream.hasNext()) throw new ExpectedRightBracket(stream.getLine()); + } while (stream.checkNext().equals(COMMA)); + String rightBracket = stream.next(); + if (!rightBracket.equals(RIGHT_BRACKET)) throw new ExpectedRightBracket(stream.getLine()); + resourcePath.setArity(arity); + return term; + } - public TokenStream() { - line = 0; - n = 0; - } + public ResourceHierarchy parseResourceHierarchy(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression { + ResourceHierarchy hierarchy = null; + do { + String literalOrLeftCurlyBracket = stream.next(); + if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { + // No path parameter + String rightCurlyBracket = stream.next(); + if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) + throw new ExpectedRightCurlyBracket(stream.getLine()); + hierarchy = new ResourceHierarchy(hierarchy, 1); + } else { + // Path literal + hierarchy = new ResourceHierarchy(hierarchy, literalOrLeftCurlyBracket); + } + if (!stream.hasNext()) throw new WrongPathExpression(stream.getLine()); + if (stream.checkNext().equals(LEFT_BRACKET)) break; + if (stream.checkNext().equals(COLON)) break; + } while (stream.next().equals(DOT)); + hierarchy = model.getOrPutResourceHierarchy(hierarchy); + return hierarchy; + } - public void addLine(String line) { - lines.add(line); - line = line.trim(); - tokens.add( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - splitBy( - line.split("[ \t]"), - ADD, - ADD_REGX), - MUL, - MUL_REGX), - SUB, - SUB_REGX), - DIV, - DIV_REGX), - MOD, - MOD), - EQ, - EQ), - NEQ, - NEQ), - GE, - GE), - LE, - LE), - GT, - GT), - LT, - LT), - AND, - AND), - OR, - OR_REGX), - NEG, - NEG), - DOT, - DOT_REGX), - COMMA, - COMMA), - COLON, - COLON), - LEFT_BRACKET, - LEFT_BRACKET_REGX), - RIGHT_BRACKET, - RIGHT_BRACKET_REGX), - EQUALS, - EQUALS), - LEFT_CURLY_BRACKET, - LEFT_CURLY_BRACKET_REGX), - RIGHT_CURLY_BRACKET, - RIGHT_CURLY_BRACKET_REGX), - LEFT_SQUARE_BRACKET, - LEFT_SQUARE_BRACKET_REGX), - RIGHT_SQUARE_BRACKET, - RIGHT_SQUARE_BRACKET_REGX)); - } - - private ArrayList splitBy(String[] tokens, final String delimiter, final String delimiterRegx) { - ArrayList newTokens = new ArrayList<>(); - for (String token: tokens) { - newTokens.add(new Token(token)); - } - return splitBy(newTokens, delimiter, delimiterRegx); - } + public ResourcePath parseResourcePath(TokenStream stream, DataTransferModel model) throws ExpectedRightBracket, ExpectedRightCurlyBracket, WrongPathExpression, WrongJsonExpression, ExpectedColon { + ResourcePath path = null; + do { + String literalOrLeftCurlyBracket = stream.next(); + if (literalOrLeftCurlyBracket.equals(LEFT_CURLY_BRACKET)) { + // Path parameter + Expression paramTerm = parseTerm(stream, model); + String rightCurlyBracket = stream.next(); + if (rightCurlyBracket == null || !rightCurlyBracket.equals(RIGHT_CURLY_BRACKET)) + throw new ExpectedRightCurlyBracket(stream.getLine()); + path = new ResourcePath(path, paramTerm); + } else { + // Path literal + if (path == null) { + path = new ResourcePath(literalOrLeftCurlyBracket); + } else { + path = new ResourcePath(path, literalOrLeftCurlyBracket); + } + } + if (!stream.hasNext()) throw new WrongPathExpression(stream.getLine()); + if (stream.checkNext().equals(LEFT_BRACKET)) break; + } while (stream.next().equals(DOT)); + model.addResourcePath(path); + return path; + } - private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { - ArrayList newTokens = new ArrayList<>(); - for (Token token: tokens) { - if (token.isAtomic()) { - newTokens.add(token); - } else { - String[] splitTokens = token.split(delimiterRegx); - boolean fFirstToken = true; - for (String t: splitTokens) { - if (!fFirstToken) { - newTokens.add(new Token(delimiter, true)); - } - if (t.length() > 0) { - newTokens.add(new Token(t)); - } - fFirstToken = false; - } - while (token.endsWith(delimiter)) { - newTokens.add(new Token(delimiter, true)); - token = token.substring(0, token.length() - 1); - } - } - } - return newTokens; - } + protected Boolean doesMatchToKeyword(final String token, final String specificTokenName) { + if (token == null) return false; + if (specificTokenName == null) return false; + return token.equals(specificTokenName); + } - public String next() { - if (line >= tokens.size()) return null; - while (n >= tokens.get(line).size()) { - line++; - n = 0; - if (line >= tokens.size()) return null; - } - String token = tokens.get(line).get(n).getTokenStr(); - n++; - return token; - } + public static class TokenStream { + private ArrayList> tokens = new ArrayList<>(); + private ArrayList lines = new ArrayList<>(); + private int line = 0; + private int n = 0; - public String checkNext() { - if (line >= tokens.size()) return null; - while (n >= tokens.get(line).size()) { - line++; - n = 0; - if (line >= tokens.size()) return null; - } - return tokens.get(line).get(n).getTokenStr(); - } + public TokenStream() { + line = 0; + n = 0; + } - public boolean hasNext() { - if (line >= tokens.size()) return false; - while (n >= tokens.get(line).size()) { - line++; - n = 0; - if (line >= tokens.size()) return false; - } - return true; - } + public void addLine(String line) { + lines.add(line); + line = line.trim(); + tokens.add(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(splitBy(line.split("[ \t]"), ADD, ADD_REGX), MUL, MUL_REGX), SUB, SUB_REGX), DIV, DIV_REGX), MOD, MOD), EQ, EQ), NEQ, NEQ), GE, GE), LE, LE), GT, GT), LT, LT), AND, AND), OR, OR_REGX), NEG, NEG), DOT, DOT_REGX), COMMA, COMMA), COLON, COLON), LEFT_BRACKET, LEFT_BRACKET_REGX), RIGHT_BRACKET, RIGHT_BRACKET_REGX), EQUALS, EQUALS), LEFT_CURLY_BRACKET, LEFT_CURLY_BRACKET_REGX), RIGHT_CURLY_BRACKET, RIGHT_CURLY_BRACKET_REGX), LEFT_SQUARE_BRACKET, LEFT_SQUARE_BRACKET_REGX), RIGHT_SQUARE_BRACKET, RIGHT_SQUARE_BRACKET_REGX)); + } - public int getLine() { - return line; - } + private ArrayList splitBy(String[] tokens, final String delimiter, final String delimiterRegx) { + ArrayList newTokens = new ArrayList<>(); + for (String token : tokens) { + newTokens.add(new Token(token)); + } + return splitBy(newTokens, delimiter, delimiterRegx); + } - public String getSourceText(int from, int to) { - String text = ""; - for (int l = from; l <= to; l++) { - text += lines.get(l) + "\n"; - } - return text; - } - } - - public static class Token { - String token; - boolean isAtomic = false; - - public Token(String token) { - this.token = token; - } + private ArrayList splitBy(final List tokens, final String delimiter, final String delimiterRegx) { + ArrayList newTokens = new ArrayList<>(); + for (Token token : tokens) { + if (token.isAtomic()) { + newTokens.add(token); + } else { + String[] splitTokens = token.split(delimiterRegx); + boolean fFirstToken = true; + for (String t : splitTokens) { + if (!fFirstToken) { + newTokens.add(new Token(delimiter, true)); + } + if (t.length() > 0) { + newTokens.add(new Token(t)); + } + fFirstToken = false; + } + while (token.endsWith(delimiter)) { + newTokens.add(new Token(delimiter, true)); + token = token.substring(0, token.length() - 1); + } + } + } + return newTokens; + } - public Token(String token, boolean isAtomic) { - this.token = token; - this.isAtomic = isAtomic; - } - - public String getTokenStr() { - return token; - } - - public boolean isAtomic() { - return isAtomic; - } - - public String[] split(String delimiterRegx) { - return token.split(delimiterRegx); - } + public String next() { + if (line >= tokens.size()) return null; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return null; + } + String token = tokens.get(line).get(n).getTokenStr(); + n++; + return token; + } - public boolean endsWith(String delimiter) { - return token.endsWith(delimiter); - } + public String checkNext() { + if (line >= tokens.size()) return null; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return null; + } + return tokens.get(line).get(n).getTokenStr(); + } - public int length() { - return token.length(); - } + public boolean hasNext() { + if (line >= tokens.size()) return false; + while (n >= tokens.get(line).size()) { + line++; + n = 0; + if (line >= tokens.size()) return false; + } + return true; + } - public Token substring(int beginIdx, int endIdx) { - return new Token(token.substring(beginIdx, endIdx)); - } - } + public int getLine() { + return line; + } + + public String getSourceText(int from, int to) { + String text = ""; + for (int l = from; l <= to; l++) { + text += lines.get(l) + "\n"; + } + return text; + } + } + + public static class Token { + String token; + boolean isAtomic = false; + + public Token(String token) { + this.token = token; + } + + public Token(String token, boolean isAtomic) { + this.token = token; + this.isAtomic = isAtomic; + } + + public String getTokenStr() { + return token; + } + + public boolean isAtomic() { + return isAtomic; + } + + public String[] split(String delimiterRegx) { + return token.split(delimiterRegx); + } + + public boolean endsWith(String delimiter) { + return token.endsWith(delimiter); + } + + public int length() { + return token.length(); + } + + public Token substring(int beginIdx, int endIdx) { + return new Token(token.substring(beginIdx, endIdx)); + } + } }