%name LucyParseJson
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
%token_type { cfish_Obj* }
%token_destructor { CFISH_DECREF($$); }
%token_prefix LUCY_JSON_TOKENTYPE_
%include {
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "Lucy/Object/Hash.h"
#include "Lucy/Object/VArray.h"
#include "Lucy/Object/CharBuf.h"
#include "Lucy/Object/Err.h"
#include "Lucy/Util/Json.h"
}
%extra_argument { lucy_JsonParserState *state }
%syntax_error {
state->errors = true;
}
result ::= top_level_value(A).
{
state->result = A;
}
/* Allow any "value" as a top-level construct. This "loose", tolerant grammar
* makes testing somewhat easier. A strict JSON parser would only allow JSON
* Objects and Arrays at the top level.
*/
top_level_value(A) ::= value(B). { A = B; }
/* Values */
%type STRING { cfish_CharBuf* }
value(A) ::= FALSE(B). { A = B; }
value(A) ::= NULL(B). { A = B; }
value(A) ::= TRUE(B). { A = B; }
value(A) ::= object(B). { A = (cfish_Obj*)B; }
value(A) ::= array(B). { A = (cfish_Obj*)B; }
value(A) ::= NUMBER(B). { A = (cfish_Obj*)B; }
value(A) ::= STRING(B). { A = B; }
/* Javascript Objects, implemented as Clownfish Hashes. */
%type object { cfish_Hash* }
%type empty_object { cfish_Hash* }
%type single_pair_object { cfish_Hash* }
%type multi_pair_object { cfish_Hash* }
%type key_value_pair_list { cfish_Hash* }
%destructor object { CFISH_DECREF($$); }
%destructor empty_object { CFISH_DECREF($$); }
%destructor single_pair_object { CFISH_DECREF($$); }
%destructor multi_pair_object { CFISH_DECREF($$); }
%destructor key_value_pair_list { CFISH_DECREF($$); }
object(A) ::= empty_object(B). { A = B; }
object(A) ::= single_pair_object(B). { A = B; }
object(A) ::= multi_pair_object(B). { A = B; }
empty_object(A) ::= LEFT_CURLY_BRACKET RIGHT_CURLY_BRACKET.
{
A = cfish_Hash_new(0);
}
single_pair_object(A) ::= LEFT_CURLY_BRACKET STRING(B) COLON value(C) RIGHT_CURLY_BRACKET.
{
A = cfish_Hash_new(1);
Cfish_Hash_Store(A, (cfish_Obj*)B, C);
CFISH_DECREF(B);
}
multi_pair_object(A) ::= LEFT_CURLY_BRACKET key_value_pair_list(B) STRING(C) COLON value(D) RIGHT_CURLY_BRACKET.
{
A = B;
Cfish_Hash_Store(A, (cfish_Obj*)C, D);
CFISH_DECREF(C);
}
key_value_pair_list(A) ::= key_value_pair_list(B) STRING(C) COLON value(D) COMMA.
{
A = B;
Cfish_Hash_Store(A, (cfish_Obj*)C, D);
CFISH_DECREF(C);
}
key_value_pair_list(A) ::= STRING(B) COLON value(C) COMMA.
{
A = cfish_Hash_new(0);
Cfish_Hash_Store(A, (cfish_Obj*)B, C);
CFISH_DECREF(B);
}
/* Arrays. */
%type array { cfish_VArray* }
%type empty_array { cfish_VArray* }
%type single_elem_array { cfish_VArray* }
%type multi_elem_array { cfish_VArray* }
%type array_elem_list { cfish_VArray* }
%destructor array { CFISH_DECREF($$); }
%destructor single_elem_array { CFISH_DECREF($$); }
%destructor multi_elem_array { CFISH_DECREF($$); }
%destructor array_elem_list { CFISH_DECREF($$); }
array(A) ::= empty_array(B). { A = B; }
array(A) ::= single_elem_array(B). { A = B; }
array(A) ::= multi_elem_array(B). { A = B; }
empty_array(A) ::= LEFT_SQUARE_BRACKET RIGHT_SQUARE_BRACKET.
{
A = cfish_VA_new(0);
}
single_elem_array(A) ::= LEFT_SQUARE_BRACKET value(B) RIGHT_SQUARE_BRACKET.
{
A = cfish_VA_new(1);
Cfish_VA_Push(A, B);
}
multi_elem_array(A) ::= LEFT_SQUARE_BRACKET array_elem_list(B) value(C) RIGHT_SQUARE_BRACKET.
{
A = B;
Cfish_VA_Push(A, C);
}
array_elem_list(A) ::= array_elem_list(B) value(C) COMMA.
{
A = B;
Cfish_VA_Push(A, C);
}
array_elem_list(A) ::= value(B) COMMA.
{
A = cfish_VA_new(1);
Cfish_VA_Push(A, B);
}