diff --git a/SanityCheck.jar b/SanityCheck.jar index ae0827bf18a9d723f76089c40656eceb4da08e8c..bebdf1da3e6277f966e8fff78ea96d884fe27b0b 100644 Binary files a/SanityCheck.jar and b/SanityCheck.jar differ diff --git a/devTools/javaSanityCheck/htmlTags b/devTools/javaSanityCheck/htmlTags index 608a30a5ff6648b7c873d6c41f6f6d794afbc757..751b084ff5822f4162e3f79ea622b91f60c5472b 100644 --- a/devTools/javaSanityCheck/htmlTags +++ b/devTools/javaSanityCheck/htmlTags @@ -1,5 +1,5 @@ #Allowed HTML tags -#Effectively everything that is allowed in one of these statements like this: +#Effectively everything that is allowed in a these statements like this: #<tag> or <tag ???> #when ;1 is specified it expects a matching closing tag like this: </tag> #Do not add Twine Tags here. @@ -25,11 +25,11 @@ h1;1 h2;1 h3;1 h4;1 -hr;1 +hr;0 html;1 i;1 img;1 -input;1 +input;0 li;1 option;1 script;1 diff --git a/devTools/javaSanityCheck/src/DisallowedTagException.java b/devTools/javaSanityCheck/src/DisallowedTagException.java new file mode 100644 index 0000000000000000000000000000000000000000..f4cc75e736b162192a5f18bbc55a10edb21eaa38 --- /dev/null +++ b/devTools/javaSanityCheck/src/DisallowedTagException.java @@ -0,0 +1,8 @@ +package org.arkerthan.sanityCheck; + +public class DisallowedTagException extends RuntimeException { + + public DisallowedTagException(String tag) { + super(tag); + } +} diff --git a/devTools/javaSanityCheck/src/Main.java b/devTools/javaSanityCheck/src/Main.java index 6a7aee137ca63aad29d76d338f6f47a29351b3f3..eea3a4ff611203b0025cd29ce1fe431447f80e1c 100644 --- a/devTools/javaSanityCheck/src/Main.java +++ b/devTools/javaSanityCheck/src/Main.java @@ -1,11 +1,9 @@ package org.arkerthan.sanityCheck; import org.arkerthan.sanityCheck.element.AngleBracketElement; -import org.arkerthan.sanityCheck.element.AtElement; +import org.arkerthan.sanityCheck.element.CommentElement; import org.arkerthan.sanityCheck.element.Element; -import org.arkerthan.sanityCheck.element.KnownHtmlElement; -import org.arkerthan.sanityCheck.tag.HtmlTag; -import org.arkerthan.sanityCheck.tag.Tag; +import org.arkerthan.sanityCheck.element.KnownElement; import java.io.*; import java.nio.charset.Charset; @@ -16,7 +14,7 @@ import java.util.*; public class Main { - public static TagSearchTree<HtmlTag> htmlTags; + public static TagSearchTree<Tag> htmlTags, twineTags; private static String currentFile; private static int currentLine, currentPosition; private static Stack<Element> stack; @@ -27,6 +25,7 @@ public class Main { //setup setupExclude(); setupHtmlTags(); + setupTwineTags(); Path workingDir = Paths.get("").toAbsolutePath(); //actual sanityCheck @@ -42,7 +41,7 @@ public class Main { /** * Goes through the whole directory including subdirectories and runs - * sanitycheck() on all .tw files + * sanityCheck() on all .tw files * * @param dir to be checked */ @@ -61,7 +60,9 @@ public class Main { } } } catch (NullPointerException e) { - System.err.println("Couldn't find directory " + dir.getPath()); + e.printStackTrace(); + System.err.println("Couldn't find directory " + currentFile); + System.exit(-1); } } @@ -96,23 +97,23 @@ public class Main { } /** - * sets up the alphabetical search tree for fast access later + * sets up the alphabetical search tree for fast access of HTML tags later */ private static void setupHtmlTags() { //load HTML tags into a list - List<Tag> htmlTagsList = new LinkedList<>(); + List<Tag> TagsList = new LinkedList<>(); try { Files.lines(new File("devTools/javaSanityCheck/htmlTags").toPath()).map(String::trim) .filter(s -> !s.startsWith("#")) - .forEach(s -> htmlTagsList.add(parseTag(s))); + .forEach(s -> TagsList.add(parseTag(s))); } catch (IOException e) { System.err.println("Couldn't read devTools/javaSanityCheck/htmlTags"); } //turn List into alphabetical search tree try { - htmlTags = new TagSearchTree(htmlTagsList); + htmlTags = new TagSearchTree(TagsList); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Illegal Character in devTools/javaSanityCheck/htmlTags"); System.exit(-1); @@ -120,18 +121,42 @@ public class Main { } /** - * Turns a string into a HtmlTag + * sets up the alphabetical search tree for fast access of twine tags later + */ + private static void setupTwineTags() { + //load twine tags into a list + List<Tag> TagsList = new LinkedList<>(); + try { + + Files.lines(new File("devTools/javaSanityCheck/twineTags").toPath()).map(String::trim) + .filter(s -> !s.startsWith("#")) + .forEach(s -> TagsList.add(parseTag(s))); + } catch (IOException e) { + System.err.println("Couldn't read devTools/javaSanityCheck/twineTags"); + } + + //turn List into alphabetical search tree + try { + twineTags = new TagSearchTree(TagsList); + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println("Illegal Character in devTools/javaSanityCheck/twineTags"); + System.exit(-1); + } + } + + /** + * Turns a string into a Tag * ";1" at the end of the String indicates that the tag needs to be closed later * * @param s tag as String - * @return tag as HtmlTag + * @return tag as Tag */ - private static HtmlTag parseTag(String s) { + private static Tag parseTag(String s) { String[] st = s.split(";"); if (st.length > 1 && st[1].equals("1")) { - return new HtmlTag(st[0], false); + return new Tag(st[0], false); } - return new HtmlTag(st[0], true); + return new Tag(st[0], true); } /** @@ -225,45 +250,64 @@ public class Main { if (change == 2) { //remove the topmost element from stack since it is complete stack.pop(); + return; } //3 means the Element is complete and part of a two tag system if (change == 3) { //remove the topmost element from stack since it is complete - KnownHtmlElement k = stack.pop().getKnownElement(); - if (k.isOpening()) { + KnownElement k = stack.pop().getKnownElement(); + /*if (k.isOpening()) { stack.push(k); - } else if (stack.empty()) { - addError(new SyntaxError("Closed HTML tag \"" + k.getStatement() + "\" without having any open tags.", -1)); - } else if (stack.peek() instanceof KnownHtmlElement) { - KnownHtmlElement kFirst = (KnownHtmlElement) stack.peek(); - if (!kFirst.isMatchingElement(k)) { - addError(new SyntaxError("Opening HTML tag \"" + kFirst.getStatement() + - "\" does not match closing tag \"" + k.getStatement() + "\".", -1)); + } else */ + if (k.isClosing()) { + if (stack.empty()) { + addError(new SyntaxError("Closed tag " + k.getShortDescription() + " without having any open tags.", -2)); + } else if (stack.peek() instanceof KnownElement) { + KnownElement kFirst = (KnownElement) stack.pop(); + if (!kFirst.isMatchingElement(k)) { + addError(new SyntaxError("Opening tag " + kFirst.getShortDescription() + + " does not match closing tag " + k.getShortDescription() + ".", -2)); + } + //stack.pop(); + } else { + addError(new SyntaxError("Closing tag " + k.getShortDescription() + " inside " + + "another tag: " + stack.peek().getShortDescription(), -2, true)); } - stack.pop(); - } else { - addError(new SyntaxError("Closing HTML tag \"" + k.getStatement() + "\" inside " + - "another tag: " + stack.peek().getShortDescription(), -1, true)); } + if (k.isOpening()) { + stack.push(k); + } + return; + } + if (change == 4) { + stack.pop(); + } else { + return; } - return; } } //innermost element was uninterested, trying to find matching element switch (c) { - case '@': - stack.push(new AtElement(currentLine, currentPosition)); - break; + //case '@': + // stack.push(new AtElement(currentLine, currentPosition)); + //break; case '<': stack.push(new AngleBracketElement(currentLine, currentPosition)); break; + //case '>': + //addError(new SyntaxError("Dangling \">\", current innermost: " + (stack.empty() ? "null" : stack.peek().getShortDescription()), -2)); + //break; + case '/': + stack.push(new CommentElement(currentLine, currentPosition)); + break; } } /** * add an error to the error list + * * @param e new error */ private static void addError(SyntaxError e) { diff --git a/devTools/javaSanityCheck/src/SyntaxError.java b/devTools/javaSanityCheck/src/SyntaxError.java index 90d9db7333c3b82728fc1c21dad4591e2c9d16bf..150f2bd449b8c318b5a05884868a71538554ec67 100644 --- a/devTools/javaSanityCheck/src/SyntaxError.java +++ b/devTools/javaSanityCheck/src/SyntaxError.java @@ -4,7 +4,7 @@ public class SyntaxError extends Exception { private String file; private int line, position; private String description; - private int change; //see Element for values; -1 means not thrown + private int change; //see Element for values; -2 means not thrown private boolean warning = false; public SyntaxError(String description, int change) { diff --git a/devTools/javaSanityCheck/src/tag/Tag.java b/devTools/javaSanityCheck/src/Tag.java similarity index 52% rename from devTools/javaSanityCheck/src/tag/Tag.java rename to devTools/javaSanityCheck/src/Tag.java index 386292b48eb43f2eeec4721addc62f5fbc328159..8a13ee4f7a178399db3eaf626b693e8a12ae71df 100644 --- a/devTools/javaSanityCheck/src/tag/Tag.java +++ b/devTools/javaSanityCheck/src/Tag.java @@ -1,10 +1,10 @@ -package org.arkerthan.sanityCheck.tag; +package org.arkerthan.sanityCheck; -public abstract class Tag { +public class Tag { public final String tag; public final boolean single; - protected Tag(String tag, boolean single) { + public Tag(String tag, boolean single) { this.tag = tag; this.single = single; } diff --git a/devTools/javaSanityCheck/src/TagSearchTree.java b/devTools/javaSanityCheck/src/TagSearchTree.java index 567f33f35d7d4aef7bd2b2db70f5b49c0ea6b01a..dde49df879a346f124d15647cfeb821d0e0735fb 100644 --- a/devTools/javaSanityCheck/src/TagSearchTree.java +++ b/devTools/javaSanityCheck/src/TagSearchTree.java @@ -1,32 +1,52 @@ package org.arkerthan.sanityCheck; -import org.arkerthan.sanityCheck.tag.Tag; - import java.util.List; +/** + * Tag SearchTree stores Tags in an alphabetical search tree. + * Once created the search tree can't be changed anymore. + * + * @param <E> Tag class to be stored + */ public class TagSearchTree<E extends Tag> { private static final int SIZE = 128; + private final TagSearchTree<E>[] branches; private E element = null; - private TagSearchTree<E>[] branches; private String path; + /** + * creates a new empty TagSearchTree + */ private TagSearchTree() { branches = new TagSearchTree[SIZE]; } + /** + * Creates a new filled TagSearchTree + * + * @param list Tags to be inserted + */ public TagSearchTree(List<E> list) { this(); - for (E e : - list) { + for (E e : list) { this.add(e, 0); } } + /** + * adds a new Tag to the TagSearchTree + * + * @param e Tag to be stored + * @param index index of relevant char for adding in tag + */ private void add(E e, int index) { - path = e.tag.substring(0,index); + //set the path to here + path = e.tag.substring(0, index); + //checks if tag has to be stored here or further down if (e.tag.length() == index) { element = e; } else { + //store tag in correct branch char c = e.tag.charAt(index); if (branches[c] == null) { branches[c] = new TagSearchTree<>(); @@ -35,15 +55,25 @@ public class TagSearchTree<E extends Tag> { } } + /** + * @param c character of branch needed + * @return branch or null if branch doesn't exist + */ public TagSearchTree<E> getBranch(char c) { if (c >= SIZE) return null; return branches[c]; } + /** + * @return stored Tag, null if empty + */ public E getElement() { return element; } + /** + * @return path inside full tree to get to this Branch + */ public String getPath() { return path; } diff --git a/devTools/javaSanityCheck/src/element/AngleBracketElement.java b/devTools/javaSanityCheck/src/element/AngleBracketElement.java index 35877dec434f5795fa0b81be43847b0a4e061104..e4819ba37ea48e4924dc944827d651fa14e02ad1 100644 --- a/devTools/javaSanityCheck/src/element/AngleBracketElement.java +++ b/devTools/javaSanityCheck/src/element/AngleBracketElement.java @@ -1,28 +1,39 @@ package org.arkerthan.sanityCheck.element; -import org.arkerthan.sanityCheck.Main; -import org.arkerthan.sanityCheck.SyntaxError; -import org.arkerthan.sanityCheck.TagSearchTree; -import org.arkerthan.sanityCheck.UnknownStateException; -import org.arkerthan.sanityCheck.tag.HtmlTag; +import org.arkerthan.sanityCheck.*; + +import java.util.Arrays; +import java.util.List; public class AngleBracketElement extends Element { + private static final List<String> logicTags = Arrays.asList("if", "elseif", "else", "switch", "case", "default"); private int state = 0; /* - -1 - </ 0 - initial: < + TWINE 1 - << - 2 - <<abc - 3 - <<abc> - - 4 - trying to complete HTML tag: <tag ???> - -4 - trying to complete HTML tag: </tag> - 5 - waiting for > + -1 - <</ + 2 - trying to complete twine tag: <<tag ???>> + -2 - trying to complete twine tag: <</tag>> + 3 - waiting for >> + -3 - expecting > from 3 + 4 - waiting for >> with KnownElement + -4 - expecting > from 4 + 5 - expecting >> -5 - expecting > - 6 - waiting for > with KnownHtmlElement + 6 - expecting > with KnownElement opening; comparison? + -6 - expecting > with KnownElement closing + + HTML + -9 - </ + 10 - trying to complete HTML tag: <tag ???> + -10 - trying to complete HTML tag: </tag> + 11 - waiting for > + -11 - expecting > + 12 - waiting for > with KnownElement */ - private TagSearchTree<HtmlTag> htmlTree; + private TagSearchTree<Tag> tree; public AngleBracketElement(int line, int pos) { super(line, pos); @@ -39,7 +50,7 @@ public class AngleBracketElement extends Element { case '>': throw new SyntaxError("Empty Statement?", 2); case '/': - state = -1; + state = -9; return 1; case ' ':// assume comparison case '=':// " @@ -48,63 +59,118 @@ public class AngleBracketElement extends Element { return 2; default: try { - state = 4; - htmlTree = Main.htmlTags; + state = 10; + tree = Main.htmlTags; return handleOpeningHTML(c); } catch (SyntaxError e) { state = 1; throw new SyntaxError("Opening \"<\" missing, found " + c + " [debug:initialCase]", 1); } } - case -1: - if (c == '>') { - throw new SyntaxError("Empty Statement?", 2, true); - } - state = -4; - htmlTree = Main.htmlTags; - return handleClosingHTML(c); case 1: if (c == '<') { throw new SyntaxError("Too many \"<\".", 1); } else if (c == '>') { state = 3; throw new SyntaxError("Empty Statement?", 1); - } else { - state = 2; + } else if (c == '/') { + state = -1; return 1; } + state = 2; + tree = Main.twineTags; + return handleOpeningTwine(c); + case -1: + if (c == '>') { + throw new SyntaxError("Empty Statement?", 2, true); + } + state = -2; + tree = Main.twineTags; + return handleClosingTwine(c); + case 2: - //TODO finding special Twine statements: IF, ELSE... + return handleOpeningTwine(c); + case -2: + return handleClosingTwine(c); + case 3: if (c == '>') { - state = 3; + state = -3; return 1; } break; - case 3: + case -3: if (c == '>') { return 2; } else if (c == ' ' || c == '=') { // assuming comparison - state = 2; + state = 3; + return 1; } else { - throw new SyntaxError("Closing \">\" missing [1]", 2); + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2); + } + case 4: + if (c == '>') { + state = -4; + return 1; } break; + case -4: + if (c == '>') { + return 3; + } else if (c == ' ' || c == '=') { // assuming comparison + state = 4; + return 1; + } else { + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2); + } + case 5: + if (c == '>') { + state = -5; + return 1; + } else { + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2); + } + case -5: + if (c == '>') { + return 2; + } + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 2); + case 6: + if (c == '>') { + return 3; + } else if (c == ' ' || c == '=') { + state = 3; + return 1; + } else { + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 3); + } + case -6: + if (c == '>') { + return 3; + } + throw new SyntaxError("Closing \">\" missing, opened [" + line + ":" + pos + "]", 3); - case 4: + case -9: + if (c == '>') { + throw new SyntaxError("Empty Statement?", 2, true); + } + state = -10; + tree = Main.htmlTags; + return handleClosingHTML(c); + case 10: return handleOpeningHTML(c); - case -4: + case -10: return handleClosingHTML(c); - case 5: + case 11: if (c == '>') return 2; if (c == '@') //@ inside HTML tags is allowed return 1; break; - case -5: + case -11: if (c == '>') return 2; throw new SyntaxError("Closing \">\" missing [2]", 2); - case 6: + case 12: if (c == '>') return 3; if (c == '@') //@ inside HTML tags is allowed @@ -118,31 +184,31 @@ public class AngleBracketElement extends Element { private int handleOpeningHTML(char c) throws SyntaxError { if (c == ' ') { - state = 5; - if (htmlTree.getElement() == null) { + state = 11; + if (tree.getElement() == null) { throw new SyntaxError("Unknown HTML tag", 1); } - if (!htmlTree.getElement().single) { - k = new KnownHtmlElement(line, pos, true, htmlTree.getElement().tag); - state = 6; + if (!tree.getElement().single) { + k = new KnownHtmlElement(line, pos, true, tree.getElement().tag); + state = 12; return 1; } return 1; } if (c == '>') { - if (htmlTree.getElement() == null) { + if (tree.getElement() == null) { throw new SyntaxError("Unknown HTML tag", 2); } - if (!htmlTree.getElement().single) { - k = new KnownHtmlElement(line, pos, true, htmlTree.getElement().tag); + if (!tree.getElement().single) { + k = new KnownHtmlElement(line, pos, true, tree.getElement().tag); return 3; } return 2; } - htmlTree = htmlTree.getBranch(c); - if (htmlTree == null) { - state = 5; + tree = tree.getBranch(c); + if (tree == null) { + state = 11; throw new SyntaxError("Unknown HTML tag or closing \">\" missing, found " + c, 1); } @@ -151,29 +217,104 @@ public class AngleBracketElement extends Element { private int handleClosingHTML(char c) throws SyntaxError { if (c == '>') { - if (htmlTree.getElement() == null) { + if (tree.getElement() == null) { throw new SyntaxError("Unknown HTML tag", 2); } - if (htmlTree.getElement().single) { - throw new SyntaxError("Single HTML tag used as closing Tag: " + htmlTree.getElement().tag, 2); + if (tree.getElement().single) { + throw new SyntaxError("Single HTML tag used as closing Tag: " + tree.getElement().tag, 2); } - k = new KnownHtmlElement(line, pos, false, htmlTree.getElement().tag); + k = new KnownHtmlElement(line, pos, false, tree.getElement().tag); return 3; } - htmlTree = htmlTree.getBranch(c); - if (htmlTree == null) { - state = -5; + tree = tree.getBranch(c); + if (tree == null) { + state = -11; throw new SyntaxError("Unknown HTML tag or closing \">\" missing, found " + c, 1); } return 1; } + + private int handleOpeningTwine(char c) throws SyntaxError { + if (c == ' ') { + state = 3; + if (tree.getElement() == null) { + //assuming not listed means widget until better solution + return 1; + //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + tree.getPath(), 1); + } + if (!tree.getElement().single) { + if (logicTags.contains(tree.getElement().tag)) { + k = new KnownLogicElement(line, pos, tree.getElement().tag, false); + } else { + k = new KnownTwineElement(line, pos, true, tree.getElement().tag); + } + state = 4; + return 1; + } + return 1; + } + if (c == '>') { + state = -5; + if (tree.getElement() == null) { + //assuming not listed means widget until better solution + //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + tree.getPath(), 1); + return 1; + } + if (!tree.getElement().single) { + if (logicTags.contains(tree.getElement().tag)) { + k = new KnownLogicElement(line, pos, tree.getElement().tag, false); + } else { + k = new KnownTwineElement(line, pos, true, tree.getElement().tag); + } + state = 6; + return 1; + } + return 2; + } + + tree = tree.getBranch(c); + if (tree == null) { + //assuming not listed means widget until better solution + state = 3; + //throw new SyntaxError("Unknown Twine tag or closing \">>\" missing, found " + c, 1); + } + + return 1; + } + + private int handleClosingTwine(char c) throws SyntaxError { + if (c == '>') { + if (tree.getElement() == null) { + throw new SyntaxError("Unknown Twine tag", 2); + } + if (tree.getElement().single) { + throw new SyntaxError("Single Twine tag used as closing Tag: " + tree.getElement().tag, 2); + } + if (logicTags.contains(tree.getElement().tag)) { + k = new KnownLogicElement(line, pos, tree.getElement().tag, true); + } else { + k = new KnownTwineElement(line, pos, false, tree.getElement().tag); + } + state = -6; + return 1; + } + + tree = tree.getBranch(c); + if (tree == null) { + state = 3; + throw new SyntaxError("Unknown Twine closing tag or closing \">>\" missing, found " + c, 1); + } + + return 1; + } + @Override public String getShortDescription() { StringBuilder builder = new StringBuilder(); - builder.append(line).append(":").append(pos).append(" "); + builder.append('[').append(line).append(":").append(pos).append("] "); switch (state) { case 0: builder.append("<"); @@ -182,31 +323,37 @@ public class AngleBracketElement extends Element { builder.append("<<"); break; case -1: - builder.append("</"); + builder.append("<</"); break; case 2: - builder.append("<<???"); + builder.append("<<").append(tree.getPath()); + break; + case -2: + builder.append("<</").append(tree.getPath()); break; case 3: - builder.append("<<???>"); + builder.append("<<??? ???"); break; case 4: - builder.append("<").append(htmlTree.getPath()); + builder.append("<<?").append(tree.getPath()).append(" ???"); + break; + case -3: + builder.append("<<??? ???>"); break; case -4: - builder.append("</").append(htmlTree.getPath()); + builder.append("<<?").append(tree.getPath()).append(" ???>"); break; case 5: - builder.append("<").append(htmlTree.getPath()).append(" ???"); + builder.append("<").append(tree.getPath()).append(" ???"); break; case -5: - builder.append("</").append(htmlTree.getPath()); + builder.append("</").append(tree.getPath()); break; case 6: - builder.append("<").append(htmlTree.getPath()).append(" ???"); + builder.append("<").append(tree.getPath()).append(" ???"); break; default: - throw new UnknownStateException(state); + //throw new UnknownStateException(state); } return builder.toString(); } diff --git a/devTools/javaSanityCheck/src/element/CommentElement.java b/devTools/javaSanityCheck/src/element/CommentElement.java new file mode 100644 index 0000000000000000000000000000000000000000..3a3cc12aff9f3c2e4b06cc7240d14824575cc96e --- /dev/null +++ b/devTools/javaSanityCheck/src/element/CommentElement.java @@ -0,0 +1,66 @@ +package org.arkerthan.sanityCheck.element; + +import org.arkerthan.sanityCheck.SyntaxError; +import org.arkerthan.sanityCheck.UnknownStateException; + +public class CommentElement extends Element { + int state = 0; + /* + 0 - / + 1 - /*??? + 2 - /*???* + 3 - /%??? + 4 - /%???% + */ + + public CommentElement(int line, int pos) { + super(line, pos); + } + + @Override + public int handleChar(char c) throws SyntaxError { + switch (state) { + case 0: + if (c == '*') { + state = 1; + } else if (c == '%') { + state = 3; + } else if (c == '>') { + throw new SyntaxError("XHTML style closure", 4, true); + } else { + return 4; + } + break; + case 1: + if (c == '*') { + state = 2; + } + break; + case 2: + if (c == '/') { + return 2; + } + state = 1; + break; + case 3: + if (c == '%') { + state = 4; + } + break; + case 4: + if (c == '/') { + return 2; + } + state = 3; + break; + default: + throw new UnknownStateException(state); + } + return 1; + } + + @Override + public String getShortDescription() { + return null; + } +} diff --git a/devTools/javaSanityCheck/src/element/Element.java b/devTools/javaSanityCheck/src/element/Element.java index 5393426861853b5397f67fdb6cd85926d8481c72..b0f99fa904f66a6a9ebcecb5ffdfb7040493b08b 100644 --- a/devTools/javaSanityCheck/src/element/Element.java +++ b/devTools/javaSanityCheck/src/element/Element.java @@ -3,13 +3,12 @@ package org.arkerthan.sanityCheck.element; import org.arkerthan.sanityCheck.SyntaxError; public abstract class Element { - protected KnownHtmlElement k; + protected KnownElement k; protected int line, pos; /** - * * @param line Line the instance was created - * @param pos Position in line the instance was created + * @param pos Position in line the instance was created */ protected Element(int line, int pos) { this.line = line; @@ -22,6 +21,7 @@ public abstract class Element { * 1 - the Element changed state * 2 - the Element is finished * 3 - the Element is finished and a KnownHtmlElement was generated + * 4 - the Element is finished and the char is still open for use * * @param c * @return @@ -29,12 +29,11 @@ public abstract class Element { */ public abstract int handleChar(char c) throws SyntaxError; - public KnownHtmlElement getKnownElement() { + public KnownElement getKnownElement() { return k; } /** - * * @return a short description usually based on state and position of the Element */ public abstract String getShortDescription(); diff --git a/devTools/javaSanityCheck/src/element/KnownElement.java b/devTools/javaSanityCheck/src/element/KnownElement.java new file mode 100644 index 0000000000000000000000000000000000000000..305be2fe65210b191d96ead352487b35e448ce39 --- /dev/null +++ b/devTools/javaSanityCheck/src/element/KnownElement.java @@ -0,0 +1,31 @@ +package org.arkerthan.sanityCheck.element; + +import org.arkerthan.sanityCheck.SyntaxError; + +public abstract class KnownElement extends Element { + + public KnownElement(int line, int pos) { + super(line, pos); + } + + /** + * @return true, if it needs another Known Element to close it. + */ + public abstract boolean isOpening(); + + /** + * @return true if it closes another Element. + */ + public abstract boolean isClosing(); + + /** + * @param k Element to be checked + * @return true if given Element closes Element + */ + public abstract boolean isMatchingElement(KnownElement k); + + @Override + public int handleChar(char c) throws SyntaxError { + return 0; + } +} diff --git a/devTools/javaSanityCheck/src/element/KnownHtmlElement.java b/devTools/javaSanityCheck/src/element/KnownHtmlElement.java index b3b136733787bcea1261e15684fac14770e8ea66..d086a74bc547a0aa90520e50c4398f5cf6dc365e 100644 --- a/devTools/javaSanityCheck/src/element/KnownHtmlElement.java +++ b/devTools/javaSanityCheck/src/element/KnownHtmlElement.java @@ -1,6 +1,6 @@ package org.arkerthan.sanityCheck.element; -public class KnownHtmlElement extends Element { +public class KnownHtmlElement extends KnownElement { private boolean opening; private String statement; @@ -11,43 +11,31 @@ public class KnownHtmlElement extends Element { this.statement = statement; } - @Override - public int handleChar(char c) { - return 0; - } - @Override public String getShortDescription() { StringBuilder builder = new StringBuilder(); - builder.append(line).append(":").append(pos).append(" <"); - if(!opening){ + builder.append('[').append(line).append(":").append(pos).append("] <"); + if (!opening) { builder.append("/"); } - return builder.append(statement).toString(); + return builder.append(statement).append(">").toString(); } - /** - * @return true, if it needs another Known Element to close it, false if it closes another element. - */ + @Override public boolean isOpening() { return opening; } - /** - * @param k Element to be checked - * @return true if given Element closes Element - */ - public boolean isMatchingElement(KnownHtmlElement k) { - return k.statement.equals(this.statement); + @Override + public boolean isClosing() { + return !opening; } - /** - * Returns, if isOpening is true, the needed statement for closing, - * otherwise the statement that generated it. - * - * @return statement - */ - public String getStatement() { - return statement; + @Override + public boolean isMatchingElement(KnownElement k) { + if (k instanceof KnownHtmlElement) { + return ((KnownHtmlElement) k).statement.equals(this.statement); + } + return false; } } diff --git a/devTools/javaSanityCheck/src/element/KnownLogicElement.java b/devTools/javaSanityCheck/src/element/KnownLogicElement.java new file mode 100644 index 0000000000000000000000000000000000000000..502abde93a296c3dffb2391b75b08893aeecd2c5 --- /dev/null +++ b/devTools/javaSanityCheck/src/element/KnownLogicElement.java @@ -0,0 +1,117 @@ +package org.arkerthan.sanityCheck.element; + +import org.arkerthan.sanityCheck.DisallowedTagException; +import org.arkerthan.sanityCheck.UnknownStateException; + +import java.util.Arrays; +import java.util.List; + +public class KnownLogicElement extends KnownElement { + private static final List<String> allowedTags = Arrays.asList("if", "elseif", "else"); + private final int state; + private boolean last; + /* + 0 - if + 1 - elseif + 2 - else + 3 - switch + 4 - case + 5 - default + */ + + public KnownLogicElement(int line, int pos, String tag, boolean last) { + this(line, pos, tag); + this.last = last; + } + + public KnownLogicElement(int line, int pos, String tag) { + super(line, pos); + switch (tag) { + case "if": + state = 0; + break; + case "elseif": + state = 1; + break; + case "else": + state = 2; + break; + case "switch": + state = 3; + break; + case "case": + state = 4; + break; + case "default": + state = 5; + break; + default: + throw new DisallowedTagException(tag); + } + last = false; + } + + @Override + public boolean isOpening() { + return !last; + } + + @Override + public boolean isClosing() { + return (state != 0 && state != 3) || last; + } + + @Override + public boolean isMatchingElement(KnownElement k) { + if (!(k instanceof KnownLogicElement)) { + return false; + } + KnownLogicElement l = (KnownLogicElement) k; + switch (state) { + case 0: + case 1: + return l.state == 1 || l.state == 2 || (l.state == 0 && l.last); + case 2: + return l.state == 0 && l.last; + case 3: + case 4: + return l.state == 3 || l.state == 4; + case 5: + return l.state == 3 && l.last; + default: + throw new UnknownStateException(state); + } + } + + @Override + public String getShortDescription() { + StringBuilder builder = new StringBuilder(); + builder.append("[").append(line).append(":").append(pos).append("] <<"); + if (last) { + builder.append('/'); + } + switch (state) { + case 0: + builder.append("if"); + break; + case 1: + builder.append("elseif"); + break; + case 2: + builder.append("else"); + break; + case 3: + builder.append("switch"); + break; + case 4: + builder.append("case"); + break; + case 5: + builder.append("default"); + break; + default: + throw new UnknownStateException(state); + } + return builder.append(">>").toString(); + } +} diff --git a/devTools/javaSanityCheck/src/element/KnownTwineElement.java b/devTools/javaSanityCheck/src/element/KnownTwineElement.java new file mode 100644 index 0000000000000000000000000000000000000000..24003fd00be0bb79aa6a01b2fbd2d9a91439ac6a --- /dev/null +++ b/devTools/javaSanityCheck/src/element/KnownTwineElement.java @@ -0,0 +1,41 @@ +package org.arkerthan.sanityCheck.element; + +public class KnownTwineElement extends KnownElement { + + private boolean opening; + private String statement; + + public KnownTwineElement(int line, int pos, boolean opening, String statement) { + super(line, pos); + this.opening = opening; + this.statement = statement; + } + + @Override + public String getShortDescription() { + StringBuilder builder = new StringBuilder(); + builder.append("[").append(line).append(":").append(pos).append("] <<"); + if (!opening) { + builder.append("/"); + } + return builder.append(statement).append(">>").toString(); + } + + @Override + public boolean isOpening() { + return opening; + } + + @Override + public boolean isClosing() { + return !opening; + } + + @Override + public boolean isMatchingElement(KnownElement k) { + if (k instanceof KnownTwineElement) { + return ((KnownTwineElement) k).statement.equals(this.statement); + } + return false; + } +} diff --git a/devTools/javaSanityCheck/src/tag/HtmlTag.java b/devTools/javaSanityCheck/src/tag/HtmlTag.java deleted file mode 100644 index 70bff2c5a32d27804cb2e95839eddf595fb4693c..0000000000000000000000000000000000000000 --- a/devTools/javaSanityCheck/src/tag/HtmlTag.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.arkerthan.sanityCheck.tag; - -public class HtmlTag extends Tag { - public HtmlTag(String tag, boolean single) { - super(tag, single); - } -} diff --git a/devTools/javaSanityCheck/twineTags b/devTools/javaSanityCheck/twineTags index d8df5639a52b55b94f020884713f15d510f4a782..e1dea71621bd818041d6aad43d7b3053b2c78132 100644 --- a/devTools/javaSanityCheck/twineTags +++ b/devTools/javaSanityCheck/twineTags @@ -7,123 +7,17 @@ #Do not add HTML Tags here. #Characters outside of ASCII scope are not supported. # -#widgets -amputeeDescription;0 -assignmentFilter;0 -resetAssignmentFilter;0 -accentDescription;0 -collarDescription;0 -AnusDescription;0 -armsTatDescription;0 -BoobsDescription;0 -boobBrandDescription;0 -BellyInflationDescription;0 -BellyImplantDescription;0 -BellyDescription;0 -ButtDescription;0 -showallAssignmentFilter;0 -boobsShapeDescription;0 -boobsExtraDescription;0 -boobsTatDescription;0 -shouldersDescription;0 -nipplesDescription;0 -crotchDescription;0 -listOfSlavesWithParent;0 -redisplayFamily;0 -parentName;0 -listOfSlavesWithSameParent;0 -nurseryAssignmentFilter;0 -dickDescription;0 -vaginaDescription;0 -SlaveInteractImpreg;0 -SlaveInteractFertility;0 -SlaveInteractSexOption;0 -SlaveInteractAnalSexOption;0 -SlaveInteractGropeOption;0 -SlaveInteractDickGropeOption;0 -SlaveInteractAnalGropeOption;0 -SlaveInteractDrugs;0 -nipplesPiercingDescription;0 -areolaeDescription;0 -nailsDescription;0 -backTatDescription;0 -pregnancyDescription;0 -ClothingDescription;0 -InscripDesc;0 -clothingCorsetDescription;0 -SlaveArt;0 -SlaveSort;0 -shouldersTatDescription;0 -earDescription;0 -upperFaceDescription;0 -HairDescription;0 -earPiercingDescription;0 -nosePiercingDescription;0 -eyebrowPiercingDescription;0 -customTatDescription;0 -faceDescription;0 -mouthDescription;0 -setLocalPronouns;0 -eyeDescription;0 -brandDescription;0 -Family;0 -chastityPiercingDescription;0 -footwearDescription;0 -HairClothingDescription;0 -FlowerDesc;0 -ImageDesc;0 -waistDescription;0 -heightImplantDescription;0 -BodyguardWeapon;0 -CorsetPiercingDescription;0 -heelDescription;0 -FarmyardStatistics;0 -skinDescription;0 -Master;0 -setPlayerPronouns;0 -farmyardAssignmentFilter;0 -setAssistantPronouns;0 -OptionAbbreviateDevotion;0 -OptionAbbreviateDiet;0 -OptionAbbreviateDrugs;0 -OptionAbbreviateHormoneBalance;0 -OptionAbbreviateGenitalia;0 -OptionAbbreviatePhysicals;0 -OptionAbbreviateOrigins;0 -OptionAbbreviateRulesets;0 -OptionAbbreviateSidebar;0 -OptionAbbreviateMissing;0 -OptionAbbreviateSkills;0 -OptionAbbreviateMental;0 -OptionAbbreviateNationality;0 -OptionAbbreviateClothes;0 -OptionAbbreviateRace;0 -OptionAbbreviateRules;0 -OptionAbbreviateHealth;0 -OptionLineSeparations;0 -OptionSortBy;0 -OptionRulesAssistantMain;0 -OptionDisplayAssignments;0 -OptionSortOrder;0 -OptionSortMain;0 -OptionSummaryStats;0 -s;0 -c;0 -ss;0 -S;0 -x;0 -z;0 -say;0 -Sh;0 -# #twine tags capture;1 continue;0 for;1 +#does foreach really exist? +foreach;1 goto;0 htag;1 include;0 link;1 +nobr;1 print;0 replace;1 run;0 @@ -134,7 +28,7 @@ textbox;0 timed;1 unset;0 widget;1 -=; +=;0 # # Twine logic ### DO NOT TOUCH ### if;1