package org.watertemplate.interpreter.parser; import org.watertemplate.interpreter.parser.exception.IncorrectLocationForToken; import java.util.function.Function; import java.util.regex.Pattern; enum Terminal implements GrammarSymbol { IF(Keywords.IF::startsWith, Keywords.IF::equals), IN(Keywords.IN::startsWith, Keywords.IN::equals), FOR(Keywords.FOR::startsWith, Keywords.FOR::equals), ELSE(Keywords.ELSE::startsWith, Keywords.ELSE::equals), END_OF_BLOCK(Keywords.END_OF_BLOCK::startsWith, Keywords.END_OF_BLOCK::equals), ACCESSOR(Keywords.ACCESSOR::equals), COLON(Keywords.COLON::equals), WAVE(Keywords.WAVE::equals), BLANK(s -> s.trim().isEmpty()), PROPERTY_KEY(Terminal::propertyKeyPatternMatches) { @Override public AbstractSyntaxTree buildAbstractSyntaxTree(final Token token) { return new AbstractSyntaxTree.Id(token.getValue()); } }, TEXT(s -> s.length() == 1 || (!s.endsWith("\0") && !s.endsWith(Keywords.COLON) && !s.endsWith(Keywords.WAVE))) { @Override public AbstractSyntaxTree buildAbstractSyntaxTree(final Token token) { return new AbstractSyntaxTree.Text(token.getValue()); } }, END_OF_INPUT("\0"::equals); // private final static Pattern PROPERTY_KEY_PATTERN = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$"); private final Function<String, Boolean> isCandidate; private final Function<String, Boolean> isAcceptable; Terminal(final Function<String, Boolean> isCandidate) { this(isCandidate, isCandidate); } Terminal(final Function<String, Boolean> isCandidate, final Function<String, Boolean> isAcceptable) { this.isCandidate = isCandidate; this.isAcceptable = isAcceptable; } public final Boolean isCandidateFrom(final String s) { return isCandidate.apply(s); } public final Boolean isAcceptableFrom(final String s) { return isAcceptable.apply(s); } // private static Boolean propertyKeyPatternMatches(final String s) { return PROPERTY_KEY_PATTERN.matcher(s).matches(); } @Override public final AbstractSyntaxTree buildAbstractSyntaxTree(final TokenStream tokenStream) { Token current = tokenStream.current(); if (!current.canBe(this)) { throw new IncorrectLocationForToken(this, current); } tokenStream.shift(); return buildAbstractSyntaxTree(current); } AbstractSyntaxTree buildAbstractSyntaxTree(final Token current) { return AbstractSyntaxTree.EMPTY; } }