-
-
Notifications
You must be signed in to change notification settings - Fork 380
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adds ParsingStack data type * Add ParseStackOverflowException * Store ParsingStack in ParserInstance * Implement the parsing stack in SkriptParser Document SkriptParser#parse_i a bit better * Improve robustness of ParsingStack Add more operations to ParsingStack * Add usage note to ParsingStack * Add modification notice to ParserInstance#getParsingStack * Switch from Stack class to LinkedList class Add notice on iteration order * Change brackets of ignored catch block Co-authored-by: Patrick Miller <apickledwalrus@gmail.com> * Review response, slight documentation changes, variable rename, formatting changes * Update src/main/java/ch/njol/skript/lang/parser/ParsingStack.java Co-authored-by: Kiip <25848425+kiip1@users.noreply.github.com> * Add `@param` tags to method Javadocs for completeness sake Co-authored-by: LimeGlass <16087552+TheLimeGlass@users.noreply.github.com> * Forgot import because of GH suggested change commit * Fix newer merge changes. --------- Co-authored-by: TPGamesNL <pet.teun.03@gmail.com> Co-authored-by: TPGamesNL <29547183+TPGamesNL@users.noreply.github.com> Co-authored-by: Patrick Miller <apickledwalrus@gmail.com> Co-authored-by: Kiip <25848425+kiip1@users.noreply.github.com> Co-authored-by: LimeGlass <16087552+TheLimeGlass@users.noreply.github.com>
- Loading branch information
1 parent
2f2f7fc
commit e1565dc
Showing
4 changed files
with
258 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
src/main/java/ch/njol/skript/lang/parser/ParseStackOverflowException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package ch.njol.skript.lang.parser; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.PrintStream; | ||
|
||
/** | ||
* An exception noting that a {@link StackOverflowError} has occurred | ||
* during Skript parsing. Contains information about the {@link ParsingStack} | ||
* from when the stack overflow occurred. | ||
*/ | ||
public class ParseStackOverflowException extends RuntimeException { | ||
|
||
protected final ParsingStack parsingStack; | ||
|
||
public ParseStackOverflowException(StackOverflowError cause, ParsingStack parsingStack) { | ||
super(createMessage(parsingStack), cause); | ||
this.parsingStack = parsingStack; | ||
} | ||
|
||
/** | ||
* Creates the exception message from the given {@link ParsingStack}. | ||
*/ | ||
private static String createMessage(ParsingStack stack) { | ||
ByteArrayOutputStream stream = new ByteArrayOutputStream(); | ||
|
||
PrintStream printStream = new PrintStream(stream); | ||
stack.print(printStream); | ||
|
||
return stream.toString(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
src/main/java/ch/njol/skript/lang/parser/ParsingStack.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
package ch.njol.skript.lang.parser; | ||
|
||
import ch.njol.skript.lang.Expression; | ||
import ch.njol.skript.lang.SkriptParser; | ||
import ch.njol.skript.lang.SyntaxElement; | ||
import ch.njol.skript.lang.SyntaxElementInfo; | ||
import ch.njol.util.Kleenean; | ||
|
||
import java.io.PrintStream; | ||
import java.util.Collections; | ||
import java.util.Iterator; | ||
import java.util.LinkedList; | ||
|
||
/** | ||
* A stack that keeps track of what Skript is currently parsing. | ||
* <p> | ||
* When accessing the stack from within | ||
* {@link SyntaxElement#init(Expression[], int, Kleenean, SkriptParser.ParseResult)}, | ||
* the stack element corresponding to that {@link SyntaxElement} is <b>not</b> | ||
* on the parsing stack. | ||
*/ | ||
public class ParsingStack implements Iterable<ParsingStack.Element> { | ||
|
||
private final LinkedList<Element> stack; | ||
|
||
/** | ||
* Creates an empty parsing stack. | ||
*/ | ||
public ParsingStack() { | ||
this.stack = new LinkedList<>(); | ||
} | ||
|
||
/** | ||
* Creates a parsing stack containing all elements | ||
* of another given parsing stack. | ||
*/ | ||
public ParsingStack(ParsingStack parsingStack) { | ||
this.stack = new LinkedList<>(parsingStack.stack); | ||
} | ||
|
||
/** | ||
* Removes and returns the top element of this stack. | ||
* | ||
* @throws IllegalStateException if the stack is empty. | ||
*/ | ||
public Element pop() throws IllegalStateException { | ||
if (stack.isEmpty()) { | ||
throw new IllegalStateException("Stack is empty"); | ||
} | ||
|
||
return stack.pop(); | ||
} | ||
|
||
/** | ||
* Returns the element at the given index in the stack, | ||
* starting with the top element at index 0. | ||
* | ||
* @param index the index in stack. | ||
* @throws IndexOutOfBoundsException if the index is not appointed | ||
* to an element in the stack. | ||
*/ | ||
public Element peek(int index) throws IndexOutOfBoundsException { | ||
if (index < 0 || index >= size()) { | ||
throw new IndexOutOfBoundsException("Index: " + index); | ||
} | ||
|
||
return stack.get(index); | ||
} | ||
|
||
/** | ||
* Returns the top element of the stack. | ||
* Equivalent to {@code peek(0)}. | ||
* | ||
* @throws IllegalStateException if the stack is empty. | ||
*/ | ||
public Element peek() throws IllegalStateException { | ||
if (stack.isEmpty()) { | ||
throw new IllegalStateException("Stack is empty"); | ||
} | ||
|
||
return stack.peek(); | ||
} | ||
|
||
/** | ||
* Adds the given element to the top of the stack. | ||
*/ | ||
public void push(Element element) { | ||
stack.push(element); | ||
} | ||
|
||
/** | ||
* Check if this stack is empty. | ||
*/ | ||
public boolean isEmpty() { | ||
return stack.isEmpty(); | ||
} | ||
|
||
/** | ||
* Gets the size of the stack. | ||
*/ | ||
public int size() { | ||
return stack.size(); | ||
} | ||
|
||
/** | ||
* Prints this stack to the given {@link PrintStream}. | ||
* | ||
* @param printStream a {@link PrintStream} to print the stack to. | ||
*/ | ||
public void print(PrintStream printStream) { | ||
// Synchronized to assure it'll all be printed at once, | ||
// PrintStream uses synchronization on itself internally, justifying warning suppression | ||
|
||
//noinspection SynchronizationOnLocalVariableOrMethodParameter | ||
synchronized (printStream) { | ||
printStream.println("Stack:"); | ||
|
||
if (stack.isEmpty()) { | ||
printStream.println("<empty>"); | ||
} else { | ||
for (Element element : stack) { | ||
printStream.println("\t" + element.getSyntaxElementClass().getName() + | ||
" @ " + element.patternIndex()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Iterate over the stack, starting at the top. | ||
*/ | ||
@Override | ||
public Iterator<Element> iterator() { | ||
return Collections.unmodifiableList(stack).iterator(); | ||
} | ||
|
||
/** | ||
* A stack element, containing details about the syntax element it is about. | ||
*/ | ||
public record Element(SyntaxElementInfo<?> syntaxElementInfo, int patternIndex) { | ||
|
||
public Element { | ||
assert patternIndex >= 0 && patternIndex < syntaxElementInfo.getPatterns().length; | ||
} | ||
|
||
/** | ||
* Gets the raw {@link SyntaxElementInfo} of this stack element. | ||
* <p> | ||
* For ease of use, consider using other getters of this class. | ||
* | ||
* @see #getSyntaxElementClass() | ||
* @see #getPattern() | ||
*/ | ||
@Override | ||
public SyntaxElementInfo<?> syntaxElementInfo() { | ||
return syntaxElementInfo; | ||
} | ||
|
||
/** | ||
* Gets the index to the registered patterns for the syntax element | ||
* of this stack element. | ||
*/ | ||
@Override | ||
public int patternIndex() { | ||
return patternIndex; | ||
} | ||
|
||
/** | ||
* Gets the syntax element class of this stack element. | ||
*/ | ||
public Class<? extends SyntaxElement> getSyntaxElementClass() { | ||
return syntaxElementInfo.getElementClass(); | ||
} | ||
|
||
/** | ||
* Gets the pattern that was matched for this stack element. | ||
*/ | ||
public String getPattern() { | ||
return syntaxElementInfo.getPatterns()[patternIndex]; | ||
} | ||
|
||
/** | ||
* Gets all patterns registered with the syntax element | ||
* of this stack element. | ||
*/ | ||
public String[] getPatterns() { | ||
return syntaxElementInfo.getPatterns(); | ||
} | ||
|
||
} | ||
|
||
} |