All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.parboiled.examples.json.JsonParser1.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2009-2011 Mathias Doenitz
 *
 * 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 org.parboiled.examples.json

import org.parboiled.scala._
import java.lang.String
import org.parboiled.errors.{ErrorUtils, ParsingException}

/**
 * 

A complete JSON parser producing an AST representation of the parsed JSON source.

*

The syntactical grammar is identical to the JsonParser0 example, however this parser adds the parser * actions required to build an AST during the parsing run.

*

You might also want to look at the functionally equivalent JsonParser2 class in this example. It makes * most of the type information explicit that is left out in JsonParser1 and can make the parsers workings * easier to understand for first-time users

*/ class JsonParser1 extends Parser { /** * These case classes form the nodes of the AST. */ sealed abstract class AstNode case class ObjectNode(members: List[MemberNode]) extends AstNode case class MemberNode(key: String, value: AstNode) extends AstNode case class ArrayNode(elements: List[AstNode]) extends AstNode case class StringNode(text: String) extends AstNode case class NumberNode(value: BigDecimal) extends AstNode case object True extends AstNode case object False extends AstNode case object Null extends AstNode // the root rule def Json = rule { WhiteSpace ~ (JsonObject | JsonArray) ~ EOI } def JsonObject: Rule1[ObjectNode] = rule { "{ " ~ zeroOrMore(Pair, separator = ", ") ~ "} " ~~> ObjectNode } def Pair = rule { JsonString ~~> (_.text) ~ ": " ~ Value ~~> MemberNode } def Value: Rule1[AstNode] = rule { JsonString | JsonNumber | JsonObject | JsonArray | JsonTrue | JsonFalse | JsonNull } def JsonString = rule { "\"" ~ zeroOrMore(Character) ~> StringNode ~ "\" " } def JsonNumber = rule { group(Integer ~ optional(Frac ~ optional(Exp))) ~> (s => NumberNode(BigDecimal(s))) ~ WhiteSpace } def JsonArray = rule { "[ " ~ zeroOrMore(Value, separator = ", ") ~ "] " ~~> ArrayNode } def Character = rule { EscapedChar | NormalChar } def EscapedChar = rule { "\\" ~ (anyOf("\"\\/bfnrt") | Unicode) } def NormalChar = rule { !anyOf("\"\\") ~ ANY } def Unicode = rule { "u" ~ HexDigit ~ HexDigit ~ HexDigit ~ HexDigit } def Integer = rule { optional("-") ~ (("1" - "9") ~ Digits | Digit) } def Digits = rule { oneOrMore(Digit) } def Digit = rule { "0" - "9" } def HexDigit = rule { "0" - "9" | "a" - "f" | "A" - "Z" } def Frac = rule { "." ~ Digits } def Exp = rule { ignoreCase("e") ~ optional(anyOf("+-")) ~ Digits } def JsonTrue = rule { "true " ~ push(True) } def JsonFalse = rule { "false " ~ push(False) } def JsonNull = rule { "null " ~ push(Null) } def WhiteSpace: Rule0 = rule { zeroOrMore(anyOf(" \n\r\t\f")) } /** * We redefine the default string-to-rule conversion to also match trailing whitespace if the string ends with * a blank, this keeps the rules free from most whitespace matching clutter */ override implicit def toRule(string: String) = if (string.endsWith(" ")) str(string.trim) ~ WhiteSpace else str(string) /** * The main parsing method. Uses a ReportingParseRunner (which only reports the first error) for simplicity. */ def parseJson(json: String): AstNode = { val parsingResult = ReportingParseRunner(Json).run(json) parsingResult.result match { case Some(astRoot) => astRoot case None => throw new ParsingException("Invalid JSON source:\n" + ErrorUtils.printParseErrors(parsingResult)) } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy