/*
* Copyright (C) 2012 Sony Mobile Communications AB
*
* This file is part of ApkAnalyser.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jerl.blockformat;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Stack;
import java.util.StringTokenizer;
public class BFReader {
private static final String BEGIN_HEADER = "\\begin{";
private static final String END_HEADER = "\\end{";
private final Stack<String> blockStack = new Stack<String>();
private final LineNumberReader reader;
public BFReader(InputStream is) {
reader = new LineNumberReader(new InputStreamReader(is));
}
public void accept(BFVisitor visitor) throws IOException, BFParseException {
String line = null;
try {
while ((line = reader.readLine()) != null) {
String lineTrim = line.trim();
if (lineTrim.startsWith("#")) {
continue;
}
else if (line.indexOf(BEGIN_HEADER) != -1) {
String blockName = getBlockNameBegin(line);
String[] args = getBlockArgumentsBegin(line);
blockStack.push(blockName);
visitor.visitBeginBlock(blockName, args);
} else if (line.indexOf(END_HEADER) != -1) {
String blockName = getBlockNameEnd(line);
String fromStack = blockStack.pop();
if (!blockName.equals(fromStack)) {
throw new BFParseException(
"ERROR: expected end of block '" + fromStack
+ "' got '" + blockName + "'. ("
+ reader.getLineNumber() + "), line='"
+ line + "'");
}
visitor.visitEndBlock(blockName);
} else if (line.indexOf("=") != -1) {
String key = getPropertyKey(line);
String value = getPropertyValue(line);
visitor.visitProperty(key, value);
}
}
} catch (Exception e) {
throw new BFParseException("ERROR: " + e.getClass().getName() + ": " + e.getMessage() + ". ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
if (blockStack.size() != 0) {
throw new BFParseException(
"ERROR: found more block begin than block end");
}
}
private String getPropertyKey(String line) throws BFParseException {
int i = line.indexOf('=');
if (i == -1) {
throw new BFParseException(
"ERROR: expecting property 'key=value'. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
return line.substring(0, i).trim();
}
private String getPropertyValue(String line) throws BFParseException {
int i = line.indexOf('=');
if (i == -1 || line.length() < i + 2) {
throw new BFParseException(
"ERROR: expecting property 'key=value'. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
return line.substring(i + 1).trim();
}
private String[] getBlockArgumentsBegin(String line)
throws BFParseException {
int startI = line.indexOf(BEGIN_HEADER);
if (startI == -1) {
throw new BFParseException("ERROR: missing block header. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
startI = line.indexOf('[', startI);
if (startI == -1) {
return new String[0];
}
int endI = line.indexOf(']', startI);
if (startI == -1) {
throw new BFParseException(
"ERROR: missing ']' at end of argument list. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
String args = line.substring(startI + 1, endI).trim();
StringTokenizer st = new StringTokenizer(args, ",");
String[] ret = new String[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
ret[i++] = st.nextToken().trim();
}
return ret;
}
private String getBlockNameBegin(String line) throws BFParseException {
int startI;
startI = line.indexOf(BEGIN_HEADER);
if (startI == -1) {
throw new BFParseException("ERROR: missing block header. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
int endI = line.indexOf('}', startI);
if (endI == -1) {
throw new BFParseException("ERROR: missing '}'. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
return line.substring(startI + BEGIN_HEADER.length(), endI).trim();
}
private String getBlockNameEnd(String line) throws BFParseException {
int startI;
startI = line.indexOf(END_HEADER);
if (startI == -1) {
throw new BFParseException("ERROR: missing block header. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
int endI = line.indexOf('}', startI);
if (endI == -1) {
throw new BFParseException("ERROR: missing '}'. ("
+ reader.getLineNumber() + "), line='" + line + "'");
}
return line.substring(startI + END_HEADER.length(), endI).trim();
}
public static void main(String[] args) throws IOException, BFParseException {
BFReader pr = new BFReader(new FileInputStream("res/ex1"));
pr.accept(new BFVisitor() {
@Override
public void visitBeginBlock(String blockName, String[] args) {
System.out.println("start block, name='" + blockName + "'");
for (int i = 0; i < args.length; i++) {
System.out.println("\t'" + args[i] + "'");
}
}
@Override
public void visitEndBlock(String blockName) {
System.out.println("end block, name='" + blockName + "'");
}
@Override
public void visitProperty(String key, String value) {
System.out.println("key='" + key + "', value='" + value + "'");
}
});
/*
* System.out.println("'"+getBlockNameBegin("\\begin{ blockname
* }[ab]")+"'");
* System.out.println("'"+getBlockNameEnd("\\end{blockname}")+"'");
* System.out.println("'"+getBlockArgumentsBegin("\\begin{ blockname
* }")+"'"); System.out.println("'"+getBlockArgumentsBegin("\\begin{
* blockname }[arg1=2, arg5=34342]")+"'");
*/
}
}