Created
August 14, 2013 15:09
-
-
Save abailly/6231966 to your computer and use it in GitHub Desktop.
Tracing parser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class Productions { | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
//~ Static fields/initializers | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
private static final Logger DEFAULT_LOGGER = Logger.getLogger(Productions.class.getName()); | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
//~ Constructors | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
private Productions() { | |
} | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
//~ Methods | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
public static <T> Parser<T> syntax(Parser<T> parser, Logger logger, String id) { | |
return new SyntacticProduction<T>(parser, logger, id); | |
} | |
@SuppressWarnings("unchecked") | |
public static Parser<?> skip(Parser<?> parser, String id) { | |
return _(new SyntacticProduction(parser, DEFAULT_LOGGER, id)); | |
} | |
public static <T> Parser<T> lexic(Parser<T> parser, String id) { | |
return new TokenProduction<T>(parser, Productions.DEFAULT_LOGGER, id); | |
} | |
public static <T> Parser<T> lexic(Parser<T> parser, Logger logger, String id) { | |
return new TokenProduction<T>(parser, logger, id); | |
} | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
//~ Inner Classes | |
//~ ---------------------------------------------------------------------------------------------------------------- | |
public abstract static class Production<T> extends Parser<T> { | |
private final Parser<T> parser; | |
private final Logger logger; | |
private final String id; | |
public Production(Parser<T> parser, String id) { | |
this(parser, DEFAULT_LOGGER, id); | |
} | |
public Production(Parser<T> parser, Logger logger, String id) { | |
this.parser = parser; | |
this.logger = logger; | |
this.id = id; | |
} | |
public Parser<T> getParser() { | |
return parser; | |
} | |
public Logger getLogger() { | |
return logger; | |
} | |
public String getId() { | |
return id; | |
} | |
abstract void before(ParseContext parseContext); | |
abstract void after(ParseContext parseContext, boolean isSuccessful); | |
@Override | |
boolean apply(ParseContext parseContext) { | |
if (shouldTrace()) { | |
before(parseContext); | |
} | |
boolean isSuccessful = parser.apply(parseContext); | |
if (shouldTrace()) { | |
after(parseContext, isSuccessful); | |
} | |
return isSuccessful; | |
} | |
private boolean shouldTrace() { | |
return logger.isLoggable(Level.FINEST); | |
} | |
} | |
static class SyntacticProduction<T> extends Production<T> { | |
public SyntacticProduction(Parser<T> parser, Logger logger, String id) { | |
super(parser, logger, id); | |
} | |
void after(ParseContext parseContext, boolean isSuccessful) { | |
getLogger().log(Level.FINEST, "parsed: {0} -> {1} (at {2})", new Object[] { getId(), isSuccessful, parseContext.at }); | |
} | |
void before(ParseContext parseContext) { | |
getLogger().log(Level.FINEST, "parsing: {0} (token: {1})", new Object[] { getId(), eofOrToken(parseContext) }); | |
} | |
private Object eofOrToken(ParseContext parseContext) { | |
return (parseContext.isEof() ? "EOF" : parseContext.getToken()); | |
} | |
} | |
static class TokenProduction<T> extends Production<T> { | |
public static final int DISPLAYABLE_TEXT_LENGTH = 10; | |
public TokenProduction(Parser<T> parser, Logger logger, String id) { | |
super(parser, logger, id); | |
} | |
@Override | |
void after(ParseContext parseContext, boolean isSuccessful) { | |
getLogger().log(Level.FINEST, "scanned: {0} -> {1} (pos: {3}, text: \"{2}\")", new Object[] { getId(), isSuccessful, nextCharacters(parseContext), parseContext.at }); | |
} | |
@Override | |
void before(ParseContext parseContext) { | |
getLogger().log(Level.FINEST, "scanning: {0} (pos: {2}, text: \"{1}\")", new Object[] { getId(), nextCharacters(parseContext), parseContext.at }); | |
} | |
private CharSequence nextCharacters(ParseContext parseContext) { | |
return parseContext.source.subSequence(parseContext.at, Math.min(DISPLAYABLE_TEXT_LENGTH, parseContext.source.length())); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment