Skip to content

Instantly share code, notes, and snippets.

@vsajip
Created December 17, 2021 20:25
Show Gist options
  • Save vsajip/080d3681bd78bd68b3dc3e1b6ce032e6 to your computer and use it in GitHub Desktop.
Save vsajip/080d3681bd78bd68b3dc3e1b6ce032e6 to your computer and use it in GitHub Desktop.
/* Generated by: JavaCC 21 Parser Generator. JSONParser.java */
package org.parsers.json;
import org.parsers.json.ast.*;
import java.util.*;
import java.util.concurrent.CancellationException;
import java.util.logging.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.parsers.json.JSONConstants.TokenType.*;
@SuppressWarnings("unused")
public class JSONParser implements JSONConstants {
private static final java.util.logging.Logger LOGGER= Logger.getLogger(JSONConstants.class.getName());
public static void setLogLevel(Level level) {
LOGGER.setLevel(level);
Logger.getGlobal().getParent().getHandlers()[0].setLevel(level);
}
static final int UNLIMITED= Integer.MAX_VALUE;
// The last token successfully "consumed"
Token lastConsumedToken= new Token();
// We start with a dummy token. REVISIT
private TokenType nextTokenType;
private Token currentLookaheadToken;
private boolean scanToEnd;
private String currentlyParsedProduction, currentLookaheadProduction;
private EnumSet<TokenType> outerFollowSet;
private boolean cancelled;
public void cancel() {
cancelled= true;
}
public boolean isCancelled() {
return cancelled;
}
/** Generated Lexer. */
public JSONLexer token_source;
public void setInputSource(String inputSource) {
token_source.setInputSource(inputSource);
}
String getInputSource() {
return token_source.getInputSource();
}
//=================================
// Generated constructors
//=================================
public JSONParser(String inputSource, CharSequence content) {
this(new JSONLexer(inputSource, content));
}
public JSONParser(CharSequence content) {
this("input", content);
}
public JSONParser(String inputSource, Path path) throws IOException {
this(inputSource, FileLineMap.stringFromBytes(Files.readAllBytes(path)));
}
public JSONParser(Path path) throws IOException {
this(path.toString(), path);
}
public JSONParser(java.io.InputStream stream) {
this(new InputStreamReader(stream));
}
public JSONParser(Reader reader) {
this(new JSONLexer("input", reader));
}
/** Constructor with user supplied Lexer. */
public JSONParser(JSONLexer lexer) {
token_source= lexer;
lastConsumedToken.setInputSource(lexer.getInputSource());
}
// If tok already has a next field set, it returns that
// Otherwise, it goes to the token_source, i.e. the Lexer.
final private Token nextToken(final Token tok) {
Token result= tok== null?null:
tok.getNext();
Token previous= null;
while (result== null) {
nextTokenType= null;
Token next= token_source.getNextToken();
previous= next;
if (!next.isUnparsed()) {
result= next;
}
else if (next instanceof InvalidToken) {
result= next.getNextToken();
}
}
if (tok!=null) tok.setNext(result);
nextTokenType= null;
return result;
}
/**
* @return the next Token off the stream. This is the same as #getToken(1)
*/
final public Token getNextToken() {
return getToken(1);
}
/**
* @param index how many tokens to look ahead
* @return the specific Token index ahead in the stream.
* If we are in a lookahead, it looks ahead from the currentLookaheadToken
* Otherwise, it is the lastConsumedToken
*/
final public Token getToken(int index) {
Token t= currentLookaheadToken== null?lastConsumedToken:
currentLookaheadToken;
for (int i= 0; i<index; i++) {
t= nextToken(t);
}
return t;
}
private final TokenType nextTokenType() {
if (nextTokenType== null) {
nextTokenType= nextToken(lastConsumedToken).getType();
}
return nextTokenType;
}
boolean activateTokenTypes(TokenType type, TokenType...types) {
boolean result= token_source.activeTokenTypes.add(type);
for (TokenType tt : types) {
result|=token_source.activeTokenTypes.add(tt);
}
if (result) {
token_source.reset(getToken(0));
nextTokenType= null;
}
return result;
}
boolean deactivateTokenTypes(TokenType type, TokenType...types) {
boolean result= token_source.activeTokenTypes.remove(type);
for (TokenType tt : types) {
result|=token_source.activeTokenTypes.remove(tt);
}
if (result) {
token_source.reset(getToken(0));
nextTokenType= null;
}
return result;
}
// JSON.javacc:65:1
final public void Array() throws ParseException {
if (trace_enabled) LOGGER.info("Entering production defined on line 65 of JSON.javacc");
if (cancelled) throw new CancellationException();
String prevProduction= currentlyParsedProduction;
this.currentlyParsedProduction= "Array";
Array Array1= null;
if (buildTree) {
Array1= new Array();
Array1.setInputSource(getInputSource());
openNodeScope(Array1);
}
ParseException parseException1= null;
int callStackSize2= parsingStack.size();
try {
if (false) throw new ParseException("Never happens!");
// Code for RegexpRef specified at:
// JSON.javacc:66:5
consumeToken(OPEN_BRACKET);
// Code for ZeroOrOne specified at:
// JSON.javacc:67:5
if (first_set$JSON_javacc$68$7.contains(nextTokenType())) {
// Code for NonTerminal specified at:
// JSON.javacc:68:7
pushOntoCallStack("Array", "JSON.javacc", 68, 7);
outerFollowSet= follow_set$JSON_javacc$68$7$;
try {
Value();
}
finally {
popCallStack();
}
// Code for ZeroOrMore specified at:
// JSON.javacc:68:14
while (true) {
if (!(nextTokenType()== COMMA)) break;
// Code for RegexpRef specified at:
// JSON.javacc:68:15
consumeToken(COMMA);
// Code for NonTerminal specified at:
// JSON.javacc:68:23
pushOntoCallStack("Array", "JSON.javacc", 68, 23);
outerFollowSet= follow_set$JSON_javacc$68$23;
try {
Value();
}
finally {
popCallStack();
}
}
}
// Code for RegexpRef specified at:
// JSON.javacc:70:5
consumeToken(CLOSE_BRACKET);
}
catch(ParseException e) {
parseException1= e;
throw e;
}
finally {
restoreCallStack(callStackSize2);
if (Array1!=null) {
if (parseException1== null) {
closeNodeScope(Array1, nodeArity()> 1);
}
else {
if (trace_enabled) LOGGER.warning("ParseException: "+parseException1.getMessage());
clearNodeScope();
}
}
this.currentlyParsedProduction= prevProduction;
}
}
static private final EnumSet<TokenType> Value_FIRST_SET= EnumSet.of(OPEN_BRACKET, OPEN_BRACE, TRUE, FALSE, NULL, STRING_LITERAL, NUMBER);
// JSON.javacc:73:1
final public void Value() throws ParseException {
if (trace_enabled) LOGGER.info("Entering production defined on line 73 of JSON.javacc");
if (cancelled) throw new CancellationException();
String prevProduction= currentlyParsedProduction;
this.currentlyParsedProduction= "Value";
// Code for ExpansionChoice specified at:
// JSON.javacc:74:5
Value Value2= null;
if (buildTree) {
Value2= new Value();
Value2.setInputSource(getInputSource());
openNodeScope(Value2);
}
ParseException parseException31= null;
int callStackSize32= parsingStack.size();
try {
if (false) throw new ParseException("Never happens!");
if (nextTokenType()== TRUE) {
// Code for RegexpRef specified at:
// JSON.javacc:74:5
consumeToken(TRUE);
}
else if (nextTokenType()== FALSE) {
// Code for RegexpRef specified at:
// JSON.javacc:76:5
consumeToken(FALSE);
}
else if (nextTokenType()== NULL) {
// Code for RegexpRef specified at:
// JSON.javacc:78:5
consumeToken(NULL);
}
else if (nextTokenType()== STRING_LITERAL) {
// Code for RegexpRef specified at:
// JSON.javacc:80:5
consumeToken(STRING_LITERAL);
}
else if (nextTokenType()== NUMBER) {
// Code for RegexpRef specified at:
// JSON.javacc:82:5
consumeToken(NUMBER);
}
else if (nextTokenType()== OPEN_BRACKET) {
// Code for NonTerminal specified at:
// JSON.javacc:84:5
pushOntoCallStack("Value", "JSON.javacc", 84, 5);
try {
Array();
}
finally {
popCallStack();
}
}
else if (nextTokenType()== OPEN_BRACE) {
// Code for NonTerminal specified at:
// JSON.javacc:86:5
pushOntoCallStack("Value", "JSON.javacc", 86, 5);
try {
JSONObject();
}
finally {
popCallStack();
}
}
else {
pushOntoCallStack("Value", "JSON.javacc", 74, 5);
throw new ParseException(this, Value_FIRST_SET, parsingStack);
}
}
catch(ParseException e) {
parseException31= e;
throw e;
}
finally {
restoreCallStack(callStackSize32);
if (Value2!=null) {
if (parseException31== null) {
closeNodeScope(Value2, nodeArity()> 1);
}
else {
if (trace_enabled) LOGGER.warning("ParseException: "+parseException31.getMessage());
clearNodeScope();
}
}
this.currentlyParsedProduction= prevProduction;
}
}
// JSON.javacc:89:1
final public void KeyValuePair() throws ParseException {
if (trace_enabled) LOGGER.info("Entering production defined on line 89 of JSON.javacc");
if (cancelled) throw new CancellationException();
String prevProduction= currentlyParsedProduction;
this.currentlyParsedProduction= "KeyValuePair";
KeyValuePair KeyValuePair3= null;
if (buildTree) {
KeyValuePair3= new KeyValuePair();
KeyValuePair3.setInputSource(getInputSource());
openNodeScope(KeyValuePair3);
}
ParseException parseException76= null;
int callStackSize77= parsingStack.size();
try {
if (false) throw new ParseException("Never happens!");
// Code for RegexpRef specified at:
// JSON.javacc:89:16
consumeToken(STRING_LITERAL);
// Code for RegexpRef specified at:
// JSON.javacc:89:33
consumeToken(COLON);
// Code for NonTerminal specified at:
// JSON.javacc:89:41
pushOntoCallStack("KeyValuePair", "JSON.javacc", 89, 41);
try {
Value();
}
finally {
popCallStack();
}
}
catch(ParseException e) {
parseException76= e;
throw e;
}
finally {
restoreCallStack(callStackSize77);
if (KeyValuePair3!=null) {
if (parseException76== null) {
closeNodeScope(KeyValuePair3, nodeArity()> 1);
}
else {
if (trace_enabled) LOGGER.warning("ParseException: "+parseException76.getMessage());
clearNodeScope();
}
}
this.currentlyParsedProduction= prevProduction;
}
}
// JSON.javacc:91:1
final public void JSONObject() throws ParseException {
if (trace_enabled) LOGGER.info("Entering production defined on line 91 of JSON.javacc");
if (cancelled) throw new CancellationException();
String prevProduction= currentlyParsedProduction;
this.currentlyParsedProduction= "JSONObject";
JSONObject JSONObject4= null;
if (buildTree) {
JSONObject4= new JSONObject();
JSONObject4.setInputSource(getInputSource());
openNodeScope(JSONObject4);
}
ParseException parseException88= null;
int callStackSize89= parsingStack.size();
try {
if (false) throw new ParseException("Never happens!");
// Code for RegexpRef specified at:
// JSON.javacc:92:5
consumeToken(OPEN_BRACE);
// Code for ZeroOrOne specified at:
// JSON.javacc:93:5
if (nextTokenType()== STRING_LITERAL) {
// Code for NonTerminal specified at:
// JSON.javacc:94:9
pushOntoCallStack("JSONObject", "JSON.javacc", 94, 9);
outerFollowSet= follow_set$JSON_javacc$94$9;
try {
KeyValuePair();
}
finally {
popCallStack();
}
// Code for ZeroOrMore specified at:
// JSON.javacc:94:22
while (true) {
if (!(nextTokenType()== COMMA)) break;
// Code for RegexpStringLiteral specified at:
// JSON.javacc:94:23
consumeToken(COMMA);
// Code for NonTerminal specified at:
// JSON.javacc:94:27
pushOntoCallStack("JSONObject", "JSON.javacc", 94, 27);
outerFollowSet= follow_set$JSON_javacc$94$27;
try {
KeyValuePair();
}
finally {
popCallStack();
}
}
}
// Code for RegexpRef specified at:
// JSON.javacc:96:5
consumeToken(CLOSE_BRACE);
}
catch(ParseException e) {
parseException88= e;
throw e;
}
finally {
restoreCallStack(callStackSize89);
if (JSONObject4!=null) {
if (parseException88== null) {
closeNodeScope(JSONObject4, nodeArity()> 1);
}
else {
if (trace_enabled) LOGGER.warning("ParseException: "+parseException88.getMessage());
clearNodeScope();
}
}
this.currentlyParsedProduction= prevProduction;
}
}
// JSON.javacc:99:1
final public void Root() throws ParseException {
if (trace_enabled) LOGGER.info("Entering production defined on line 99 of JSON.javacc");
if (cancelled) throw new CancellationException();
String prevProduction= currentlyParsedProduction;
this.currentlyParsedProduction= "Root";
Root Root5= null;
if (buildTree) {
Root5= new Root();
Root5.setInputSource(getInputSource());
openNodeScope(Root5);
}
ParseException parseException118= null;
int callStackSize119= parsingStack.size();
try {
if (false) throw new ParseException("Never happens!");
// Code for NonTerminal specified at:
// JSON.javacc:99:8
pushOntoCallStack("Root", "JSON.javacc", 99, 8);
outerFollowSet= follow_set$JSON_javacc$99$8;
try {
Value();
}
finally {
popCallStack();
}
// Code for EndOfFile specified at:
// JSON.javacc:99:15
consumeToken(EOF);
}
catch(ParseException e) {
parseException118= e;
throw e;
}
finally {
restoreCallStack(callStackSize119);
if (Root5!=null) {
if (parseException118== null) {
closeNodeScope(Root5, nodeArity()> 1);
}
else {
if (trace_enabled) LOGGER.warning("ParseException: "+parseException118.getMessage());
clearNodeScope();
}
}
this.currentlyParsedProduction= prevProduction;
}
}
static private final EnumSet<TokenType> first_set$JSON_javacc$68$7= EnumSet.of(OPEN_BRACKET, OPEN_BRACE, TRUE, FALSE, NULL, STRING_LITERAL, NUMBER);
static private EnumSet<TokenType> follow_set$JSON_javacc$66$5_init() {
return EnumSet.of(OPEN_BRACKET, CLOSE_BRACKET, OPEN_BRACE, TRUE, FALSE, NULL, STRING_LITERAL, NUMBER);
}
static private final EnumSet<TokenType> follow_set$JSON_javacc$68$7$= EnumSet.of(COMMA, CLOSE_BRACKET);
static private final EnumSet<TokenType> follow_set$JSON_javacc$68$23= EnumSet.of(COMMA, CLOSE_BRACKET);
static private final EnumSet<TokenType> follow_set$JSON_javacc$94$9= EnumSet.of(COMMA, CLOSE_BRACE);
static private final EnumSet<TokenType> follow_set$JSON_javacc$94$27= EnumSet.of(COMMA, CLOSE_BRACE);
static private final EnumSet<TokenType> follow_set$JSON_javacc$99$8= EnumSet.of(EOF);
private boolean trace_enabled= false;
public void setTracingEnabled(boolean tracingEnabled) {
trace_enabled= tracingEnabled;
}
/**
* @deprecated Use #setTracingEnabled
*/
@Deprecated public void enable_tracing() {
setTracingEnabled(true);
}
/**
* @deprecated Use #setTracingEnabled
*/
@Deprecated public void disable_tracing() {
setTracingEnabled(false);
}
ArrayList<NonTerminalCall> parsingStack= new ArrayList<> ();
private ArrayList<NonTerminalCall> lookaheadStack= new ArrayList<> ();
/**
* Inner class that represents entering a grammar production
*/
class NonTerminalCall {
final String sourceFile;
final String productionName;
final int line, column;
// We actually only use this when we're working with the LookaheadStack
final boolean scanToEnd;
final EnumSet<TokenType> followSet;
NonTerminalCall(String sourceFile, String productionName, int line, int column) {
this.sourceFile= sourceFile;
this.productionName= productionName;
this.line= line;
this.column= column;
this.scanToEnd= JSONParser.this.scanToEnd;
this.followSet= JSONParser.this.outerFollowSet;
}
StackTraceElement createStackTraceElement() {
return new StackTraceElement("JSONParser", productionName, sourceFile, line);
}
void dump(PrintStream ps) {
ps.println(productionName+":"+line+":"+column);
}
}
private final void pushOntoCallStack(String methodName, String fileName, int line, int column) {
parsingStack.add(new NonTerminalCall(fileName, methodName, line, column));
}
private final void popCallStack() {
NonTerminalCall ntc= parsingStack.remove(parsingStack.size()-1);
this.currentlyParsedProduction= ntc.productionName;
this.outerFollowSet= ntc.followSet;
}
private final void restoreCallStack(int prevSize) {
while (parsingStack.size()> prevSize) {
popCallStack();
}
}
void dumpLookaheadStack(PrintStream ps) {
ListIterator<NonTerminalCall> it= lookaheadStack.listIterator(lookaheadStack.size());
while (it.hasPrevious()) {
it.previous().dump(ps);
}
}
void dumpCallStack(PrintStream ps) {
ListIterator<NonTerminalCall> it= parsingStack.listIterator(parsingStack.size());
while (it.hasPrevious()) {
it.previous().dump(ps);
}
}
void dumpLookaheadCallStack(PrintStream ps) {
ps.println("Current Parser Production is: "+currentlyParsedProduction);
ps.println("Current Lookahead Production is: "+currentLookaheadProduction);
ps.println("---Lookahead Stack---");
dumpLookaheadStack(ps);
ps.println("---Call Stack---");
dumpCallStack(ps);
}
public boolean isParserTolerant() {
return false;
}
public void setParserTolerant(boolean tolerantParsing) {
if (tolerantParsing) {
throw new UnsupportedOperationException("This parser was not built with that feature!");
}
}
private Token consumeToken(TokenType expectedType) throws ParseException {
Token oldToken= lastConsumedToken;
Token nextToken= nextToken(lastConsumedToken);
if (nextToken.getType()!=expectedType) {
nextToken= handleUnexpectedTokenType(expectedType, nextToken);
}
this.lastConsumedToken= nextToken;
this.nextTokenType= null;
if (buildTree&&tokensAreNodes) {
pushNode(lastConsumedToken);
}
if (trace_enabled) LOGGER.info("Consumed token of type "+lastConsumedToken.getType()+" from "+lastConsumedToken.getLocation());
return lastConsumedToken;
}
private Token handleUnexpectedTokenType(TokenType expectedType, Token nextToken) throws ParseException {
throw new ParseException(nextToken, EnumSet.of(expectedType), parsingStack);
}
private class ParseState {
Token lastConsumed;
ArrayList<NonTerminalCall> parsingStack;
NodeScope nodeScope;
ParseState() {
this.lastConsumed= JSONParser.this.lastConsumedToken;
@SuppressWarnings("unchecked")
ArrayList<NonTerminalCall> parsingStack= (ArrayList<NonTerminalCall> ) JSONParser.this.parsingStack.clone();
this.parsingStack= parsingStack;
this.nodeScope= (NodeScope) currentNodeScope.clone();
}
}
private boolean buildTree= true;
private boolean tokensAreNodes= true;
private boolean unparsedTokensAreNodes= false;
public boolean isTreeBuildingEnabled() {
return buildTree;
}
public void setUnparsedTokensAreNodes(boolean unparsedTokensAreNodes) {
this.unparsedTokensAreNodes= unparsedTokensAreNodes;
}
public void setTokensAreNodes(boolean tokensAreNodes) {
this.tokensAreNodes= tokensAreNodes;
}
NodeScope currentNodeScope= new NodeScope();
/**
* @return the root node of the AST. It only makes sense to call
* this after a successful parse.
*/
public Node rootNode() {
return currentNodeScope.rootNode();
}
/**
* push a node onto the top of the node stack
* @param n the node to push
*/
public void pushNode(Node n) {
currentNodeScope.add(n);
}
/**
* @return the node on the top of the stack, and remove it from the
* stack.
*/
public Node popNode() {
return currentNodeScope.pop();
}
/**
* @return the node currently on the top of the tree-building stack.
*/
public Node peekNode() {
return currentNodeScope.peek();
}
/**
* Puts the node on the top of the stack. However, unlike pushNode()
* it replaces the node that is currently on the top of the stack.
* This is effectively equivalent to popNode() followed by pushNode(n)
* @param n the node to poke
*/
public void pokeNode(Node n) {
currentNodeScope.poke(n);
}
/**
* @return the number of Nodes on the tree-building stack in the current node
* scope.
*/
public int nodeArity() {
return currentNodeScope.size();
}
private void clearNodeScope() {
currentNodeScope.clear();
}
private void openNodeScope(Node n) {
new NodeScope();
if (n!=null) {
Token next= nextToken(lastConsumedToken);
n.setBeginLine(next.getBeginLine());
n.setBeginColumn(next.getBeginColumn());
n.setInputSource(this.getInputSource());
n.open();
}
if (trace_enabled&&n!=null) LOGGER.info("Opened node scope for node of type: "+n.getClass().getName());
if (trace_enabled) LOGGER.info("Scope nesting level is "+currentNodeScope.nestingLevel());
}
/* A definite node is constructed from a specified number of
* children. That number of nodes are popped from the stack and
* made the children of the definite node. Then the definite node
* is pushed on to the stack.
*/
private void closeNodeScope(Node n, int num) {
n.setEndLine(lastConsumedToken.getEndLine());
n.setEndColumn(lastConsumedToken.getEndColumn());
if (trace_enabled) LOGGER.info("Closing node scope for node of type: "+n.getClass().getName()+", popping "+num+" nodes off the stack.");
currentNodeScope.close();
ArrayList<Node> nodes= new ArrayList<Node> ();
for (int i= 0; i<num; i++) {
nodes.add(popNode());
}
Collections.reverse(nodes);
for (Node child : nodes) {
// FIXME deal with the UNPARSED_TOKENS_ARE_NODES case
n.addChild(child);
}
n.close();
pushNode(n);
}
/**
* A conditional node is constructed if the condition is true. All
* the nodes that have been pushed since the node was opened are
* made children of the conditional node, which is then pushed
* on to the stack. If the condition is false the node is not
* constructed and they are left on the stack.
*/
private void closeNodeScope(Node n, boolean condition) {
if (n!=null&&condition) {
n.setEndColumn(lastConsumedToken.getEndColumn());
n.setEndLine(lastConsumedToken.getEndLine());
if (trace_enabled) LOGGER.finer("Closing node scope for node of type: "+n.getClass().getName()+", popping "+nodeArity()+" nodes off the stack.");
int a= nodeArity();
currentNodeScope.close();
ArrayList<Node> nodes= new ArrayList<Node> ();
while (a--> 0) {
nodes.add(popNode());
}
Collections.reverse(nodes);
for (Node child : nodes) {
if (unparsedTokensAreNodes&&child instanceof Token) {
Token tok= (Token) child;
while (tok.getPreviousToken()!=null&&tok.getPreviousToken().isUnparsed()) {
tok= tok.getPreviousToken();
}
while (tok.isUnparsed()) {
n.addChild(tok);
tok= tok.getNextToken();
}
}
n.addChild(child);
}
n.close();
if (trace_enabled) {
LOGGER.info("Closing node scope for node of type: "+n.getClass().getName()+", leaving "+nodeArity()+" nodes on the stack.");
LOGGER.info("Nesting level is : "+currentNodeScope.nestingLevel());
}
pushNode(n);
if (trace_enabled) {
LOGGER.info("Closed node scope for node of type: "+n.getClass().getName()+", there are now "+nodeArity()+" nodes on the stack.");
LOGGER.info("Nesting level is : "+currentNodeScope.nestingLevel());
}
}
else {
currentNodeScope.close();
if (trace_enabled&&n!=null) {
LOGGER.info("Closed node scope for node of type: "+n.getClass().getName()+", leaving "+nodeArity()+" nodes on the stack.");
LOGGER.info("Nesting level is : "+currentNodeScope.nestingLevel());
}
}
}
public boolean getBuildTree() {
return buildTree;
}
public void setBuildTree(boolean buildTree) {
this.buildTree= buildTree;
}
/**
* Just a kludge so that existing jjtree-based code that uses
* parser.jjtree.foo can work without change.
*/
JSONParser jjtree= this;
@SuppressWarnings("serial")
class NodeScope extends ArrayList<Node> {
NodeScope parentScope;
NodeScope() {
this.parentScope= JSONParser.this.currentNodeScope;
JSONParser.this.currentNodeScope= this;
}
boolean isRootScope() {
return parentScope== null;
}
Node rootNode() {
NodeScope ns= this;
while (ns.parentScope!=null) {
ns= ns.parentScope;
}
return ns.isEmpty()?null:
ns.get(0);
}
Node peek() {
return isEmpty()?parentScope.peek():
get(size()-1);
}
Node pop() {
return isEmpty()?parentScope.pop():
remove(size()-1);
}
void poke(Node n) {
if (isEmpty()) {
parentScope.poke(n);
}
else {
set(size()-1, n);
}
}
void close() {
parentScope.addAll(this);
JSONParser.this.currentNodeScope= parentScope;
}
int nestingLevel() {
int result= 0;
NodeScope parent= this;
while (parent.parentScope!=null) {
result++;
parent= parent.parentScope;
}
return result;
}
public NodeScope clone() {
NodeScope clone= (NodeScope) super.clone();
if (parentScope!=null) {
clone.parentScope= (NodeScope) parentScope.clone();
}
return clone;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment