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.
/** * 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
/** * Parse a token list returning a node chain. * * @author Ceki Gulcu */
public class Parser { final List<Token> tokenList; int pointer = 0; public Parser(List<Token> 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; } }