/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
* LaTeXDraw is distributed without any warranty; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package net.sf.latexdraw.parsers;
import java.util.Objects;
/**
* Aan abstract parser for parsing code.
* @author Arnaud BLOUIN
*/
public abstract class CodeParser implements Parser {
/** The token for the end of the code. */
public static final int EOC = -1;
/**
* Defines a core level of the code parser that can be share with others
* code parser.
* @author Arnaud Blouin
*/
protected static class Code {
/** The code to parser. */
protected String code;
/** The current position of the character to read. */
protected int position;
/** The current line number. */
protected int linePosition;
/**
* Creates and initialises a core code.
* @param c The code to parse.
* @throws IllegalArgumentException If the given code is null.
*/
protected Code(final String c) {
super();
code = Objects.requireNonNull(c);
position = 0;
linePosition = 1;
}
}
/** The core level of the parser that contains the code to parse,...
* It can be shared with others code parsers. */
private Code codeCore;
/**
* Creates and initialises the code parser.
* @param code The code to parse.
* @throws IllegalArgumentException If the given code is null.
*/
protected CodeParser(final String code) {
super();
if(code==null)
throw new IllegalArgumentException();
codeCore = new Code(code);
}
/**
* Reinitialises the parser.
* @since 2.0.2
*/
public void initialise() {
codeCore.position = 0;
codeCore.linePosition = 1;
}
/**
* @return the code.
* @since 2.0.2
*/
public String getCode() {
return codeCore.code;
}
/**
* @param code the code to set. It re-initialises the parser.
* @since 2.0.2
*/
public void setCode(final String code) {
if(code!=null) {
this.codeCore.code = code;
initialise();
}
}
/**
* Reads the next char and returns it.
* @return the next read character or EOC if the end of the path is reached.
* @since 2.0.2
*/
public int nextChar() {
codeCore.position++;
return getChar();
}
/**
* The character at the given position.
* @param pos The position of the wanted character.
* @return The character or EOC.
* @since 2.0.3
*/
public int getCharAt(final int pos) {
if(pos>=codeCore.code.length() || pos<0)
return EOC;
return codeCore.code.charAt(pos);
}
/**
* @return the current character or EOC if the end of the path is reached.
* @since 2.0.2
*/
public int getChar() {
if(codeCore.position>=codeCore.code.length())
return EOC;
return codeCore.code.charAt(codeCore.position);
}
/**
* @return True if the end of the code is reached.
* @since 2.0.2
*/
public boolean isEOC() {
return getChar()==EOC;
}
/**
* @return the position.
* @since 2.0.2
*/
public int getPosition() {
return codeCore.position;
}
/**
* @return the line position.
* @since 2.0.2
*/
public int getLinePosition() {
return codeCore.linePosition;
}
/**
* Skips the comment.
* @return The read comment.
* @since 2.0.2
*/
public abstract String skipComment();
/**
* Skips the useless characters.
* @since 2.0.2
*/
public abstract void skipWSP();
/**
* Skips both comments and ignorable characters.
* @since 2.0.2
*/
public void skipWSPComments() {
int pos;
do {
pos = codeCore.position;
skipWSP();
skipComment();
}
while(pos!=codeCore.position && !isEOC());
}
/**
* @return True if the current position points to a comment token.
* @since 2.0.3
*/
public abstract boolean isComment();
/**
* @return True if the current character is a whitespace/ignorable character.
* @since 2.0.2
*/
public abstract boolean isWSP();
/**
* @return True if the current character is EOL.
* For the EOL CR+LF, the next character (LF) is read.
* @since 2.0.2
*/
public boolean isEOL() {
final int c = getChar();
final boolean eol;
if(c=='\r') {
eol = true;
if(nextChar()!='\n')
codeCore.position--;
}
else
eol = c=='\n';
return eol;
}
/**
* @param position the position to set.
* @since 2.0.2
*/
public void setPosition(final int position) {
if(position>=0)
codeCore.position = position;
}
/**
* @param linePosition the line position to set. Must be greater than 0.
* @since 2.0.2
*/
public void setLinePosition(final int linePosition) {
if(linePosition>=1)
codeCore.linePosition = linePosition;
}
}