mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
json: add json parsing support
This patch implements JSON parsing support. It's based on the parsing parts of the patch I posted here: https://gcc.gnu.org/legacy-ml/gcc-patches/2017-08/msg00417.html with the parsing moved to a separate source file and header, heavily rewritten to capture source location information for JSON values, and to capture errors via a result template. I also added optional support for C and C++ style comments, which is extremely useful in DejaGnu tests. gcc/ChangeLog: * Makefile.in (OBJS-libcommon): Add json-parsing.o. * json-parsing.cc: New file. * json-parsing.h: New file. * json.cc (selftest::assert_print_eq): Remove "static". * json.h (json::array::begin): New. (json::array::end): New. (json::array::length): New. (json::array::get): New. (is_a_helper <json::value *>::test): New. (is_a_helper <const json::value *>::test): New. (is_a_helper <json::object *>::test): New. (is_a_helper <const json::object *>::test): New. (is_a_helper <json::array *>::test): New. (is_a_helper <const json::array *>::test): New. (is_a_helper <json::float_number *>::test): New. (is_a_helper <const json::float_number *>::test): New. (is_a_helper <json::integer_number *>::test): New. (is_a_helper <const json::integer_number *>::test): New. (is_a_helper <json::string *>::test): New. (is_a_helper <const json::string *>::test): New. (selftest::assert_print_eq): New decl. * selftest-run-tests.cc (selftest::run_tests): Call selftest::json_parser_cc_tests. * selftest.h (selftest::json_parser_cc_tests): New decl. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
parent
99a909aba3
commit
66e6e4f131
@ -1838,7 +1838,7 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
|
||||
diagnostic-show-locus.o \
|
||||
edit-context.o \
|
||||
pretty-print.o intl.o \
|
||||
json.o \
|
||||
json.o json-parsing.o \
|
||||
sbitmap.o \
|
||||
vec.o input.o hash-table.o ggc-none.o memory-block.o \
|
||||
selftest.o selftest-diagnostic.o sort.o \
|
||||
|
2394
gcc/json-parsing.cc
Normal file
2394
gcc/json-parsing.cc
Normal file
File diff suppressed because it is too large
Load Diff
113
gcc/json-parsing.h
Normal file
113
gcc/json-parsing.h
Normal file
@ -0,0 +1,113 @@
|
||||
/* JSON parsing
|
||||
Copyright (C) 2017-2022 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_JSON_PARSING_H
|
||||
#define GCC_JSON_PARSING_H
|
||||
|
||||
#include "json.h"
|
||||
|
||||
namespace json
|
||||
{
|
||||
|
||||
/* Declarations for parsing JSON to a json::value * tree. */
|
||||
|
||||
/* Abstract base class for recording what the locations of JSON values
|
||||
were as they parsed. */
|
||||
|
||||
class location_map
|
||||
{
|
||||
public:
|
||||
/* A point within the JSON input file. */
|
||||
struct point
|
||||
{
|
||||
size_t m_unichar_idx; /* zero-based. */
|
||||
int m_line; /* one-based. */
|
||||
int m_column; /* zero-based unichar count. */
|
||||
};
|
||||
|
||||
/* A range of points within the JSON input file.
|
||||
Both endpoints are part of the range. */
|
||||
struct range
|
||||
{
|
||||
point m_start;
|
||||
point m_end;
|
||||
};
|
||||
|
||||
virtual ~location_map () {}
|
||||
virtual void record_range_for_value (json::value *jv, const range &r) = 0;
|
||||
virtual void on_finished_parsing () {}
|
||||
};
|
||||
|
||||
/* Class for recording an error within a JSON file. */
|
||||
|
||||
class error
|
||||
{
|
||||
public:
|
||||
error (const location_map::range &r, char *msg)
|
||||
: m_range (r), m_msg (msg)
|
||||
{
|
||||
}
|
||||
~error ()
|
||||
{
|
||||
free (m_msg);
|
||||
}
|
||||
|
||||
const location_map::range &get_range () const { return m_range; }
|
||||
const char *get_msg () const { return m_msg; }
|
||||
|
||||
private:
|
||||
location_map::range m_range;
|
||||
char *m_msg;
|
||||
};
|
||||
|
||||
/* Class for the result of an operation: either a value or an error
|
||||
(or both null for the case of "successful nullptr").
|
||||
The types must be default-constructible. */
|
||||
|
||||
template <typename ValueType, typename ErrorType>
|
||||
struct result
|
||||
{
|
||||
result (ValueType val) : m_val (std::move (val)), m_err () {}
|
||||
result (ErrorType err) : m_val (), m_err (std::move (err)) {}
|
||||
|
||||
ValueType m_val;
|
||||
ErrorType m_err;
|
||||
};
|
||||
|
||||
/* Typedef for the result of parsing JSON: ownership of either a
|
||||
json::value * or of a json::error *. */
|
||||
typedef result<std::unique_ptr<value>,
|
||||
std::unique_ptr<error>> parser_result_t;
|
||||
|
||||
/* Functions for parsing JSON buffers. */
|
||||
|
||||
extern parser_result_t
|
||||
parse_utf8_string (size_t length,
|
||||
const char *utf8_buf,
|
||||
bool allow_comments,
|
||||
location_map *out_loc_map);
|
||||
extern parser_result_t
|
||||
parse_utf8_string (const char *utf8,
|
||||
bool allow_comments,
|
||||
location_map *out_loc_map);
|
||||
|
||||
} // namespace json
|
||||
|
||||
#endif /* GCC_JSON_PARSING_H */
|
@ -383,7 +383,7 @@ namespace selftest {
|
||||
|
||||
/* Verify that JV->print () prints EXPECTED_JSON. */
|
||||
|
||||
static void
|
||||
void
|
||||
assert_print_eq (const location &loc,
|
||||
const json::value &jv,
|
||||
bool formatted,
|
||||
|
122
gcc/json.h
122
gcc/json.h
@ -36,8 +36,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
|
||||
and https://tools.ietf.org/html/rfc7159
|
||||
|
||||
Supports creating a DOM-like tree of json::value *, and then dumping
|
||||
json::value * to text. */
|
||||
Supports parsing text into a DOM-like tree of json::value *, directly
|
||||
creating such trees, and dumping json::value * to text. */
|
||||
|
||||
/* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
|
||||
extract this code and move to libiberty. */
|
||||
@ -175,6 +175,13 @@ class array : public value
|
||||
size_t size () const { return m_elements.length (); }
|
||||
value *operator[] (size_t i) const { return m_elements[i]; }
|
||||
|
||||
value **begin () { return m_elements.begin (); }
|
||||
value **end () { return m_elements.end (); }
|
||||
const value * const *begin () const { return m_elements.begin (); }
|
||||
const value * const *end () const { return m_elements.end (); }
|
||||
size_t length () const { return m_elements.length (); }
|
||||
value *get (size_t idx) const { return m_elements[idx]; }
|
||||
|
||||
private:
|
||||
auto_vec<value *> m_elements;
|
||||
};
|
||||
@ -252,4 +259,115 @@ class literal : public value
|
||||
|
||||
} // namespace json
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::value *>::test (json::value *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::value *>::test (const json::value *)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::object *>::test (json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::object *>::test (const json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::array *>::test (json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::array *>::test (const json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::float_number *>::test (json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_FLOAT;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::float_number *>::test (const json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_FLOAT;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::integer_number *>::test (json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_INTEGER;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::integer_number *>::test (const json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_INTEGER;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <json::string *>::test (json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const json::string *>::test (const json::value *jv)
|
||||
{
|
||||
return jv->get_kind () == json::JSON_STRING;
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
||||
class location;
|
||||
|
||||
extern void assert_print_eq (const location &loc,
|
||||
const json::value &jv,
|
||||
bool formatted,
|
||||
const char *expected_json);
|
||||
|
||||
} // namespace selftest
|
||||
|
||||
#endif /* #if CHECKING_P */
|
||||
|
||||
#endif /* GCC_JSON_H */
|
||||
|
@ -75,6 +75,7 @@ selftest::run_tests ()
|
||||
opt_suggestions_cc_tests ();
|
||||
opts_cc_tests ();
|
||||
json_cc_tests ();
|
||||
json_parser_cc_tests ();
|
||||
cgraph_cc_tests ();
|
||||
optinfo_emit_json_cc_tests ();
|
||||
ordered_hash_map_tests_cc_tests ();
|
||||
|
@ -240,6 +240,7 @@ extern void hash_set_tests_cc_tests ();
|
||||
extern void input_cc_tests ();
|
||||
extern void json_cc_tests ();
|
||||
extern void lazy_diagnostic_path_cc_tests ();
|
||||
extern void json_parser_cc_tests ();
|
||||
extern void optinfo_emit_json_cc_tests ();
|
||||
extern void opts_cc_tests ();
|
||||
extern void opts_diagnostic_cc_tests ();
|
||||
|
Loading…
Reference in New Issue
Block a user