summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-03-28 17:17:11 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-11-07 16:41:37 +0000
commit3cd4ff83a253e098e6524df5be3a686727e4f50b (patch)
treecfbfaac4753d6321339f8653c3cabaca440afec8 /lib
parentCompile stb wrapper in C++ mode (diff)
downloadilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.tar.bz2
ilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.tar.xz
ilt-3cd4ff83a253e098e6524df5be3a686727e4f50b.zip
Initial commit of basis persistence
JSON parser lifted almost verbatim for libjsonpp running into some custom code for populating ilt objects. Pretty minimal per object code requirements.
Diffstat (limited to 'lib')
-rw-r--r--lib/jsonParse.h43
-rw-r--r--lib/jsonParse.impl.cpp39
-rw-r--r--lib/jsonParse.ll156
3 files changed, 238 insertions, 0 deletions
diff --git a/lib/jsonParse.h b/lib/jsonParse.h
new file mode 100644
index 0000000..6b1249f
--- /dev/null
+++ b/lib/jsonParse.h
@@ -0,0 +1,43 @@
+#ifndef JSONFLEXLEXER_H
+#define JSONFLEXLEXER_H
+
+#ifndef FLEX_SCANNER
+# define yyFlexLexer jsonBaseFlexLexer
+# include <FlexLexer.h>
+#endif
+#include <cassert>
+#include <filesystem>
+#include <fstream>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+namespace json {
+ class jsonParser : public yyFlexLexer {
+ public:
+ using yyFlexLexer::yyFlexLexer;
+ int yylex() override;
+
+ static void appendEscape(const char *, std::string &);
+ static void appendEscape(unsigned long, std::string &);
+
+ protected:
+ virtual void BeginObject() = 0;
+ virtual void BeginArray() = 0;
+
+ virtual void PushBoolean(bool) = 0;
+ virtual void PushNumber(float) = 0;
+ virtual void PushNull() = 0;
+ virtual void PushText(std::string &&) = 0;
+ virtual void PushKey(std::string &&) = 0;
+
+ virtual void EndArray() = 0;
+ virtual void EndObject() = 0;
+
+ void LexerError(const char * msg) override;
+
+ std::string buf;
+ };
+}
+
+#endif
diff --git a/lib/jsonParse.impl.cpp b/lib/jsonParse.impl.cpp
new file mode 100644
index 0000000..27e73b4
--- /dev/null
+++ b/lib/jsonParse.impl.cpp
@@ -0,0 +1,39 @@
+#include "jsonParse.h"
+
+void
+json::jsonParser::LexerError(const char * msg)
+{
+ throw std::runtime_error(msg);
+}
+
+void
+json::jsonParser::appendEscape(const char * cphs, std::string & str)
+{
+ appendEscape(std::strtoul(cphs, nullptr, 16), str);
+}
+
+void
+json::jsonParser::appendEscape(unsigned long cp, std::string & str)
+{
+ if (cp <= 0x7F) {
+ str += cp;
+ }
+ else if (cp <= 0x7FF) {
+ str += (cp >> 6) + 192;
+ str += (cp & 63) + 128;
+ }
+ else if (0xd800 <= cp && cp <= 0xdfff) {
+ throw std::range_error("Invalid UTF-8 sequence");
+ }
+ else if (cp <= 0xFFFF) {
+ str += (cp >> 12) + 224;
+ str += ((cp >> 6) & 63) + 128;
+ str += (cp & 63) + 128;
+ }
+ else if (cp <= 0x10FFFF) {
+ str += (cp >> 18) + 240;
+ str += ((cp >> 12) & 63) + 128;
+ str += ((cp >> 6) & 63) + 128;
+ str += (cp & 63) + 128;
+ }
+}
diff --git a/lib/jsonParse.ll b/lib/jsonParse.ll
new file mode 100644
index 0000000..0fc27e9
--- /dev/null
+++ b/lib/jsonParse.ll
@@ -0,0 +1,156 @@
+%option batch
+%option c++
+%option noyywrap
+%option 8bit
+%option stack
+%option yylineno
+%option yyclass="json::jsonParser"
+%option prefix="jsonBase"
+
+%{
+#include <string>
+#include "jsonParse.h"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wnull-conversion"
+#endif
+%}
+
+beginobj "{"
+endobj "}"
+beginarray "["
+endarray "]"
+beginstr "\""
+endstr "\""
+true "true"
+false "false"
+null "null"
+number [-+]?[0-9]+(\.[0-9]+)?
+colon ":"
+separator ","
+escape "\\"
+text [^\\\"]*
+
+%x OBJECT_ITEM
+%x OBJECT_ITEM_OR_END
+%x OBJECT_NEXT
+%x ARRAY_ITEM
+%x ARRAY_NEXT
+%x COLON
+%x TEXT
+%x STRING
+%x ESCAPE
+
+%%
+
+<ARRAY_ITEM,INITIAL>{true} {
+ PushBoolean(true);
+ yy_pop_state();
+}
+
+<ARRAY_ITEM,INITIAL>{false} {
+ PushBoolean(false);
+ yy_pop_state();
+}
+
+<ARRAY_ITEM,INITIAL>{number} {
+ PushNumber(std::strtof(YYText(), NULL));
+ yy_pop_state();
+}
+
+<ARRAY_ITEM,INITIAL>{null} {
+ PushNull();
+ yy_pop_state();
+}
+
+<ARRAY_ITEM,INITIAL,OBJECT_ITEM,OBJECT_ITEM_OR_END>{beginstr} {
+ yy_push_state(STRING);
+}
+
+<ARRAY_ITEM,INITIAL>{beginobj} {
+ BeginObject();
+ BEGIN(OBJECT_ITEM_OR_END);
+}
+
+<ARRAY_ITEM,INITIAL>{beginarray} {
+ BeginArray();
+ BEGIN(ARRAY_NEXT);
+ yy_push_state(ARRAY_ITEM);
+}
+
+<STRING>{endstr} {
+ yy_pop_state();
+ switch (YY_START) {
+ case ARRAY_ITEM:
+ case INITIAL:
+ PushText(std::move(buf));
+ yy_pop_state();
+ break;
+ case OBJECT_ITEM:
+ case OBJECT_ITEM_OR_END:
+ PushKey(std::move(buf));
+ BEGIN(COLON);
+ break;
+ }
+ buf.clear();
+}
+
+<OBJECT_NEXT,OBJECT_ITEM_OR_END>{endobj} {
+ EndObject();
+ yy_pop_state();
+}
+
+<ARRAY_ITEM>{endarray} {
+ EndArray();
+ yy_pop_state();
+ yy_pop_state();
+}
+
+<ARRAY_NEXT>{endarray} {
+ EndArray();
+ yy_pop_state();
+}
+
+<COLON>{colon} {
+ BEGIN(OBJECT_NEXT);
+ yy_push_state(INITIAL);
+}
+
+<OBJECT_NEXT>{separator} {
+ BEGIN(OBJECT_ITEM);
+}
+
+<ARRAY_NEXT>{separator} {
+ yy_push_state(INITIAL);
+}
+
+<STRING>{escape} {
+ yy_push_state(ESCAPE);
+}
+
+<ESCAPE>"\"" { buf += "\""; yy_pop_state(); }
+<ESCAPE>"\\" { buf += "\\"; yy_pop_state(); }
+<ESCAPE>"/" { buf += "/"; yy_pop_state(); }
+<ESCAPE>"b" { buf += "\b"; yy_pop_state(); }
+<ESCAPE>"f" { buf += "\f"; yy_pop_state(); }
+<ESCAPE>"n" { buf += "\n"; yy_pop_state(); }
+<ESCAPE>"r" { buf += "\r"; yy_pop_state(); }
+<ESCAPE>"t" { buf += "\t"; yy_pop_state(); }
+
+<ESCAPE>"u"[0-9a-fA-Z]{4} {
+ appendEscape(YYText(), buf);
+ yy_pop_state();
+}
+
+<STRING>{text} {
+ buf += YYText();
+}
+
+<*>[ \t\r\n\f] {
+}
+
+%%
+
+// Make iwyu think unistd.h is required
+[[maybe_unused]]static auto x=getpid;