Skip to content

Instantly share code, notes, and snippets.

@abailly
Created August 14, 2013 15:09
Show Gist options
  • Save abailly/6231966 to your computer and use it in GitHub Desktop.
Save abailly/6231966 to your computer and use it in GitHub Desktop.
Tracing parser
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