From 5bdef288372d3a6a8134479a6497c44f3b17c4dc Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 27 Apr 2016 20:54:50 +0100 Subject: Replace parboiled parser with hand-written parser --- .../styles/parsing/DocumentMatcherParser.java | 94 ++++++++++ .../internal/styles/parsing/HtmlPathParser.java | 68 +++++++ .../mammoth/internal/styles/parsing/ListVar.java | 30 ---- .../mammoth/internal/styles/parsing/Parsing.java | 21 --- .../internal/styles/parsing/StyleMapParser.java | 37 +++- .../styles/parsing/StyleMappingParser.java | 196 --------------------- .../styles/parsing/StyleMappingTokeniser.java | 112 ++++++++++++ .../mammoth/internal/styles/parsing/Token.java | 24 +++ .../internal/styles/parsing/TokenIterator.java | 57 ++++++ .../mammoth/internal/styles/parsing/TokenType.java | 20 +++ 10 files changed, 407 insertions(+), 252 deletions(-) create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/HtmlPathParser.java delete mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/ListVar.java delete mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/Parsing.java delete mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingParser.java create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/Token.java create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java create mode 100644 src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenType.java (limited to 'src/main/java') diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java new file mode 100644 index 0000000..0998f8b --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/DocumentMatcherParser.java @@ -0,0 +1,94 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +import org.zwobble.mammoth.internal.documents.NumberingLevel; +import org.zwobble.mammoth.internal.styles.HtmlPath; +import org.zwobble.mammoth.internal.styles.ParagraphMatcher; +import org.zwobble.mammoth.internal.styles.RunMatcher; +import org.zwobble.mammoth.internal.styles.StyleMapBuilder; + +import java.math.BigInteger; +import java.util.Optional; +import java.util.function.BiConsumer; + +public class DocumentMatcherParser { + public static BiConsumer parse(TokenIterator tokens) { + String identifier = tokens.nextValue(TokenType.IDENTIFIER); + switch (identifier) { + case "p": + ParagraphMatcher paragraph = parseParagraphMatcher(tokens); + return (builder, path) -> builder.mapParagraph(paragraph, path); + case "r": + RunMatcher run = parseRunMatcher(tokens); + return (builder, path) -> builder.mapRun(run, path); + case "b": + return StyleMapBuilder::bold; + case "i": + return StyleMapBuilder::italic; + case "u": + return StyleMapBuilder::underline; + case "strike": + return StyleMapBuilder::strikethrough; + default: + throw new IllegalArgumentException("Unrecognised document element: " + identifier); + } + } + + public static ParagraphMatcher parseParagraphMatcher(TokenIterator tokens) { + Optional styleId = parseStyleId(tokens); + Optional styleName = parseStyleName(tokens); + Optional numbering = parseNumbering(tokens); + return new ParagraphMatcher(styleId, styleName, numbering); + } + + public static RunMatcher parseRunMatcher(TokenIterator tokens) { + Optional styleId = parseStyleId(tokens); + Optional styleName = parseStyleName(tokens); + return new RunMatcher(styleId, styleName); + } + + private static Optional parseStyleId(TokenIterator tokens) { + if (tokens.peekTokenType() == TokenType.DOT) { + tokens.skip(); + return Optional.of(tokens.nextValue(TokenType.IDENTIFIER)); + } else { + return Optional.empty(); + } + } + + private static Optional parseStyleName(TokenIterator tokens) { + if (tokens.peekTokenType() == TokenType.OPEN_SQUARE_BRACKET) { + tokens.skip(); + tokens.skip(TokenType.IDENTIFIER, "style-name"); + tokens.skip(TokenType.EQUALS); + String value = tokens.nextValue(TokenType.STRING); + tokens.skip(TokenType.CLOSE_SQUARE_BRACKET); + return Optional.of(value.substring(1, value.length() - 1)); + } else { + return Optional.empty(); + } + } + + private static Optional parseNumbering(TokenIterator tokens) { + if (tokens.peekTokenType() == TokenType.COLON) { + tokens.skip(); + boolean isOrdered = parseListType(tokens); + tokens.skip(TokenType.OPEN_PAREN); + String level = new BigInteger(tokens.nextValue(TokenType.INTEGER)).subtract(BigInteger.ONE).toString(); + tokens.skip(TokenType.CLOSE_PAREN); + return Optional.of(new NumberingLevel(level, isOrdered)); + } else { + return Optional.empty(); + } + } + + private static boolean parseListType(TokenIterator tokens) { + String listType = tokens.nextValue(TokenType.IDENTIFIER); + if (listType.equals("ordered-list")) { + return true; + } else if (listType.equals("unordered-list")) { + return false; + } else { + throw new IllegalArgumentException("Unrecognised list type: " + listType); + } + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/HtmlPathParser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/HtmlPathParser.java new file mode 100644 index 0000000..105504c --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/HtmlPathParser.java @@ -0,0 +1,68 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +import org.zwobble.mammoth.internal.styles.HtmlPath; +import org.zwobble.mammoth.internal.styles.HtmlPathElement; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.zwobble.mammoth.internal.util.Maps.map; + +public class HtmlPathParser { + public static HtmlPath parse(TokenIterator tokens) { + List elements = new ArrayList<>(); + + if (tokens.peekTokenType() == TokenType.IDENTIFIER) { + HtmlPathElement element = parseElement(tokens); + elements.add(element); + while (tokens.peekTokenType() == TokenType.WHITESPACE && tokens.peekTokenType(1) == TokenType.GREATER_THAN) { + tokens.skip(TokenType.WHITESPACE); + tokens.skip(TokenType.GREATER_THAN); + tokens.skip(TokenType.WHITESPACE); + elements.add(parseElement(tokens)); + } + } + + return new HtmlPath(elements); + } + + private static HtmlPathElement parseElement(TokenIterator tokens) { + List tagNames = parseTagNames(tokens); + List classNames = parseClassNames(tokens); + Map attributes = classNames.isEmpty() + ? map() + : map("class", String.join(" ", classNames)); + boolean isFresh = parseIsFresh(tokens); + return new HtmlPathElement(tagNames, attributes, !isFresh); + } + + private static List parseTagNames(TokenIterator tokens) { + List tagNames = new ArrayList<>(); + tagNames.add(tokens.nextValue(TokenType.IDENTIFIER)); + while (tokens.peekTokenType() == TokenType.CHOICE) { + tokens.skip(); + tagNames.add(tokens.nextValue(TokenType.IDENTIFIER)); + } + return tagNames; + } + + private static List parseClassNames(TokenIterator tokens) { + List classNames = new ArrayList<>(); + while (tokens.peekTokenType() == TokenType.DOT) { + tokens.skip(); + classNames.add(tokens.nextValue(TokenType.IDENTIFIER)); + } + return classNames; + } + + private static boolean parseIsFresh(TokenIterator tokens) { + if (tokens.peekTokenType() == TokenType.COLON) { + tokens.skip(); + tokens.skip(TokenType.IDENTIFIER, "fresh"); + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/ListVar.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/ListVar.java deleted file mode 100644 index 0404a3a..0000000 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/ListVar.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.zwobble.mammoth.internal.styles.parsing; - - -import org.parboiled.support.Var; - -import java.util.ArrayList; -import java.util.List; - -class ListVar extends Var> { - boolean append(Var element) { - return append(element.get()); - } - - boolean append(T element) { - get().add(element); - return set(get()); - } - - @Override - public List get() { - if (isNotSet()) { - set(new ArrayList()); - } - return super.get(); - } - - public boolean isEmpty() { - return get().isEmpty(); - } -} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Parsing.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Parsing.java deleted file mode 100644 index bef3c0b..0000000 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Parsing.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.zwobble.mammoth.internal.styles.parsing; - -import org.parboiled.BaseParser; -import org.parboiled.Parboiled; -import org.parboiled.Rule; -import org.parboiled.parserunners.ReportingParseRunner; -import org.parboiled.support.ParsingResult; - -import java.util.function.Function; - -public class Parsing { - public static , V> void parse(Class parserType, Function rule, String value) { - U parser = Parboiled.createParser(parserType); - ReportingParseRunner runner = new ReportingParseRunner<>(rule.apply(parser)); - ParsingResult result = runner.run(value); - if (result.hasErrors()) { - // TODO: wrap in result - throw new RuntimeException("Parse error"); - } - } -} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMapParser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMapParser.java index d0bf2c7..9e8e8c9 100644 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMapParser.java +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMapParser.java @@ -1,10 +1,12 @@ package org.zwobble.mammoth.internal.styles.parsing; -import org.parboiled.support.Var; +import org.zwobble.mammoth.internal.styles.HtmlPath; import org.zwobble.mammoth.internal.styles.StyleMap; import org.zwobble.mammoth.internal.styles.StyleMapBuilder; import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; import static java.util.Arrays.asList; @@ -14,14 +16,14 @@ public class StyleMapParser { } public static StyleMap parseStyleMappings(List lines) { - Var styleMap = new Var<>(StyleMap.builder()); + StyleMapBuilder styleMap = StyleMap.builder(); for (String line : lines) { handleLine(styleMap, line); } - return styleMap.get().build(); + return styleMap.build(); } - private static void handleLine(Var styleMap, String line) { + private static void handleLine(StyleMapBuilder styleMap, String line) { if (line.startsWith("#")) { return; } @@ -29,6 +31,31 @@ public class StyleMapParser { if (line.isEmpty()) { return; } - Parsing.parse(StyleMappingParser.class, parser -> parser.StyleMapping(styleMap), line); + + parseStyleMapping(line).accept(styleMap); + } + + private static Consumer parseStyleMapping(String line) { + TokenIterator tokens = new TokenIterator(StyleMappingTokeniser.tokenise(line)); + + BiConsumer documentMatcher = DocumentMatcherParser.parse(tokens); + + tokens.skip(TokenType.WHITESPACE); + tokens.skip(TokenType.ARROW); + + HtmlPath htmlPath = parseHtmlPath(tokens); + + tokens.skip(TokenType.EOF); + + return styleMap -> documentMatcher.accept(styleMap, htmlPath); + } + + private static HtmlPath parseHtmlPath(TokenIterator tokens) { + if (tokens.peekTokenType() == TokenType.EOF) { + return HtmlPath.EMPTY; + } else { + tokens.skip(TokenType.WHITESPACE); + return HtmlPathParser.parse(tokens); + } } } diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingParser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingParser.java deleted file mode 100644 index c006319..0000000 --- a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingParser.java +++ /dev/null @@ -1,196 +0,0 @@ -package org.zwobble.mammoth.internal.styles.parsing; - -import org.parboiled.Action; -import org.parboiled.BaseParser; -import org.parboiled.Context; -import org.parboiled.Rule; -import org.parboiled.support.Var; -import org.zwobble.mammoth.internal.documents.NumberingLevel; -import org.zwobble.mammoth.internal.styles.*; - -import java.math.BigInteger; -import java.util.Optional; -import java.util.function.BiFunction; - -import static org.zwobble.mammoth.internal.util.Maps.map; - -public class StyleMappingParser extends BaseParser { - Rule StyleMapping(Var styleMap) { - Var> documentElementMatcher = new Var<>(); - Var path = new Var<>(); - return Sequence( - DocumentElementMatcher(documentElementMatcher), Whitespace(), "=>", Whitespace(), HtmlPath(path), EOI, - styleMap.set(documentElementMatcher.get().apply(styleMap.get(), path.get()))); - } - - Rule DocumentElementMatcher(Var> updateBuilder) { - Var paragraphMatcher = new Var<>(); - Var runMatcher = new Var<>(); - return FirstOf( - Sequence( - ParagraphMatcher(paragraphMatcher), - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set((styleMap, htmlPath) -> styleMap.mapParagraph(paragraphMatcher.get(), htmlPath)); - return true; - } - }), - Sequence( - RunMatcher(runMatcher), - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set((styleMap, htmlPath) -> styleMap.mapRun(runMatcher.get(), htmlPath)); - return true; - } - }), - Sequence( - "b", - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set(StyleMapBuilder::bold); - return true; - } - }), - Sequence( - "i", - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set(StyleMapBuilder::italic); - return true; - } - }), - Sequence( - "u", - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set(StyleMapBuilder::underline); - return true; - } - }), - Sequence( - "strike", - new Action() { - @Override - public boolean run(Context context) { - updateBuilder.set(StyleMapBuilder::strikethrough); - return true; - } - })); - } - - public Rule ParagraphMatcher(Var matcher) { - Var> styleId = new Var<>(); - Var> styleName = new Var<>(); - Var> numbering = new Var<>(); - return Sequence( - "p", StyleId(styleId), StyleName(styleName), Numbering(numbering), - matcher.set(new ParagraphMatcher(styleId.get(), styleName.get(), numbering.get()))); - } - - public Rule RunMatcher(Var matcher) { - Var> styleId = new Var<>(); - Var> styleName = new Var<>(); - return Sequence( - "r", StyleId(styleId), StyleName(styleName), - matcher.set(new RunMatcher(styleId.get(), styleName.get()))); - } - - Rule StyleId(Var> styleId) { - return Sequence(styleId.set(Optional.empty()), Optional(".", Identifier(), styleId.set(Optional.of(match())))); - } - - Rule StyleName(Var> styleName) { - Var value = new Var<>(); - return Sequence( - styleName.set(Optional.empty()), - Optional("[style-name=", SingleQuotedString(value), "]", styleName.set(Optional.of(value.get())))); - } - - Rule Numbering(Var> numbering) { - Var isOrdered = new Var<>(); - Var level = new Var<>(); - return Sequence( - numbering.set(Optional.empty()), - Optional(Sequence( - ":", NumberingType(isOrdered), "(", Number(level), ")", - numbering.set(Optional.of(new NumberingLevel(level.get().subtract(BigInteger.ONE).toString(), isOrdered.get())))))); - } - - Rule NumberingType(Var isOrdered) { - return FirstOf( - Sequence("ordered-list", isOrdered.set(true)), - Sequence("unordered-list", isOrdered.set(false))); - } - - Rule Number(Var level) { - return Sequence( - OneOrMore(CharRange('0', '9')), - level.set(new BigInteger(match()))); - } - - public Rule HtmlPath(Var htmlPath) { - ListVar elements = new ListVar<>(); - return Sequence(Optional(HtmlPathElements(elements)), htmlPath.set(new HtmlPath(elements.get()))); - } - - Rule HtmlPathElements(ListVar elements) { - Var element = new Var<>(); - return Sequence( - HtmlPathElement(element), - elements.append(element), - ZeroOrMore(Sequence(Whitespace(), Ch('>'), Whitespace(), HtmlPathElement(element), elements.append(element)))); - } - - Rule HtmlPathElement(Var element) { - ListVar tagNames = new ListVar<>(); - ListVar classNames = new ListVar<>(); - Var fresh = new Var<>(); - return Sequence( - TagNames(tagNames), - ClassNames(classNames), - Fresh(fresh), - element.set(new HtmlPathElement( - tagNames.get(), - classNames.isEmpty() ? map() : map("class", String.join(" ", classNames.get())), - !fresh.get()))); - } - - Rule TagNames(ListVar tagNames) { - return Sequence( - Identifier(), - tagNames.append(match()), - ZeroOrMore(Sequence("|", Identifier(), tagNames.append(match())))); - } - - Rule ClassNames(ListVar classNames) { - Var className = new Var<>(); - return ZeroOrMore(Sequence(ClassName(className), classNames.append(className))); - } - - Rule ClassName(Var className) { - return Sequence(".", Identifier(), className.set(match())); - } - - Rule Fresh(Var fresh) { - return Sequence(fresh.set(false), Optional(":fresh", fresh.set(true))); - } - - Rule SingleQuotedString(Var value) { - return Sequence("'", ZeroOrMore(NoneOf("\'")), value.set(match()), "'"); - } - - Rule Identifier() { - return Sequence( - FirstOf(CharRange('a', 'z'), CharRange('A', 'Z')), - ZeroOrMore(FirstOf(CharRange('a', 'z'), CharRange('A', 'Z'), CharRange('0', '9'), Ch('-'), Ch('_')))); - } - - Rule Whitespace() { - return ZeroOrMore(AnyOf(" \t")); - } -} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java new file mode 100644 index 0000000..fe36242 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/StyleMappingTokeniser.java @@ -0,0 +1,112 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +import java.util.ArrayList; +import java.util.List; + +public class StyleMappingTokeniser { + public static List tokenise(String line) { + List tokens = new ArrayList<>(); + + int index = 0; + while (index < line.length()) { + Token token = nextToken(line, index); + tokens.add(token); + index += token.getValue().length(); + } + + tokens.add(new Token(TokenType.EOF, "")); + return tokens; + } + + private static Token nextToken(String line, int startIndex) { + char nextChar = line.charAt(startIndex); + TokenType tokenType = tokenType(nextChar); + int index = 0; + if (nextChar == '=' && startIndex + 1 < line.length() && line.charAt(startIndex + 1) == '>') { + tokenType = TokenType.ARROW; + index = startIndex + 2; + } else { + index = seekEndOfToken(line, startIndex + 1, tokenType); + } + return new Token(tokenType, line.substring(startIndex, index)); + } + + private static TokenType tokenType(char nextChar) { + if (isAlphabetic(nextChar)) { + return TokenType.IDENTIFIER; + } else if (isWhitespace(nextChar)) { + return TokenType.WHITESPACE; + } else if (isNumeric(nextChar)) { + return TokenType.INTEGER; + } else { + switch (nextChar) { + case '\'': + return TokenType.STRING; + case '.': + return TokenType.DOT; + case ':': + return TokenType.COLON; + case '>': + return TokenType.GREATER_THAN; + case '=': + return TokenType.EQUALS; + case '(': + return TokenType.OPEN_PAREN; + case ')': + return TokenType.CLOSE_PAREN; + case '[': + return TokenType.OPEN_SQUARE_BRACKET; + case ']': + return TokenType.CLOSE_SQUARE_BRACKET; + case '|': + return TokenType.CHOICE; + default: + return TokenType.UNKNOWN; + } + } + } + + private static int seekEndOfToken(String line, int index, TokenType tokenType) { + switch (tokenType) { + case WHITESPACE: + while (index < line.length() && isWhitespace(line.charAt(index))) { + index += 1; + } + return index; + case IDENTIFIER: + while (index < line.length() && isIdentifierCharacter(line.charAt(index))) { + index += 1; + } + return index; + case INTEGER: + while (index < line.length() && isNumeric(line.charAt(index))) { + index += 1; + } + return index; + case STRING: + while (index < line.length() && line.charAt(index) != '\'') { + index += 1; + } + index += 1; + return index; + default: + return index; + } + } + + private static boolean isWhitespace(char c) { + return c == ' ' || c == '\t'; + } + + private static boolean isIdentifierCharacter(char c) { + return isAlphabetic(c) || isNumeric(c) || c == '-' || c == '_'; + } + + private static boolean isAlphabetic(char nextChar) { + return (nextChar >= 'a' && nextChar <= 'z') || (nextChar >= 'A' && nextChar <= 'Z'); + } + + private static boolean isNumeric(char c) { + return c >= '0' && c <= '9'; + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Token.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Token.java new file mode 100644 index 0000000..f6b771e --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/Token.java @@ -0,0 +1,24 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +public class Token { + private final TokenType tokenType; + private final String value; + + public Token(TokenType tokenType, String value) { + this.tokenType = tokenType; + this.value = value; + } + + public TokenType getTokenType() { + return tokenType; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return "Token(tokenType=" + tokenType + ", value=" + value + ")"; + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java new file mode 100644 index 0000000..df22b5d --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenIterator.java @@ -0,0 +1,57 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +import java.util.List; + +public class TokenIterator { + private final List tokens; + private int index; + + public TokenIterator(List tokens) { + this.tokens = tokens; + this.index = 0; + } + + public TokenType peekTokenType() { + return tokens.get(index).getTokenType(); + } + + public TokenType peekTokenType(int count) { + return tokens.get(index + count).getTokenType(); + } + + public String nextValue(TokenType type) { + Token token = tokens.get(index); + if (token.getTokenType() == type) { + index += 1; + return token.getValue(); + } else { + throw unexpectedTokenType(type, token.getTokenType()); + } + } + + public void skip() { + index += 1; + } + + public void skip(TokenType tokenType) { + if (peekTokenType() != tokenType) { + throw unexpectedTokenType(tokenType, peekTokenType()); + } + index += 1; + } + + public void skip(TokenType tokenType, String tokenValue) { + if (peekTokenType() != tokenType) { + throw unexpectedTokenType(tokenType, peekTokenType()); + } + String actualValue = tokens.get(index).getValue(); + if (!actualValue.equals(tokenValue)) { + throw new IllegalArgumentException("expected " + tokenType + " token with value " + tokenValue + " but value was " + actualValue); + } + index += 1; + } + + private IllegalArgumentException unexpectedTokenType(TokenType expected, TokenType actual) { + return new IllegalArgumentException("expected token of type " + expected + " but was of type " + actual); + } +} diff --git a/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenType.java b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenType.java new file mode 100644 index 0000000..c9cc9a4 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/internal/styles/parsing/TokenType.java @@ -0,0 +1,20 @@ +package org.zwobble.mammoth.internal.styles.parsing; + +public enum TokenType { + WHITESPACE, + IDENTIFIER, + DOT, + COLON, + GREATER_THAN, + ARROW, + EQUALS, + OPEN_PAREN, + CLOSE_PAREN, + OPEN_SQUARE_BRACKET, + CLOSE_SQUARE_BRACKET, + STRING, + INTEGER, + CHOICE, + EOF, + UNKNOWN +} -- cgit v1.2.3