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 \
|
diagnostic-show-locus.o \
|
||||||
edit-context.o \
|
edit-context.o \
|
||||||
pretty-print.o intl.o \
|
pretty-print.o intl.o \
|
||||||
json.o \
|
json.o json-parsing.o \
|
||||||
sbitmap.o \
|
sbitmap.o \
|
||||||
vec.o input.o hash-table.o ggc-none.o memory-block.o \
|
vec.o input.o hash-table.o ggc-none.o memory-block.o \
|
||||||
selftest.o selftest-diagnostic.o sort.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. */
|
/* Verify that JV->print () prints EXPECTED_JSON. */
|
||||||
|
|
||||||
static void
|
void
|
||||||
assert_print_eq (const location &loc,
|
assert_print_eq (const location &loc,
|
||||||
const json::value &jv,
|
const json::value &jv,
|
||||||
bool formatted,
|
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 http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
|
||||||
and https://tools.ietf.org/html/rfc7159
|
and https://tools.ietf.org/html/rfc7159
|
||||||
|
|
||||||
Supports creating a DOM-like tree of json::value *, and then dumping
|
Supports parsing text into a DOM-like tree of json::value *, directly
|
||||||
json::value * to text. */
|
creating such trees, and dumping json::value * to text. */
|
||||||
|
|
||||||
/* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
|
/* TODO: `libcpp/mkdeps.cc` wants JSON writing support for p1689r5 output;
|
||||||
extract this code and move to libiberty. */
|
extract this code and move to libiberty. */
|
||||||
@ -175,6 +175,13 @@ class array : public value
|
|||||||
size_t size () const { return m_elements.length (); }
|
size_t size () const { return m_elements.length (); }
|
||||||
value *operator[] (size_t i) const { return m_elements[i]; }
|
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:
|
private:
|
||||||
auto_vec<value *> m_elements;
|
auto_vec<value *> m_elements;
|
||||||
};
|
};
|
||||||
@ -252,4 +259,115 @@ class literal : public value
|
|||||||
|
|
||||||
} // namespace json
|
} // 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 */
|
#endif /* GCC_JSON_H */
|
||||||
|
@ -75,6 +75,7 @@ selftest::run_tests ()
|
|||||||
opt_suggestions_cc_tests ();
|
opt_suggestions_cc_tests ();
|
||||||
opts_cc_tests ();
|
opts_cc_tests ();
|
||||||
json_cc_tests ();
|
json_cc_tests ();
|
||||||
|
json_parser_cc_tests ();
|
||||||
cgraph_cc_tests ();
|
cgraph_cc_tests ();
|
||||||
optinfo_emit_json_cc_tests ();
|
optinfo_emit_json_cc_tests ();
|
||||||
ordered_hash_map_tests_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 input_cc_tests ();
|
||||||
extern void json_cc_tests ();
|
extern void json_cc_tests ();
|
||||||
extern void lazy_diagnostic_path_cc_tests ();
|
extern void lazy_diagnostic_path_cc_tests ();
|
||||||
|
extern void json_parser_cc_tests ();
|
||||||
extern void optinfo_emit_json_cc_tests ();
|
extern void optinfo_emit_json_cc_tests ();
|
||||||
extern void opts_cc_tests ();
|
extern void opts_cc_tests ();
|
||||||
extern void opts_diagnostic_cc_tests ();
|
extern void opts_diagnostic_cc_tests ();
|
||||||
|
Loading…
Reference in New Issue
Block a user