diff --git a/build.gradle b/build.gradle index f1f3b408f121f388615eca5d85cd3f128128f17c..6cc84133b33e0335daf810d71955697360cfd8d3 100644 --- a/build.gradle +++ b/build.gradle @@ -37,10 +37,10 @@ subprojects { } dependencies { - compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.2' - compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2' - testCompile group: 'junit', name: 'junit', version: '4.12' - testCompile group: 'org.hamcrest', name: 'hamcrest-junit', version: '2.0.0.0' + implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.2' + implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2' + testImplementation group: 'junit', name: 'junit', version: '4.12' + testImplementation group: 'org.hamcrest', name: 'hamcrest-junit', version: '2.0.0.0' } } diff --git a/statemachine/DrAST.cfg b/statemachine/DrAST.cfg index c229f19b6e4a7ae45494a802615a084bd488a49c..a5e75e925199099f743ed7cea31321a0f60d70d4 100644 --- a/statemachine/DrAST.cfg +++ b/statemachine/DrAST.cfg @@ -1,4 +1,16 @@ +#DrAST settings file. +#Mon Nov 18 17:23:41 CET 2019 +normalEdgeWidth=1.0 +showEdges=true +refEdgeWidth=2.0 +NTA-depth=1 +NTA-cached=1 dynamic-values=0 +prevJar=build/libs/statemachine-0.1.jar +dashedVertexEdgeWidth=0.2 NTA-computed=0 -NTA-cached=1 -NTA-depth=1 +normalVertexEdgeWidth=1.0 +nodeThreshold=1000 +showNodes=true +curvedEdges=true +dashedEdgeWidth=0.2 diff --git a/statemachine/build.gradle b/statemachine/build.gradle index 35c8c24b902857777be1f34f0a3b8306352a5291..022baba06ecc05ab5fb30f0896959dda4e67b8b8 100644 --- a/statemachine/build.gradle +++ b/statemachine/build.gradle @@ -1,23 +1,46 @@ +group 'de.tudresden.inf.st' +version '2.0-SNAPSHOT' + +apply plugin: 'java' apply plugin: 'jastadd' apply plugin: 'application' -apply plugin: 'jacoco' -apply plugin: 'idea' -apply plugin: 'distribution' +apply plugin: "idea" + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +idea { + module { + generatedSourceDirs += file('src/gen/java') + } +} + +configurations { + ragdoc +} + +sourceSets { + main { + java.srcDir "src/gen/java" + } +} + +task cleanRagdoc(type: Delete) { + group = 'documentation' + new File(docsDir, 'ragdoc').deleteDir() +} dependencies { implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}" implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' - jastadd2 "org.jastadd:jastadd:2.3.4" -// ragdoc project(":ragdoc-builder") implementation files('../libs/DrAST-1.2.2.jar') -} + implementation fileTree(dir: "${System.properties['java.home']}", include: '**/jfxrt.jar') -buildscript { - repositories.mavenLocal() - repositories.mavenCentral() - dependencies { - classpath group: 'org.jastadd', name: 'jastaddgradle', version: '1.13.3' - } + jastadd2 "org.jastadd:jastadd:2.3.4" + ragdoc files('../libs/rd-builder.jar') } run { @@ -28,10 +51,20 @@ run { } } -test { - testLogging { - events "passed", "skipped", "failed" - exceptionFormat "full" +buildscript { + repositories.mavenLocal() + repositories.mavenCentral() + dependencies { + classpath group: 'org.jastadd', name: 'jastaddgradle', version: '1.13.3' + } +} + +jar { + manifest { + attributes( + 'Class-Path': configurations.compile.collect { it.getName() }.join(' '), + 'Main-Class': 'de.tudresden.inf.st.statemachine.Main' + ) } } @@ -39,7 +72,7 @@ task DrAST(type: JavaExec, dependsOn:jar) { group = "verification" description = 'run the DrAST visual debugger tool' classpath = sourceSets.test.runtimeClasspath - main = 'de.tudresden.inf.st.statemachine.Main' + main = 'de.tudresden.inf.st.statemachine.DrAstRunner' } String[] drastArguments = ['../libs/DrAST-1.2.2.jar'] @@ -50,26 +83,26 @@ task DrASTjar(type: JavaExec, dependsOn:jar) { args drastArguments } -jacocoTestReport { - reports { - xml.enabled true - html.enabled false - } -} - def relastFiles = fileTree('src/main/jastadd/') { include '**/*.relast' }.toList().toArray() String[] relastArguments = [ "../libs/relast.jar", - "--grammarName=./src/main/jastadd/StatemachineGen", + "--grammarName=./src/gen/jastadd/StatemachineGen", "--useJastAddNames", "--listClass=ArrayList", "--jastAddList=JastAddList", + "--resolverHelper", "--file" ] task preprocess(type: JavaExec) { group = 'Build' main = "-jar" + + doFirst { + delete "src/gen/jastadd" + mkdir "src/gen/jastadd" + } + args relastArguments + relastFiles inputs.files relastFiles @@ -78,49 +111,66 @@ task preprocess(type: JavaExec) { jastadd { configureModuleBuild() - modules "jastadd_modules" - module = "statemachine" + modules { + module("statemachine") { + + java { + basedir "src/" + include "main/**/*.java" + include "gen/**/*.java" + } + + jastadd { + basedir "src/" + include "main/jastadd/**/*.ast" + include "main/jastadd/**/*.jadd" + include "main/jastadd/**/*.jrag" + include "gen/jastadd/**/*.ast" + include "gen/jastadd/**/*.jadd" + include "gen/jastadd/**/*.jrag" + } + + scanner { + include "src/main/jastadd/StateMachineScanner.flex" + } + + parser { + include "src/main/jastadd/StateMachineParser.parser" + } + } + } - extraJastAddOptions = ['--List=JastAddList'] + cleanGen.doFirst { + delete "src/gen/java/de" + delete "src/gen-res/BuildInfo.properties" + } + + module = "statemachine" astPackage = 'de.tudresden.inf.st.statemachine.jastadd.model' + + parser.name = 'StateMachineParser' + genDir = 'src/gen/java' buildInfoDir = 'src/gen-res' - parser.name = 'StatemachineParser' scanner.genDir = "src/gen/java/de/tudresden/inf/st/statemachine/jastadd/scanner" parser.genDir = "src/gen/java/de/tudresden/inf/st/statemachine/jastadd/parser" -} - -idea.module.generatedSourceDirs += file('src/gen/java') - -sourceSets.main { - java { - srcDir 'src/gen/java' - } -} -javadoc { - // this is only run to get the index file etc. - failOnError = false + jastaddOptions = ['--List=JastAddList'] } String[] arguments = ["../libs/rd-builder.jar", "-d", "doc/"] def allSrcFiles = sourceSets.main.allSource.findAll { it.name.endsWith('java') }.toArray() def ragdocViewSrcData = '../ragdoc-view/src/data/' -task ragdoc(type: JavaExec, dependsOn: assemble, overwrite: true) { - group = 'documentation' - description = 'Create ragdoc json documentation files' - main = "-jar" - args arguments + allSrcFiles -} - -task cleanRagdoc(type: Delete) { - group = 'documentation' - delete fileTree(ragdocViewSrcData + '/*') -} +//task ragdoc(type: JavaExec, dependsOn: assemble, overwrite: true) { +// group = 'documentation' +// description = 'Create ragdoc json documentation files' +// main = "-jar" +// args arguments + allSrcFiles +//} task copyRagdoc(type: Copy, dependsOn: cleanRagdoc) { group = 'documentation' @@ -131,7 +181,7 @@ task copyRagdoc(type: Copy, dependsOn: cleanRagdoc) { } generateAst.dependsOn preprocess -generateAst.inputs.files file("./src/main/jastadd/StatemachineGen.ast"), file("./src/main/jastadd/StatemachineGen.jadd") +//generateAst.inputs.files file("./src/main/jastadd/StatemachineGen.ast"), file("./src/main/jastadd/StatemachineGen.jadd") //compileJava.dependsOn jastadd // //// always run jastadd diff --git a/statemachine/jastadd_modules b/statemachine/jastadd_modules deleted file mode 100644 index 0a4da9924785d8df90a13ebeb8f00070dcd31298..0000000000000000000000000000000000000000 --- a/statemachine/jastadd_modules +++ /dev/null @@ -1,24 +0,0 @@ -module("statemachine") { - - java { - basedir "src/" - include "main/**/*.java" - include "gen/**/*.java" - } - - jastadd { - basedir "src/main/jastadd/" - include "**/*.ast" - include "**/*.jadd" - include "**/*.jrag" - } - -// scanner { -// include "src/main/jastadd/statemachine.flex" -// } -// -// parser { -// include "src/main/jastadd/statemachine.parser" -// } - -} diff --git a/statemachine/src/main/jastadd/Analysis.jrag b/statemachine/src/main/jastadd/Analysis.jrag index 118dd2373e1fb883c829cb8867cb3d898f574e07..427e0b137e9a55d91e59852c7e07a3acb4201e42 100644 --- a/statemachine/src/main/jastadd/Analysis.jrag +++ b/statemachine/src/main/jastadd/Analysis.jrag @@ -1,3 +1,32 @@ aspect Analysis { + syn Map<String, State> StateMachine.stateMap() { + Map<String, State> map = new HashMap<>(); + for (State s : states()) { + map.put(s.getLabel(), s); + } + return map; + } + syn Map<String, Transition> StateMachine.transitionMap() { + Map<String, Transition> map = new HashMap<>(); + for (Transition t : transitions()) { + map.put(t.getLabel(), t); + } + return map; + } + + syn StateMachine ASTNode.root(); + eq StateMachine.root() = this; + eq ASTNode.root() = getParent().root(); + + refine RefResolverStubs eq ASTNode.globallyResolveStateByToken(String id) { + return root().stateMap().get(id); + } + + refine RefResolverStubs eq ASTNode.globallyResolveTransitionByToken(String id) { + return root().transitionMap().get(id); + } + + syn boolean State.isInitial() = root().getInitial().equals(this); + syn boolean State.isFinal() = root().getFinalList().contains(this); } diff --git a/statemachine/src/main/jastadd/Printing.jrag b/statemachine/src/main/jastadd/Printing.jrag new file mode 100644 index 0000000000000000000000000000000000000000..5f511fcb7e6374bd7e578185f97a0081322729f6 --- /dev/null +++ b/statemachine/src/main/jastadd/Printing.jrag @@ -0,0 +1,12 @@ +aspect Printing { + syn String StateMachine.prettyPrint() { + StringBuilder sb = new StringBuilder(); + states().forEach(s -> sb.append(s.prettyPrint())); + transitions().forEach(t -> sb.append(t.prettyPrint())); + return sb.toString(); + } + + syn String Element.prettyPrint(); + eq State.prettyPrint() = (isInitial() ? "initial " : "") + (isFinal() ? "final " : "") + "state " + getLabel() + ";\n"; + eq Transition.prettyPrint() = "trans " + getFrom().getLabel() + " -> " + getTo().getLabel() + " : " + getLabel() + ";\n"; +} diff --git a/statemachine/src/main/jastadd/StateMachineParser.parser b/statemachine/src/main/jastadd/StateMachineParser.parser new file mode 100644 index 0000000000000000000000000000000000000000..197392ec59f05154f50b716da6a4bd92981f1902 --- /dev/null +++ b/statemachine/src/main/jastadd/StateMachineParser.parser @@ -0,0 +1,55 @@ +%header {: +// this code is inlined before the generated parser +package de.tudresden.inf.st.statemachine.jastadd.parser; +import de.tudresden.inf.st.statemachine.jastadd.model.*; +import java.util.*; +:}; + +%embed {: + // this code is inlined in the generated parser class + State initial; + List<State> finals = new ArrayList<>(); +:}; + +%goal goal; + +// Productions with semantic actions building the JastAdd AST + +statemachine goal = + element_list + {: + StateMachine result = new StateMachine(element_list); + result.setInitial(initial); + finals.forEach( result::addFinal ); + return result; + :} + ; + +JastAddList element_list = + element {: return new JastAddList().add(element); :} + | element_list element {: return element_list.add(element); :} + ; + +Element element = + INITIAL state_body.sb SEMI {: initial = sb; return sb; :} + | FINAL state_body.sb SEMI {: finals.add(sb); return sb; :} + | INITIAL FINAL state_body.sb SEMI {: initial = sb; finals.add(sb); return sb; :} + | state_body.sb SEMI {: return sb; :} + | TRANS NAME.from ARROW NAME.to COLON NAME.label SEMI + {: + Transition result = new Transition(); + result.setLabel(label); + result.setFrom(State.createRef(from)); + result.setTo(State.createRef(to)); + return result; + :} + ; + +State state_body = + STATE NAME.name + {: + State result = new State(); + result.setLabel(name); + return result; + :} + ; diff --git a/statemachine/src/main/jastadd/StateMachineScanner.flex b/statemachine/src/main/jastadd/StateMachineScanner.flex new file mode 100644 index 0000000000000000000000000000000000000000..ad86af4783a0ca7ba0a425bf33204226c493139d --- /dev/null +++ b/statemachine/src/main/jastadd/StateMachineScanner.flex @@ -0,0 +1,45 @@ +package de.tudresden.inf.st.statemachine.jastadd.scanner; + +import de.tudresden.inf.st.statemachine.jastadd.parser.StateMachineParser.Terminals; // The terminals are implicitly defined in the parser +%% + +// define the signature for the generated scanner +%public +%final +%class StateMachineScanner +%extends beaver.Scanner + +// the interface between the scanner and the parser is the nextToken() method +%type beaver.Symbol +%function nextToken +%yylexthrow beaver.Scanner.Exception + +// store line and column information in the tokens +%line +%column + +// this code will be inlined in the body of the generated scanner class +%{ + private beaver.Symbol sym(short id) { + return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext()); + } +%} + +WhiteSpace = [ ] | \t | \f | \n | \r | \r\n +Identifier = [:jletter:][:jletterdigit:]* + +%% + +// discard whitespace information +{WhiteSpace} { } + +// token definitions +"initial" { return sym(Terminals.INITIAL); } +"final" { return sym(Terminals.FINAL); } +"state" { return sym(Terminals.STATE); } +"trans" { return sym(Terminals.TRANS); } +{Identifier} { return sym(Terminals.NAME); } +";" { return sym(Terminals.SEMI); } +":" { return sym(Terminals.COLON); } +"->" { return sym(Terminals.ARROW); } +<<EOF>> { return sym(Terminals.EOF); } diff --git a/statemachine/src/main/jastadd/StatemachineGen.ast b/statemachine/src/main/jastadd/StatemachineGen.ast deleted file mode 100644 index 52c50cf0dec245e10ba8ba6cad8c1c75a0bcbb3b..0000000000000000000000000000000000000000 --- a/statemachine/src/main/jastadd/StatemachineGen.ast +++ /dev/null @@ -1,4 +0,0 @@ -StateMachine ::= Element* <_impl_Final:ArrayList<State>> <_impl_Initial:State>; -abstract Element ::= <Label:String>; -State : Element ::= <_impl_Incoming:ArrayList<Transition>> <_impl_Outgoing:ArrayList<Transition>>; -Transition : Element ::= <_impl_From:State> <_impl_To:State>; diff --git a/statemachine/src/main/jastadd/StatemachineGen.jadd b/statemachine/src/main/jastadd/StatemachineGen.jadd deleted file mode 100644 index 045f903487777fb18511e8cc641bfed7298f3926..0000000000000000000000000000000000000000 --- a/statemachine/src/main/jastadd/StatemachineGen.jadd +++ /dev/null @@ -1,276 +0,0 @@ -import java.util.ArrayList; -import java.util.Collections; -import java.time.Instant; -import java.time.Period; -aspect RelAstAPI { - class ASTNodeAnnotation { - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) - @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) - @java.lang.annotation.Documented - public @interface RelationDoc { - String roleName(); - String targetType(); - } - } - public StateMachine.StateMachine(JastAddList<Element> Element) { - setElementList(Element); - } - public State.State(String Label) { - setLabel(Label); - } - public Transition.Transition(String Label) { - setLabel(Label); - } - // rel Transition.From <-> State.Outgoing* - /** - * @relation From - */ - public State Transition.getFrom() { - return get_impl_From(); - } - public Transition Transition.setFrom(State o) { - assertNotNull(o); - if (tokenState__impl_From != null) { - ArrayList<Transition> list2 = tokenState__impl_From.tokenArrayList_Transition___impl_Outgoing; - list2.remove(this); - tokenState__impl_From.set_impl_Outgoing(list2); - } - set_impl_From(o); - ArrayList<Transition> list = o.tokenArrayList_Transition___impl_Outgoing; - if (list == null) { - list = new ArrayList<>(); - } - list.add(this); - o.set_impl_Outgoing(list); - return this; - } - /** - * @relation Outgoing - */ - public java.util.List<Transition> State.getOutgoings() { - return getOutgoingList(); - } - public java.util.List<Transition> State.getOutgoingList() { - ArrayList<Transition> l = get_impl_Outgoing(); - return l != null ? Collections.unmodifiableList(l) : Collections.emptyList(); - } - public void State.addOutgoing(Transition o) { - assertNotNull(o); - if (o != null && o.tokenState__impl_From != null) { - ArrayList<Transition> list2 = o.tokenState__impl_From.tokenArrayList_Transition___impl_Outgoing; - if (list2.remove(o)) - o.tokenState__impl_From.set_impl_Outgoing(list2); - } - ArrayList<Transition> list = tokenArrayList_Transition___impl_Outgoing; - if (list == null) { - list = new ArrayList<>(); - } - list.add(o); - set_impl_Outgoing(list); - o.set_impl_From(this); - } - public void State.addOutgoing(int index, Transition o) { - assertNotNull(o); - if (o != null && o.tokenState__impl_From != null) { - ArrayList<Transition> list2 = o.tokenState__impl_From.tokenArrayList_Transition___impl_Outgoing; - if (list2.remove(o)) - o.tokenState__impl_From.set_impl_Outgoing(list2); - } - ArrayList<Transition> list = tokenArrayList_Transition___impl_Outgoing; - if (list == null) { - list = new ArrayList<>(); - } - list.add(index, o); - set_impl_Outgoing(list); - o.set_impl_From(this); - } - public void State.removeOutgoing(Transition o) { - assertNotNull(o); - ArrayList<Transition> list = tokenArrayList_Transition___impl_Outgoing; - if (list != null && list.remove(o)) { - set_impl_Outgoing(list); - if (o.tokenState__impl_From == this) { - o.set_impl_From(null); - } - } - } - - // rel Transition.To <-> State.Incoming* - /** - * @relation To - */ - public State Transition.getTo() { - return get_impl_To(); - } - public Transition Transition.setTo(State o) { - assertNotNull(o); - if (tokenState__impl_To != null) { - ArrayList<Transition> list2 = tokenState__impl_To.tokenArrayList_Transition___impl_Incoming; - list2.remove(this); - tokenState__impl_To.set_impl_Incoming(list2); - } - set_impl_To(o); - ArrayList<Transition> list = o.tokenArrayList_Transition___impl_Incoming; - if (list == null) { - list = new ArrayList<>(); - } - list.add(this); - o.set_impl_Incoming(list); - return this; - } - /** - * @relation Incoming - */ - public java.util.List<Transition> State.getIncomings() { - return getIncomingList(); - } - public java.util.List<Transition> State.getIncomingList() { - ArrayList<Transition> l = get_impl_Incoming(); - return l != null ? Collections.unmodifiableList(l) : Collections.emptyList(); - } - public void State.addIncoming(Transition o) { - assertNotNull(o); - if (o != null && o.tokenState__impl_To != null) { - ArrayList<Transition> list2 = o.tokenState__impl_To.tokenArrayList_Transition___impl_Incoming; - if (list2.remove(o)) - o.tokenState__impl_To.set_impl_Incoming(list2); - } - ArrayList<Transition> list = tokenArrayList_Transition___impl_Incoming; - if (list == null) { - list = new ArrayList<>(); - } - list.add(o); - set_impl_Incoming(list); - o.set_impl_To(this); - } - public void State.addIncoming(int index, Transition o) { - assertNotNull(o); - if (o != null && o.tokenState__impl_To != null) { - ArrayList<Transition> list2 = o.tokenState__impl_To.tokenArrayList_Transition___impl_Incoming; - if (list2.remove(o)) - o.tokenState__impl_To.set_impl_Incoming(list2); - } - ArrayList<Transition> list = tokenArrayList_Transition___impl_Incoming; - if (list == null) { - list = new ArrayList<>(); - } - list.add(index, o); - set_impl_Incoming(list); - o.set_impl_To(this); - } - public void State.removeIncoming(Transition o) { - assertNotNull(o); - ArrayList<Transition> list = tokenArrayList_Transition___impl_Incoming; - if (list != null && list.remove(o)) { - set_impl_Incoming(list); - if (o.tokenState__impl_To == this) { - o.set_impl_To(null); - } - } - } - - // rel StateMachine.Initial -> State - /** - * @relation Initial - */ - public State StateMachine.getInitial() { - return get_impl_Initial(); - } - public StateMachine StateMachine.setInitial(State o) { - assertNotNull(o); - set_impl_Initial(o); - return this; - } - - // rel StateMachine.Final* -> State - /** - * @relation Final - */ - public java.util.List<State> StateMachine.getFinals() { - return getFinalList(); - } - public java.util.List<State> StateMachine.getFinalList() { - ArrayList<State> l = get_impl_Final(); - return l != null ? Collections.unmodifiableList(l) : Collections.emptyList(); - } - public void StateMachine.addFinal(State o) { - assertNotNull(o); - ArrayList<State> list = tokenArrayList_State___impl_Final; - if (list == null) { - list = new ArrayList<>(); - } - list.add(o); - set_impl_Final(list); - } - public void StateMachine.addFinal(int index, State o) { - assertNotNull(o); - ArrayList<State> list = tokenArrayList_State___impl_Final; - if (list == null) { - list = new ArrayList<>(); - } - list.add(index, o); - set_impl_Final(list); - } - public void StateMachine.removeFinal(State o) { - assertNotNull(o); - ArrayList<State> list = tokenArrayList_State___impl_Final; - if (list != null && list.remove(o)) { - set_impl_Final(list); - } - } - - public boolean ASTNode.violatesLowerBounds() { - return !getLowerBoundsViolations().isEmpty(); - } - public java.util.List<Pair<ASTNode, String>> ASTNode.getLowerBoundsViolations() { - ArrayList<Pair<ASTNode, String>> list = new ArrayList<>(); - computeLowerBoundsViolations(list); - return list; - } - public void ASTNode.computeLowerBoundsViolations(java.util.List<Pair<ASTNode, String>> list) { - for (int i = 0; i < getNumChildNoTransform(); i++) { - getChildNoTransform(i).computeLowerBoundsViolations(list); - } - } - public void StateMachine.computeLowerBoundsViolations(java.util.List<Pair<ASTNode, String>> list) { - if (getInitial() == null) { - list.add(new Pair<>(this, "Initial")); - } - super.computeLowerBoundsViolations(list); - } - public void Transition.computeLowerBoundsViolations(java.util.List<Pair<ASTNode, String>> list) { - if (getFrom() == null) { - list.add(new Pair<>(this, "From")); - } - if (getTo() == null) { - list.add(new Pair<>(this, "To")); - } - super.computeLowerBoundsViolations(list); - } - public class Pair<T1, T2> { - public final T1 _1; - public final T2 _2; - public Pair(T1 _1, T2 _2) { - ASTNode.assertNotNull(_1); - ASTNode.assertNotNull(_2); - this._1 = _1; - this._2 = _2; - } - public boolean equals(Object other) { - if (other instanceof Pair) { - Pair<?,?> p = (Pair<?,?>) other; - return _1.equals(p._1) && _2.equals(p._2); - } else { - return false; - } - } - public int hashCode() { - return 31*_1.hashCode() + _2.hashCode(); - } - } - public static void ASTNode.assertNotNull(Object obj) { - if (obj == null) { - throw new NullPointerException(); - } - } -} diff --git a/statemachine/src/main/java/de/tudresden/inf/st/statemachine/DrAstRunner.java b/statemachine/src/main/java/de/tudresden/inf/st/statemachine/DrAstRunner.java new file mode 100644 index 0000000000000000000000000000000000000000..d22a3a3f1faf6bb1639e1fc696d784a17b8cdfdc --- /dev/null +++ b/statemachine/src/main/java/de/tudresden/inf/st/statemachine/DrAstRunner.java @@ -0,0 +1,82 @@ +package de.tudresden.inf.st.statemachine; + +import drast.Log; +import drast.model.DrAST; +import drast.model.DrASTSettings; +import drast.model.TreeFilter; +import drast.views.gui.DrASTGUI; +import drast.views.gui.GUIData; +import drast.views.gui.controllers.Controller; +import drast.views.gui.graph.GraphView; +import javafx.application.Platform; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Rectangle2D; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.ScrollPane; +import javafx.stage.Screen; +import javafx.stage.Stage; + +/** + * Extended runner for DrAST + * + * @author jmey - Initial contribution + */ +public class DrAstRunner extends DrASTGUI { + + public static void main(String[] args) { + + openView(); + System.exit(0); + + } + + private static final GUIData mon = new GUIData(); + private static Controller con; + private static boolean guiHasBeenCreated = false; + + private static void openView() { + guiHasBeenCreated = true; + DrASTSettings.put(DrASTSettings.PREV_JAR, "build/libs/statemachine-0.1.jar"); + launch(new String[0]); + con.onApplicationClose(); + } + + public void setRoot(Object root) { + long timeStart = System.currentTimeMillis(); + DrAST newAst = new DrAST(root, TreeFilter.readFilter(con.getFilter())); + Log.info("Filter update: done after %d ms", new Object[]{System.currentTimeMillis() - timeStart}); + Platform.runLater(() -> { + mon.reset(newAst); + if (guiHasBeenCreated) { + con.onSetRoot(); + } else { + openView(); + } + + }); + } + + public void start(Stage stage) throws Exception { + FXMLLoader loader = new FXMLLoader(); + Parent rootView = (Parent)loader.load(this.getClass().getResource("/main.fxml").openStream()); + con = (Controller)loader.getController(); + mon.setParentStage(stage); + mon.setController(con); + mon.setDrASTUI(this); + mon.setStage(stage); + GraphView graphview = new GraphView(mon); + graphview.setOnMouseClicked((event) -> graphview.getParent().requestFocus()); + mon.setGraphView(graphview); + con.init(mon); + Rectangle2D primaryScreenBounds = Screen.getPrimary().getVisualBounds(); + stage.setTitle("DrAST 1.2.2"); + stage.setScene(new Scene(rootView, primaryScreenBounds.getWidth(), primaryScreenBounds.getHeight() - 100.0D)); + stage.show(); + ScrollPane center = (ScrollPane)rootView.lookup("#graphViewScrollPane"); + center.setContent(graphview); + Platform.runLater(() -> graphview.setPreferredSize((int)center.getWidth(), (int)center.getHeight())); + con.loadPreviousFilter(); + } + +} diff --git a/statemachine/src/test/java/de/tudresden/inf/st/statemachine/ParserTest.java b/statemachine/src/test/java/de/tudresden/inf/st/statemachine/ParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7628327f4fdc8c58294fab94de040b4e7307971b --- /dev/null +++ b/statemachine/src/test/java/de/tudresden/inf/st/statemachine/ParserTest.java @@ -0,0 +1,98 @@ +package de.tudresden.inf.st.statemachine; + +import beaver.Parser; +import de.tudresden.inf.st.statemachine.jastadd.model.State; +import de.tudresden.inf.st.statemachine.jastadd.model.StateMachine; +import de.tudresden.inf.st.statemachine.jastadd.model.Transition; +import de.tudresden.inf.st.statemachine.jastadd.parser.StateMachineParser; +import de.tudresden.inf.st.statemachine.jastadd.scanner.StateMachineScanner; +import org.junit.Test; + +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.junit.Assert.*; + +/** + * TODO: Add description. + * + * @author rschoene - Initial contribution + */ +public class ParserTest { + + @Test + public void test1() throws IOException, Parser.Exception { + StateMachine stateMachine = load(Paths.get("src", "test", "resources", "machine_one.sm")); + + assertEquals(6, stateMachine.getNumElement()); + assertEquals(3, stateMachine.states().size()); + assertEquals(3, stateMachine.transitions().size()); + + State s = stateMachine.globallyResolveStateByToken("S"); + State a = stateMachine.globallyResolveStateByToken("A"); + State e = stateMachine.globallyResolveStateByToken("E"); + Transition t1 = stateMachine.globallyResolveTransitionByToken("t1"); + Transition t2 = stateMachine.globallyResolveTransitionByToken("t2"); + Transition t3 = stateMachine.globallyResolveTransitionByToken("t3"); + + assertNotNull(s); + assertNotNull(a); + assertNotNull(e); + + assertEquals(s, stateMachine.getInitial()); + assertEquals(1, stateMachine.getFinalList().size()); + assertThat("E is not final", stateMachine.getFinalList(), hasItem(e)); + + assertNotNull(t1); + assertNotNull(t2); + assertNotNull(t3); + + // t1: s -> a + assertEquals(s, t1.getFrom()); + assertEquals(a, t1.getTo()); + // t2: a -> s + assertEquals(a, t2.getFrom()); + assertEquals(s, t2.getTo()); + // t3: a -> e + assertEquals(a, t3.getFrom()); + assertEquals(e, t3.getTo()); + + List<State> outgoingFromS = outgoingConnectedStates(s); + List<State> outgoingFromA = outgoingConnectedStates(a); + assertThat(outgoingFromS, not(empty())); + assertThat(outgoingFromA, not(empty())); + assertEquals(1, outgoingFromS.size()); + assertThat("Transition S -> A missing", outgoingFromS, hasItem(a)); + assertEquals(2, outgoingFromA.size()); + assertThat("Transitions A -> S or A -> E missing", outgoingFromA, hasItems(s, e)); + assertThat(outgoingConnectedStates(e), empty()); + + String printedForm = "initial state S;\n" + + "state A;\n" + + "final state E;\n" + + "trans S -> A : t1;\n" + + "trans A -> S : t2;\n" + + "trans A -> E : t3;\n"; + assertEquals(printedForm, stateMachine.prettyPrint()); + } + + private List<State> outgoingConnectedStates(State s) { + return s.getOutgoingList().stream().map(Transition::getTo).collect(Collectors.toList()); + } + + private static StateMachine load(Path path) throws IOException, Parser.Exception { + Reader reader = Files.newBufferedReader(path); + StateMachineScanner scanner = new StateMachineScanner(reader); + StateMachineParser parser = new StateMachineParser(); + StateMachine result = (StateMachine) parser.parse(scanner); + reader.close(); + return result; + } +} diff --git a/statemachine/src/test/resources/machine_one.sm b/statemachine/src/test/resources/machine_one.sm new file mode 100644 index 0000000000000000000000000000000000000000..897ccba6b19229216233f9c8b8af57ac03bf8852 --- /dev/null +++ b/statemachine/src/test/resources/machine_one.sm @@ -0,0 +1,6 @@ +initial state S; +state A; +final state E; +trans S -> A : t1; +trans A -> S : t2; +trans A -> E : t3;