ThemisAnalysisStack.java
/*
* Themis: Java Project Framework
* Copyright 2012-2026. Tony Washer
*
* 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 io.github.tonywasher.joceanus.themis.lethe.analysis;
import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
import io.github.tonywasher.joceanus.themis.exc.ThemisDataException;
import io.github.tonywasher.joceanus.themis.lethe.analysis.ThemisAnalysisScanner.ThemisAnalysisSource;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Stack of Analysis Elements.
*/
public class ThemisAnalysisStack
implements ThemisAnalysisSource {
/**
* The stack of lines.
*/
private final Deque<ThemisAnalysisElement> theStack;
/**
* Constructor.
*
* @param pStack the stack
*/
ThemisAnalysisStack(final Deque<ThemisAnalysisElement> pStack) {
theStack = pStack;
}
/**
* Constructor.
*
* @param pElement the element
*/
ThemisAnalysisStack(final ThemisAnalysisElement pElement) {
theStack = new ArrayDeque<>();
theStack.add(pElement);
}
@Override
public boolean hasLines() {
return !theStack.isEmpty();
}
@Override
public ThemisAnalysisElement popNextLine() throws OceanusException {
/* Check that there is a line to pop */
if (theStack.isEmpty()) {
throw new ThemisDataException("No more lines");
}
/* Access the first line and remove from the list */
return theStack.removeFirst();
}
@Override
public void pushLine(final ThemisAnalysisElement pLine) {
/* Insert the line at the front of the stack */
theStack.offerFirst(pLine);
}
/**
* Is the stack empty?
*
* @return true/false
*/
public boolean isEmpty() {
return theStack.isEmpty()
|| (theStack.size() == 1 && theStack.peekFirst().toString().length() == 0);
}
/**
* Obtain the last line in the stack.
*
* @return the line
*/
ThemisAnalysisElement peekLastLine() {
return theStack.peekLast();
}
/**
* Obtain the size of the stack.
*
* @return the size
*/
public int size() {
return theStack.size();
}
/**
* Strip parentheses.
*
* @return a new stack with stripped parentheses
* @throws OceanusException on error
*/
public ThemisAnalysisStack extractParentheses() throws OceanusException {
/* Extract the parenthesised block */
final ThemisAnalysisLine myLine = (ThemisAnalysisLine) popNextLine();
final ThemisAnalysisScanner myScanner = new ThemisAnalysisScanner(this);
final Deque<ThemisAnalysisElement> myParenthesised = myScanner.scanForParenthesis(myLine);
final ThemisAnalysisStack myResult = new ThemisAnalysisStack(myParenthesised);
/* Strip the parentheses */
myResult.stripStartChar(ThemisAnalysisChar.PARENTHESIS_OPEN);
myResult.stripEndChar(ThemisAnalysisChar.PARENTHESIS_CLOSE);
/* Return the result */
return myResult;
}
/**
* Strip parentheses.
*
* @return a new stack with stripped parentheses
* @throws OceanusException on error
*/
public ThemisAnalysisStack extractArray() throws OceanusException {
/* Extract the parenthesised block */
final ThemisAnalysisLine myLine = (ThemisAnalysisLine) popNextLine();
final ThemisAnalysisScanner myScanner = new ThemisAnalysisScanner(this);
final Deque<ThemisAnalysisElement> myArray = myScanner.scanForArray(myLine);
final ThemisAnalysisStack myResult = new ThemisAnalysisStack(myArray);
/* Strip the parentheses */
myResult.stripStartChar(ThemisAnalysisChar.ARRAY_OPEN);
myResult.stripEndChar(ThemisAnalysisChar.ARRAY_CLOSE);
/* Return the result */
return myResult;
}
/**
* Does the stack start with this character?
*
* @param pChar the character
* @return true/false
*/
public boolean startsWithChar(final char pChar) {
return !theStack.isEmpty()
&& ((ThemisAnalysisLine) theStack.peekFirst()).startsWithChar(pChar);
}
/**
* Strip the starting character.
*
* @param pChar the character
*/
public void stripStartChar(final char pChar) {
if (!theStack.isEmpty()) {
((ThemisAnalysisLine) theStack.peekFirst()).stripStartChar(pChar);
}
}
/**
* Strip the ending character.
*
* @param pChar the character
*/
public void stripEndChar(final char pChar) {
if (!theStack.isEmpty()) {
((ThemisAnalysisLine) theStack.peekLast()).stripEndChar(pChar);
}
}
/**
* Rebuild the stack.
*
* @param pSource the source to rebuild from
*/
public void rebuild(final Deque<ThemisAnalysisElement> pSource) {
/* Clear the existing stack */
theStack.clear();
/* Loop through the source */
for (ThemisAnalysisElement myElement : pSource) {
theStack.offerLast(myElement);
}
}
@Override
public String toString() {
return ThemisAnalysisBuilder.formatLines(theStack);
}
}