- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
到目前为止,我已经成功地将词法分析器和堆栈组合在一起,希望实现 LL1 解析器。我这样做纯粹是为了了解解析是如何工作的,也许是为了在未来的项目中使用这些想法。我知道有更好的框架,例如 json-cpp 和 rapid-json,但我想亲自了解这一点。
头文件如下。
#pragma once
#include <string>
#include <vector>
#include <map>
#include <variant>
#include <fstream>
#include <stack>
#include "Helper.h"
// Debugging
#include <iostream>
// Types to store JSON ouput
struct jlist;
struct jobject;
using json_value = std::variant<int, float, bool, std::string, jlist, jobject>;
enum tag { int_value, float_value, string_value, list, object };
struct jlist {
tag type;
std::vector<json_value *> vector_value;
};
struct jobject {
tag type;
std::map<std::string, json_value *> map_value;
};
class JSONParser
{
public:
JSONParser();
~JSONParser();
void parseFile(std::string);
private:
std::stack<std::string> s;
bool checkDeliminator(char);
std::vector<std::string> lexer(std::ifstream &);
void parser(std::vector<std::string> &);
void transitionTable(std::string cursor);
};
实现如下。
#include "genetic-optimization/JSONParser.h"
JSONParser::JSONParser() {
}
JSONParser::~JSONParser() = default;
void JSONParser::parseFile(std::string FILE) {
std::ifstream configfile(FILE);
std::vector<std::string> scan = lexer(configfile);
parser(scan);
}
bool JSONParser::checkDeliminator(char piece) {
switch (piece) {
case '[':
return true;
case ']':
return true;
case '{':
return true;
case '}':
return true;
case ':':
return true;
case ',':
return true;
case '"':
return true;
default:
return false;
}
}
std::vector<std::string> JSONParser::lexer(std::ifstream & configfile) {
char piece;
std::string capture = "";
std::string conversion;
std::vector<std::string> capture_list;
while(configfile >> piece) {
if (checkDeliminator(piece)) {
conversion = piece;
if (capture != "") {
capture_list.push_back(capture);
capture_list.push_back(conversion);
capture = "";
} else {
capture_list.push_back(conversion);
}
} else {
capture += piece;
}
}
return capture_list;
}
void JSONParser::parser(std::vector<std::string> & scan) {
for (auto it = scan.begin(); it != scan.end(); ++it) {
std::cout << *it << "\n"; // Make sure the lexer works
transitionTable(*it);
}
}
void JSONParser::transitionTable(std::string cursor) {
if(s.empty()) {
s.push(cursor);
} else {
if (s.top() == "[") {
s.push(cursor);
} else if (s.top() == "]") {
s.pop();
} else if (s.top() == "{") {
s.push(cursor);
} else if (s.top() == "}") {
s.pop();
}
}
}
我不确定如何从这里继续,但一直在使用 json grammar作为起点和以下 tutorial以获得指导。
json -> element
value -> object|array|string|number|bool|
object -> {}|{members}
members -> member|member,members
member -> string:element
array -> []|[elements]
elements -> element|element,elements
element -> value
我有三个主要问题。
JSON语法似乎留下了间接递归。由于语法并不像教程中所示的那么简单,我不知道如何消除它。
我不知道如何生成解析表(有限状态机),特别是像 First(object)
这样的东西,这会是什么?是否有任何资源可以生成 JSON 解析表并可能为我指明正确的方向?
本教程似乎更多地是为了验证正在解析的表达式是由语法生成的,但我想将结构存储在变量中。这将在哪里完成,您对伪(甚至更好的 C++)代码的外观有什么建议吗?
为了完整起见,我使用以下 JSON 作为测试。
[
{
"libraries":[
"terminal",
"binary"
] ,
"functions":[
"terminal-basic",
"binary-basic"
]
}
,
{
"name":"addition",
"type":"binary-basic",
"function":"add_float",
"input":{
"float" : 2
},
"output":"float",
"max-number":2
}
,
{
"name":"exponent",
"type":"binary-basic",
"function":"exponent_float",
"input":{
"float":2
},
"output":"float",
"max-number":2
}
,
{
"name":"exponent",
"type":"binary-basic",
"function":"exponent_float",
"input":{
"float":2,
"int":1
},
"output":"float",
"max-number":1
}
,
{
"name":"constant_1",
"type":"terminal-basic",
"function":"non_random_constant",
"value":0.5,
"input":{ },
"output":"float",
"max-number":3
}
,
{
"name":"constant_2",
"type":"terminal-basic",
"function":"non_random_constant",
"value":2.0,
"input":{ },
"output":"float",
"max-number":3
}
,
{
"name":"constant_3",
"type":"terminal-basic",
"function":"non_random_constant",
"value":true,
"input":{
"bool":1
},
"output":"bool",
"max-number":1
}
]
最佳答案
我不想让将来来到这里的任何人都回答这个问题,但是,我个人不太喜欢这个答案附带的代码。它感觉效率低下,不是特别优雅,我不确定它是否代表了我最初试图实现的理论模型。我从@MSalters 评论中得到了指导,这对我来说意味着构建一些可行的东西,并担心模型在理论上是否合理。以下是我的尝试。
标题添加了更多功能。其中许多纯粹是为了协助 fsm
和 parser
。
class JSONParser
{
public:
JSONParser();
~JSONParser();
void parseFile(std::string);
private:
json_value root;
std::stack<std::string> s;
std::stack<json_value> s_value;
// Lexer
bool checkDeliminator(char);
std::vector<std::string> lexer(std::ifstream &);
// FSM varaibles
enum state { int_value, float_value, bool_value, string_value, default_value, bad_state};
state current;
// FSM
void fsm(std::string);
// Parser variables
enum stack_map { list_open, list_close, object_open, object_close, colon, comma, buffer, follow};
std::map<std::string, stack_map> stack_conversion;
// Parser helper functions
template<typename T> void addElement();
template<typename T> void insert(std::string &, T (*)(const std::string &));
template<typename T> void insert();
void insert(std::string &);
void pushBuffer();
template<typename ... T> bool multiComparision(const char scope, T ... args);
bool isDigit(const char);
static int st2i(const std::string & value);
static float st2f(const std::string & value);
static bool st2b(const std::string & value);
// Parser
void parser(const std::string & cursor);
};
实现文件如下。
#include "genetic-optimization/JSONParser.h"
JSONParser::JSONParser() {
state current = default_value;
stack_conversion = { { "[", list_open }, { "]", list_close }, { "{", object_open }, { "}", object_close }, { ":", colon }, { ",", comma }, { "buffer", buffer } };
}
JSONParser::~JSONParser() = default;
void JSONParser::parseFile(std::string FILE) {
std::ifstream configfile(FILE);
std::vector<std::string> scan = lexer(configfile);
scan.push_back("terminate");
for (auto it = scan.begin(); it != scan.end(); ++it) {
parser(*it);
}
root = s_value.top();
s_value.pop();
}
// Lexer
bool JSONParser::checkDeliminator(char piece) {
switch (piece) {
case '[':
return true;
case ']':
return true;
case '{':
return true;
case '}':
return true;
case ':':
return true;
case ',':
return true;
default:
return false;
}
}
std::vector<std::string> JSONParser::lexer(std::ifstream & configfile) {
char piece;
std::string capture = "";
std::string conversion;
std::vector<std::string> capture_list;
while(configfile >> piece) {
if (checkDeliminator(piece)) {
conversion = piece;
if (capture != "") {
capture_list.push_back(capture);
capture_list.push_back(conversion);
capture = "";
} else {
capture_list.push_back(conversion);
}
} else {
capture += piece;
}
}
return capture_list;
}
// FSM
void JSONParser::fsm(std::string value) {
current = default_value;
char point;
auto it = value.begin();
while (it != value.end()) {
point = *it;
if (point == '"' & current == default_value) {
current = string_value;
return;
} else if (isdigit(point)) {
if (current == default_value | current == int_value) {
current = int_value;
++it;
} else if (current == float_value) {
++it;
} else {
current = bad_state;
return;
}
} else if (point == '.' & current == int_value) {
current = float_value;
++it;
} else if (point == 'f' & current == float_value) {
++it;
} else if (current == default_value) {
if (value == "true" | value == "false") {
current = bool_value;
return;
} else {
current = bad_state;
return;
}
} else {
current = bad_state;
return;
}
}
}
// Parser Helper functions
template<>
void JSONParser::addElement<jobject>() {
json_value value_read;
json_value key_read;
value_read = s_value.top();
s_value.pop();
key_read = s_value.top();
s_value.pop();
std::get<jobject>(s_value.top()).insert(key_read, value_read);
}
template<>
void JSONParser::addElement<jlist>() {
json_value value_read;
value_read = s_value.top();
s_value.pop();
std::get<jlist>(s_value.top()).push_back(value_read);
}
template<typename T>
void JSONParser::insert(std::string & value, T (*fptr)(const std::string &)) {
T T_value(fptr(value));
s_value.push(T_value);
}
template<typename T>
void JSONParser::insert() {
T T_value;
s_value.push(T_value);
}
void JSONParser::insert(std::string & value) {
value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
s_value.push(value);
}
void JSONParser::pushBuffer() {
s.pop();
s.push("buffer");
}
template<typename ... T>
bool JSONParser::multiComparision(const char scope, T ... args) {
return (scope == (args || ...));
}
bool JSONParser::isDigit(const char c) {
return multiComparision<char>(c, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0');
}
int JSONParser::st2i(const std::string & value) {
return stoi(value);
}
float JSONParser::st2f(const std::string & value) {
return stof(value);
}
bool JSONParser::st2b(const std::string & value) {
if (value == "true") {
return true;
} else {
return false;
}
}
// Parser
void JSONParser::parser(const std::string & cursor) {
if(s.empty()) {
s.push(cursor);
} else {
stack_map stack_value;
std::string value = s.top();
if (stack_conversion.find(value) != stack_conversion.end()) {
stack_value = stack_conversion[s.top()];
} else {
stack_value = follow;
}
switch (stack_value) {
case buffer:
s.pop();
break;
case list_open:
insert<jlist>();
if (cursor == "]") {
pushBuffer();
return;
}
break;
case list_close:
addElement<jlist>();
s.pop();
s.pop();
break;
case object_open:
insert<jobject>();
if (cursor == "}") {
pushBuffer();
return;
}
break;
case object_close:
addElement<jobject>();
s.pop();
s.pop();
break;
case colon:
s.pop();
break;
case comma:
s.pop();
if (s.top() == "{") {
addElement<jobject>();
} else {
addElement<jlist>();
}
break;
default:
s.pop();
fsm(value);
switch (current) {
case string_value:
insert(value);
break;
case int_value:
insert<int>(value, st2i);
break;
case float_value:
insert<float>(value, st2f);
break;
case bool_value:
insert<bool>(value, st2b);
break;
default:
std::cout << "Bad state\n";
}
}
s.push(cursor);
}
}
这个想法是让词法分析器
在每个分隔符处中断,并将所有生成的标记放入 vector 中。然后可以循环遍历这个名为 scan
的 vector 。在此循环的每次迭代中,parser
都会运行。一般来说,这会读取堆栈的顶部 s
并确定括号/大括号是否正在打开或关闭,或者是否已达到最终值。如果括号/大括号打开,则会生成新的 jobject
或 jlist
并将其放置到新堆栈 s_value
中(如果达到最终值) fsm
(有限状态机)运行并确定值的类型,并将其放置在 s_value
之上,如果到达逗号或右括号,则相应的值将从堆栈和 s_value
中的元素被插入到适当的容器中。
这个意大利面条中最大的问题是如何调用 JSON 树中的元素。
std::cout << std::get<bool>(std::get<jobject>(std::get<jobject>(std::get<jlist>(root)[6])["input"])["bool"]); // Should return 1
虽然这确实返回 1。嵌套的 std::get 调用似乎完全错误,我不确定它们是否可以合并到 operator []
中或通过(叹气)a第三个堆栈跟踪正在存储的对象的类型。
这是我的基本尝试,它并不漂亮,但确实有效。希望我能进一步完善它并改进我所拥有的。
关于c++ - 为 C++ 编写 JSON 解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58860733/
我一直在使用 AJAX 从我正在创建的网络服务中解析 JSON 数组时遇到问题。我的前端是一个简单的 ajax 和 jquery 组合,用于显示从我正在创建的网络服务返回的结果。 尽管知道我的数据库查
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我在尝试运行 Android 应用程序时遇到问题并收到以下错误 java.lang.NoClassDefFoundError: com.parse.Parse 当我尝试运行该应用时。 最佳答案 在这
有什么办法可以防止etree在解析HTML内容时解析HTML实体吗? html = etree.HTML('&') html.find('.//body').text 这给了我 '&' 但我想
我有一个有点疯狂的例子,但对于那些 JavaScript 函数作用域专家来说,它看起来是一个很好的练习: (function (global) { // our module number one
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 8 年前。 Improve th
我需要编写一个脚本来获取链接并解析链接页面的 HTML 以提取标题和其他一些数据,例如可能是简短的描述,就像您链接到 Facebook 上的内容一样。 当用户向站点添加链接时将调用它,因此在客户端启动
在 VS Code 中本地开发时,包解析为 C:/Users//AppData/Local/Microsoft/TypeScript/3.5/node_modules/@types//index而不是
我在将 json 从 php 解析为 javascript 时遇到问题 这是我的示例代码: //function MethodAjax = function (wsFile, param) {
我在将 json 从 php 解析为 javascript 时遇到问题 这是我的示例代码: //function MethodAjax = function (wsFile, param) {
我被赋予了将一种语言“翻译”成另一种语言的工作。对于使用正则表达式的简单逐行方法来说,源代码过于灵活(复杂)。我在哪里可以了解更多关于词法分析和解析器的信息? 最佳答案 如果你想对这个主题产生“情绪化
您好,我在解析此文本时遇到问题 { { { {[system1];1;1;0.612509325}; {[system2];1;
我正在为 adobe after effects 在 extendscript 中编写一些代码,最终变成了 javascript。 我有一个数组,我想只搜索单词“assemble”并返回整个 jc3_
我有这段代码: $(document).ready(function() { // }); 问题:FB_RequireFeatures block 外部的代码先于其内部的代码执行。因此 who
背景: netcore项目中有些服务是在通过中间件来通信的,比如orleans组件。它里面服务和客户端会指定网关和端口,我们只需要开放客户端给外界,服务端关闭端口。相当于去掉host,这样省掉了些
1.首先贴上我试验成功的代码 复制代码 代码如下: protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
什么是 XML? XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。 你可以通过本站学习 X
【PHP代码】 复制代码 代码如下: $stmt = mssql_init('P__Global_Test', $conn) or die("initialize sto
在SQL查询分析器执行以下代码就可以了。 复制代码代码如下: declare @t varchar(255),@c varchar(255) declare table_cursor curs
前言 最近练习了一些前端算法题,现在做个总结,以下题目都是个人写法,并不是标准答案,如有错误欢迎指出,有对某道题有新的想法的友友也可以在评论区发表想法,互相学习🤭 题目 题目一: 二维数组中的
我是一名优秀的程序员,十分优秀!