Skip to content

Commit

Permalink
Merge pull request #288 from tr11/json-parser
Browse files Browse the repository at this point in the history
Json parser
  • Loading branch information
yruslan authored May 13, 2020
2 parents 0aea138 + 70b672c commit c9d602b
Show file tree
Hide file tree
Showing 11 changed files with 1,170 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2018 ABSA Group Limited
*
* 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 za.co.absa.cobrix.cobol.parser.antlr
import org.antlr.v4.runtime.{BailErrorStrategy, CharStreams, CommonTokenStream}

import scala.collection.JavaConversions._


class ParserJson {
def parse(text: String): Any = {
val visitor = new ParserJsonVisitor()
val charStream = CharStreams.fromString(text)
val lexer = new jsonLexer(charStream)
val tokens = new CommonTokenStream(lexer)
val parser = new jsonParser(tokens)
parser.setErrorHandler(new BailErrorStrategy());
visitor.visit(parser.json())
}

def parseMap(text: String): Map[String, Any] = {
this.parse(text).asInstanceOf[Map[String, Any]]
}
}


class ParserJsonVisitor extends jsonBaseVisitor[Any] {
/**
* Visit a parse tree produced by {@link jsonParser#pair}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitPair(ctx: jsonParser.PairContext): Any = {
val key = ctx.STRING().getText
val value = this.visit(ctx.value)
(key.substring(1, key.length - 1), value)
}

/**
* Visit a parse tree produced by the {@code value_string}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_string(ctx: jsonParser.Value_stringContext): Any = {
val text = ctx.getText
text.substring(1, text.length - 1)
}

/**
* Visit a parse tree produced by the {@code value_number}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_number(ctx: jsonParser.Value_numberContext): Any = {
val text = ctx.getText
try { text.toInt } catch { case _: Throwable => text.toDouble }
}

/**
* Visit a parse tree produced by the {@code value_obj}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_obj(ctx: jsonParser.Value_objContext): Any = {
ctx.obj().pair().map(x => this.visit(x).asInstanceOf[(String, Any)]).toMap
}

/**
* Visit a parse tree produced by the {@code value_array}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_array(ctx: jsonParser.Value_arrayContext): Any = {
ctx.arr.value.map(x => this.visit(x)).toArray
}

/**
* Visit a parse tree produced by the {@code value_true}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_true(ctx: jsonParser.Value_trueContext): Any = true

/**
* Visit a parse tree produced by the {@code value_false}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_false(ctx: jsonParser.Value_falseContext): Any = false

/**
* Visit a parse tree produced by the {@code value_null}
* labeled alternative in {@link jsonParser#value}.
*
* @param ctx the parse tree
* @return the visitor result
*/
override def visitValue_null(ctx: jsonParser.Value_nullContext): Any = null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

grammar json;

json
: value
;

obj
: '{' pair (',' pair)* '}'
| '{' '}'
;

pair
: STRING ':' value
;

arr
: '[' value (',' value)* ']'
| '[' ']'
;

value
: STRING #value_string
| NUMBER #value_number
| obj #value_obj
| arr #value_array
| 'true' #value_true
| 'false' #value_false
| 'null' #value_null
;


STRING
: '"' (ESC | SAFECODEPOINT)* '"'
;


fragment ESC
: '\\' (["\\/bfnrt] | UNICODE)
;
fragment UNICODE
: 'u' HEX HEX HEX HEX
;
fragment HEX
: [0-9a-fA-F]
;
fragment SAFECODEPOINT
: ~ ["\\\u0000-\u001F]
;


NUMBER
: '-'? INT ('.' [0-9] +)? EXP?
;


fragment INT
: '0' | [1-9] [0-9]*
;

// no leading zeros

fragment EXP
: [Ee] [+\-]? INT
;

// \- since - means "range" inside [...]

WS
: [ \t\n\r] + -> skip
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2018 ABSA Group Limited
*
* 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 za.co.absa.cobrix.cobol.parser.antlr;

// Generated from json.g4 by ANTLR 4.7.2
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;

/**
* This class provides an empty implementation of {@link jsonVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class jsonBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements jsonVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitJson(jsonParser.JsonContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitObj(jsonParser.ObjContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitPair(jsonParser.PairContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitArr(jsonParser.ArrContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_string(jsonParser.Value_stringContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_number(jsonParser.Value_numberContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_obj(jsonParser.Value_objContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_array(jsonParser.Value_arrayContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_true(jsonParser.Value_trueContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_false(jsonParser.Value_falseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_null(jsonParser.Value_nullContext ctx) { return visitChildren(ctx); }
}
Loading

0 comments on commit c9d602b

Please sign in to comment.