blob: bb3519868b16dbc99327961a16825a27c3caf8e1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2018 IBM Corporation and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
/*nlsXXX*/
package org.eclipse.wst.json.core.internal.parser;
import java.io.CharArrayReader;
import java.io.IOException;
import java.util.Stack;
import org.eclipse.wst.json.core.internal.parser.regions.JSONTextRegionFactory;
import org.eclipse.wst.json.core.regions.JSONRegionContexts;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
%%
%public
%class JSONTokenizer
%extends AbstractJSONTokenizer
%function primGetNextToken
%type String
%char
%unicode
%caseless
//%debug
%pack
%{
private final static String UNDEFINED = "undefined";
private String fBufferedContext = null;
private int fBufferedStart;
// private int fBufferedTextLength;
private int fBufferedLength;
// private StringBuilder fBufferedText = null;
private JSONTextRegionFactory fRegionFactory = JSONTextRegionFactory.getInstance();
private int fInitialState = YYINITIAL;
public final static int BUFFER_SIZE_NORMAL = 16384;
public final static int BUFFER_SIZE_SMALL = 256;
private int fInitialBufferSize = BUFFER_SIZE_NORMAL;
public void setInitialState(int state) {
fInitialState = state;
}
public void setInitialBufferSize(int size) {
fInitialBufferSize = size;
}
@Override
protected void setJSONArrayState() {
yybegin(ST_JSON_ARRAY);
}
@Override
protected void setJSONObjectState() {
yybegin(ST_JSON_OBJECT);
}
@Override
protected void setJSONValueState() {
yybegin(ST_JSON_VALUE);
}
/* user method */
public final ITextRegion getNextToken() throws IOException {
String context;
String nextTokenType;
boolean spaceFollows;
// StringBuilder text;
int start;
int textLength;
int length;
if (fBufferedContext != null) {
context = fBufferedContext;
// text = fBufferedText;
start = fBufferedStart;
textLength = length = fBufferedLength;
fBufferedContext = null;
} else {
context = primGetNextToken();
// text = new StringBuilder(yytext());
start = yychar;
textLength = length = yylength();
}
if (context != null) {
if (context == UNDEFINED) {
// undef -> concatenate undef's
nextTokenType = primGetNextToken();
while (nextTokenType == UNDEFINED) {
// text.append(yytext());
textLength += yylength();
length = textLength;
nextTokenType = primGetNextToken();
}
fBufferedContext = nextTokenType;
// fBufferedText = new StringBuilder(yytext());
fBufferedStart = yychar;
fBufferedLength = yylength();
} else {
nextTokenType = null;
spaceFollows = false;
/*if (JSONRegionUtil.isDeclarationValueType(context)) { // declaration value can contain VALUE_S
nextTokenType = primGetNextToken();
spaceFollows = (nextTokenType == JSON_DECLARATION_VALUE_S);
} else
*/
//if (canContainSpace(context)) {
nextTokenType = primGetNextToken();
//spaceFollows = (nextTokenType == JSON_S);
//}
if (nextTokenType != null) { // nextToken is retrieved
if (spaceFollows && (context != JSON_COMMENT)) {
// next is space -> append
// text.append(yytext());
length += yylength();
} else {
// next is NOT space -> push this for next time, return itself
fBufferedContext = nextTokenType;
// fBufferedText = new StringBuilder(yytext());
fBufferedStart = yychar;
fBufferedLength = yylength();
}
}
}
}
if (context != null) {
if (context == UNDEFINED) {
context = JSON_UNKNOWN;
}
return fRegionFactory.createRegion(context, start, textLength, length);
} else {
return null;
}
}
/* user method */
/* for standalone use */
/*public final List parseText() throws IOException {
List tokens = new ArrayList();
JSONTextToken token;
for (String kind = primGetNextToken(); kind != null; kind = primGetNextToken()) {
token = new JSONTextToken();
token.kind = kind;
token.start = yychar;
token.length = yylength();
token.image = yytext();
tokens.add(token);
}
return tokens;
}*/
/* user method */
/*private boolean canContainSpace(String type) {
if (type == JSON_DELIMITER || type == JSON_RBRACE || type == JSON_DECLARATION_DELIMITER) {
return false;
} else {
return true;
}
}*/
/* user method */
public final int getOffset() {
return yychar;
}
/* user method */
public final boolean isEOF() {
return zzAtEOF;
}
/* user method */
public void reset(char[] charArray) {
reset(new CharArrayReader(charArray), 0);
}
/* user method */
public final void reset(java.io.Reader in, int newOffset) {
/** the input device */
zzReader = in;
/** the current state of the DFA */
zzState = 0;
/** the current lexical state */
zzLexicalState = fInitialState; //YYINITIAL;
/** this buffer contains the current text to be matched and is
the source of the yytext() string */
if (zzBuffer.length != fInitialBufferSize) {
zzBuffer = new char[fInitialBufferSize];
}
java.util.Arrays.fill(zzBuffer, (char)0);
/** the textposition at the last accepting state */
zzMarkedPos = 0;
/** the textposition at the last state to be included in yytext */
// yy_pushbackPos = 0;
/** the current text position in the buffer */
zzCurrentPos = 0;
/** startRead marks the beginning of the yytext() string in the buffer */
zzStartRead = 0;
/** endRead marks the last character in the buffer, that has been read
from input */
zzEndRead = 0;
/** number of newlines encountered up to the start of the matched text */
yyline = 0;
/** the number of characters up to the start of the matched text */
yychar = 0;
/**
* the number of characters from the last newline up to the start of the
* matched text
*/
// yycolumn = 0;
/**
* yy_atBOL == true <=> the scanner is currently at the beginning of a line
*/
// yy_atBOL = false;
/** zzAtEOF == true <=> the scanner has returned a value for EOF */
zzAtEOF = false;
/* user variables */
// fUndefined.delete(0, fUndefined.length());
jsonContextStack.clear();
}
/* user method */
public JSONTokenizer() {
super();
}
/**
* Added to workaround stricter compilation options without creating
* an alternate skeleton file
*/
void _usePrivates() {
System.out.print(yycolumn);
System.out.print(yyline);
System.out.print(Boolean.toString(zzAtBOL));
}
%}
%state ST_JSON_OBJECT
%state ST_JSON_ARRAY
%state ST_JSON_OBJECT_COLON
%state ST_JSON_VALUE
%state ST_JSON_COMMENT
WHITE_SPACE_CHAR=[\n\r\ \t\b\012]
NUMBER_TEXT=-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?
S = [\x20\x09\x0D\x0A]+
h = [0-9a-f]
nonascii = [\u0080-\uffff]
unicode = \\{h}{1,6}[ \t\r\n\f]?
escape = {unicode}|\\[ -~\u0080-\uffff]
nmstart = [_a-zA-Z]|{nonascii}|{escape}
nmchar = [_a-zA-Z0-9-]|{nonascii}|{escape}
string1 = \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\"
string2 = \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\'
ident = -?{nmstart}{nmchar}*
value_ident = -?{nmstart}"."?({nmchar}+"."?)*
name = {nmchar}+
num = [+-]?([0-9]+|[0-9]*"."[0-9]*)
string = {string1}|{string2}
nl = \n|\r\n|\r|\f
Key = {string1}
startObject = \{
endObject = \}
startArray = \[
endArray = \]
comma = \,
%%
\/\*[^*]*\*+([^/*][^*]*\*+)*\/ { return JSON_COMMENT; }
\/\/.* { return JSON_COMMENT; }
{endObject} {return endElement(false); }
/* white space within a tag */
<ST_JSON_OBJECT, ST_JSON_OBJECT_COLON, ST_JSON_ARRAY, ST_JSON_VALUE> {S}* {
return WHITE_SPACE;
}
<YYINITIAL> {
{startObject} {return startElement(false);}
{startArray} {return startElement(true);}
}
<ST_JSON_OBJECT> {
{endObject} {return endElement(false); }
{Key} {yybegin(ST_JSON_OBJECT_COLON); return JSON_OBJECT_KEY;}
}
<ST_JSON_OBJECT_COLON> {
":" { yybegin(ST_JSON_VALUE); return JSON_COLON; }
}
<ST_JSON_ARRAY> {
{endArray} {return endElement(true);}
}
<ST_JSON_VALUE, ST_JSON_ARRAY> {
{startObject} {return startElement(false);}
{startArray} {return startElement(true);}
"true" { yybegin(ST_JSON_VALUE); return JSON_VALUE_BOOLEAN; }
"false" { yybegin(ST_JSON_VALUE); return JSON_VALUE_BOOLEAN; }
"null" { yybegin(ST_JSON_VALUE); return JSON_VALUE_NULL; }
{string} { yybegin(ST_JSON_VALUE); return JSON_VALUE_STRING; }
{NUMBER_TEXT} { yybegin(ST_JSON_VALUE); return JSON_VALUE_NUMBER; }
}
<ST_JSON_VALUE> {endObject} {
return endElement(false);
}
<ST_JSON_VALUE> {comma} {
if (!isArrayParsing()) {
yybegin(ST_JSON_OBJECT);
}
return JSON_COMMA;
}
<ST_JSON_VALUE> {endArray} {
return endElement(true);
}
. {
return UNDEFINED;
}
\040 {
return WHITE_SPACE;
}
\011 {
return WHITE_SPACE;
}
\015
{
return WHITE_SPACE;
}
\012 {
return WHITE_SPACE;
}