ch.qos.logback.core.subst.Parser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of virtdata-lib-realer Show documentation
Show all versions of virtdata-lib-realer Show documentation
With inspiration from other libraries
/**
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2015, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v1.0 as published by
* the Eclipse Foundation
*
* or (per the licensee's choosing)
*
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
*/
package ch.qos.logback.core.subst;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.spi.ScanException;
import java.util.List;
// E = TE|T
// = T(E|~)
// E = TEopt where Eopt = E|~
// T = LITERAL | { C } |'${' V '}'
// C = E|E :- E
// = E(':-'E|~)
// V = E|E :- E
// = E(':-'E|~)
/**
* Parse a token list returning a node chain.
*
* @author Ceki Gulcu
*/
public class Parser {
final List tokenList;
int pointer = 0;
public Parser(List tokenList) {
this.tokenList = tokenList;
}
public Node parse() throws ScanException {
if (tokenList == null || tokenList.isEmpty())
return null;
return E();
}
private Node E() throws ScanException {
Node t = T();
if (t == null) {
return null;
}
Node eOpt = Eopt();
if (eOpt != null) {
t.append(eOpt);
}
return t;
}
// Eopt = E|~
private Node Eopt() throws ScanException {
Token next = peekAtCurentToken();
if (next == null) {
return null;
} else {
return E();
}
}
// T = LITERAL | '${' V '}'
private Node T() throws ScanException {
Token t = peekAtCurentToken();
switch (t.type) {
case LITERAL:
advanceTokenPointer();
return makeNewLiteralNode(t.payload);
case CURLY_LEFT:
advanceTokenPointer();
Node innerNode = C();
Token right = peekAtCurentToken();
expectCurlyRight(right);
advanceTokenPointer();
Node curlyLeft = makeNewLiteralNode(CoreConstants.LEFT_ACCOLADE);
curlyLeft.append(innerNode);
curlyLeft.append(makeNewLiteralNode(CoreConstants.RIGHT_ACCOLADE));
return curlyLeft;
case START:
advanceTokenPointer();
Node v = V();
Token w = peekAtCurentToken();
expectCurlyRight(w);
advanceTokenPointer();
return v;
default:
return null;
}
}
private Node makeNewLiteralNode(String s) {
return new Node(Node.Type.LITERAL, s);
}
// V = E(':='E|~)
private Node V() throws ScanException {
Node e = E();
Node variable = new Node(Node.Type.VARIABLE, e);
Token t = peekAtCurentToken();
if (isDefaultToken(t)) {
advanceTokenPointer();
Node def = E();
variable.defaultPart = def;
}
return variable;
}
// C = E(':='E|~)
private Node C() throws ScanException {
Node e0 = E();
Token t = peekAtCurentToken();
if (isDefaultToken(t)) {
advanceTokenPointer();
Node literal = makeNewLiteralNode(CoreConstants.DEFAULT_VALUE_SEPARATOR);
e0.append(literal);
Node e1 = E();
e0.append(e1);
}
return e0;
}
private boolean isDefaultToken(Token t) {
return t != null && t.type == Token.Type.DEFAULT;
}
void advanceTokenPointer() {
pointer++;
}
void expectNotNull(Token t, String expected) {
if (t == null) {
throw new IllegalArgumentException("All tokens consumed but was expecting \"" + expected + "\"");
}
}
void expectCurlyRight(Token t) throws ScanException {
expectNotNull(t, "}");
if (t.type != Token.Type.CURLY_RIGHT) {
throw new ScanException("Expecting }");
}
}
Token peekAtCurentToken() {
if (pointer < tokenList.size()) {
return tokenList.get(pointer);
}
return null;
}
}