- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
尝试生成一个 AST,就像员工示例一样,它不仅仅包含员工。在我目前的心态中,RExpressions 示例对我没有帮助。我的示例无法编译,但据我所知,我已将团队、部门和公司添加到员工示例中。
我的问题是理解如何将不同的结构添加到变体中并将变体添加到 phrase_parse,如果这是想法的话。
在这个例子中,可以有几行相同的行相互跟随。所以想知道这是否需要使 AST 递归。
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <iostream>
#include <string>
#include <complex>
namespace client { namespace ast
{
struct employee;
struct team;
struct department;
struct corporation;
typedef x3::variant<
employee,
team,
department,
corporation
> var_types;
struct employee
{
int age;
std::string surname;
std::string forename;
double salary;
};
struct team
{
std::string name;
int num_employees;
};
struct department
{
std::string name;
int num_teams;
double budget;
};
struct corporation
{
std::string name;
int num_depts;
};
}}
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, age, surname, forename, salary)
BOOST_FUSION_ADAPT_STRUCT(client::ast::team, name, num_employees)
BOOST_FUSION_ADAPT_STRUCT(client::ast::department, name, num_teams, budget)
BOOST_FUSION_ADAPT_STRUCT(client::ast::corporation, name, num_depts)
namespace client
{
namespace parser
{
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
using x3::int_;
using x3::lit;
using x3::double_;
using x3::lexeme;
using ascii::char_;
using x3::eol;
using x3::blank;
using x3::skip;
x3::rule<class employee, ast::employee> const employee = "employee";
auto const employee_def = int_ >> *(char_ - eol) >> *(char_ - eol) >> double_;
BOOST_SPIRIT_DEFINE(employee);
x3::rule<class team, ast::team> const team = "team";
auto const team_def = *(char_ - eol) >> int_;
BOOST_SPIRIT_DEFINE(team);
x3::rule<class department, ast::department> const department = "department";
auto const department_def = *(char_ - eol) >> int_ >> double_;
BOOST_SPIRIT_DEFINE(department);
x3::rule<class corporation, ast::corporation> const corporation = "corporation";
auto const corporation_def = *(char_ - eol) >> int_;
BOOST_SPIRIT_DEFINE(corporation);
auto pemployee = skip(blank) [
*(employee >> eol)
];
auto pteam = skip(blank) [
*(team >> eol)
];
auto pdepartment = skip(blank) [
*(department >> eol)
];
auto pcorporation = skip(blank) [
*(corporation >> eol)
];
auto const input = pemployee >> pteam >> pdepartment >> pcorporation;
}
}
int main()
{
namespace x3 = boost::spirit::x3;
using boost::spirit::x3::ascii::blank;
using x3::char_;
using client::parser::input;
using client::ast::var_types;
var_types types;
std::istringstream iss("30 joe smith 100000.00\n20 mary jo 100000.00\n25 john doe 100000.00\nteamA 1\nteamB 1\nteamC 1\naccounting 1 100000.00\nengineering 2 200000.00\nAcmeCorp 3\n");
boost::spirit::istream_iterator iter(iss >> std::noskipws), eof;
bool ok = phrase_parse(iter, eof, input, x3::char_(' '), types);
std::cout << "ok = " << ok << std::endl;
return 0;
}
最佳答案
除了缺少包含和命名空间别名外,您应该只确保绑定(bind)属性 ref 允许多个条目,因为语法匹配多个员工、团队、部门和公司...:
std::vector<var_types> types;
让它为我编译。
假设你的 ast 是你想要的(为什么?!它不反射(reflect)语法)这是一个工作示例。
注意
phrase_parse
是伪造的,因为您无论如何都会覆盖船长。无论如何,出于正确性和易用性的原因,我喜欢在语法定义中使用 skipper。#include <iostream>
#define BOOST_SPIRIT_X3_DEBUG
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace x3 = boost::spirit::x3;
namespace client { namespace ast {
struct employee;
struct team;
struct department;
struct corporation;
typedef x3::variant<
employee,
team,
department,
corporation
> var_types;
struct employee
{
int age;
std::string surname;
std::string forename;
double salary;
};
struct team
{
std::string name;
int num_employees;
};
struct department
{
std::string name;
int num_teams;
double budget;
};
struct corporation
{
std::string name;
int num_depts;
};
}}
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, age, surname, forename, salary)
BOOST_FUSION_ADAPT_STRUCT(client::ast::team, name, num_employees)
BOOST_FUSION_ADAPT_STRUCT(client::ast::department, name, num_teams, budget)
BOOST_FUSION_ADAPT_STRUCT(client::ast::corporation, name, num_depts)
namespace client
{
namespace parser
{
namespace ascii = boost::spirit::x3::ascii;
using namespace x3;
auto const string
= x3::rule<struct string_, std::string> {"string"}
= lexeme[+graph];
auto const employee
= x3::rule<class employee, ast::employee>{"employee"}
= int_ >> string >> string >> double_;
auto const team
= x3::rule<class team, ast::team>{"team"}
= string >> int_;
auto const department
= x3::rule<class department, ast::department>{"department"}
= string >> int_ >> double_;
auto const corporation
= x3::rule<class corporation, ast::corporation>{"corporation"}
= string >> int_;
auto any = employee|department|team|corporation;
auto const input = skip(blank) [ *(any >> eol) ];
}
}
int main()
{
namespace x3 = boost::spirit::x3;
using boost::spirit::x3::ascii::blank;
using x3::char_;
using client::ast::var_types;
std::vector<var_types> types;
std::string const iss(R"(30 joe smith 100000.00
20 mary jo 100000.00
25 john doe 100000.00
teamA 1
teamB 1
teamC 1
accounting 1 100000.00
engineering 2 200000.00
AcmeCorp 3
)");
auto iter = iss.begin(), eof = iss.end();
bool ok = parse(iter, eof, client::parser::input, types);
if (iter != eof) {
std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n";
}
std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n";
std::cout << "ok = " << ok << std::endl;
for (auto& item : types) {
boost::apply_visitor([](auto& v) { std::cout << boost::fusion::as_deque(v) << "\n"; }, item);
}
}
打印
Parsed: 100%
ok = 1
(30 joe smith 100000)
(20 mary jo 100000)
(25 john doe 100000)
(teamA 1)
(teamB 1)
(teamC 1)
(accounting 1 100000)
(engineering 2 200000)
(AcmeCorp 3)
如果启用的话会有很多调试信息:
<employee>
<try>30 joe smith 100000.</try>
<string>
<try> joe smith 100000.00</try>
<success> smith 100000.00\n20 </success>
<attributes>[j, o, e]</attributes>
</string>
<string>
<try> smith 100000.00\n20 </try>
<success> 100000.00\n20 mary j</success>
<attributes>[s, m, i, t, h]</attributes>
</string>
<success>\n20 mary jo 100000.0</success>
<attributes>[30, [j, o, e], [s, m, i, t, h], 100000]</attributes>
</employee>
<employee>
<try>20 mary jo 100000.00</try>
<string>
<try> mary jo 100000.00\n2</try>
<success> jo 100000.00\n25 joh</success>
<attributes>[m, a, r, y]</attributes>
</string>
<string>
<try> jo 100000.00\n25 joh</try>
<success> 100000.00\n25 john d</success>
<attributes>[j, o]</attributes>
</string>
<success>\n25 john doe 100000.</success>
<attributes>[20, [m, a, r, y], [j, o], 100000]</attributes>
</employee>
<employee>
<try>25 john doe 100000.0</try>
<string>
<try> john doe 100000.00\n</try>
<success> doe 100000.00\nteamA</success>
<attributes>[j, o, h, n]</attributes>
</string>
<string>
<try> doe 100000.00\nteamA</try>
<success> 100000.00\nteamA 1\nt</success>
<attributes>[d, o, e]</attributes>
</string>
<success>\nteamA 1\nteamB 1\ntea</success>
<attributes>[25, [j, o, h, n], [d, o, e], 100000]</attributes>
</employee>
<employee>
<try>teamA 1\nteamB 1\nteam</try>
<fail/>
</employee>
<department>
<try>teamA 1\nteamB 1\nteam</try>
<string>
<try>teamA 1\nteamB 1\nteam</try>
<success> 1\nteamB 1\nteamC 1\na</success>
<attributes>[t, e, a, m, A]</attributes>
</string>
<fail/>
</department>
<team>
<try>teamA 1\nteamB 1\nteam</try>
<string>
<try>teamA 1\nteamB 1\nteam</try>
<success> 1\nteamB 1\nteamC 1\na</success>
<attributes>[t, e, a, m, A]</attributes>
</string>
<success>\nteamB 1\nteamC 1\nacc</success>
<attributes>[[t, e, a, m, A], 1]</attributes>
</team>
<employee>
<try>teamB 1\nteamC 1\nacco</try>
<fail/>
</employee>
<department>
<try>teamB 1\nteamC 1\nacco</try>
<string>
<try>teamB 1\nteamC 1\nacco</try>
<success> 1\nteamC 1\naccountin</success>
<attributes>[t, e, a, m, B]</attributes>
</string>
<fail/>
</department>
<team>
<try>teamB 1\nteamC 1\nacco</try>
<string>
<try>teamB 1\nteamC 1\nacco</try>
<success> 1\nteamC 1\naccountin</success>
<attributes>[t, e, a, m, B]</attributes>
</string>
<success>\nteamC 1\naccounting </success>
<attributes>[[t, e, a, m, B], 1]</attributes>
</team>
<employee>
<try>teamC 1\naccounting 1</try>
<fail/>
</employee>
<department>
<try>teamC 1\naccounting 1</try>
<string>
<try>teamC 1\naccounting 1</try>
<success> 1\naccounting 1 1000</success>
<attributes>[t, e, a, m, C]</attributes>
</string>
<fail/>
</department>
<team>
<try>teamC 1\naccounting 1</try>
<string>
<try>teamC 1\naccounting 1</try>
<success> 1\naccounting 1 1000</success>
<attributes>[t, e, a, m, C]</attributes>
</string>
<success>\naccounting 1 100000</success>
<attributes>[[t, e, a, m, C], 1]</attributes>
</team>
<employee>
<try>accounting 1 100000.</try>
<fail/>
</employee>
<department>
<try>accounting 1 100000.</try>
<string>
<try>accounting 1 100000.</try>
<success> 1 100000.00\nenginee</success>
<attributes>[a, c, c, o, u, n, t, i, n, g]</attributes>
</string>
<success>\nengineering 2 20000</success>
<attributes>[[a, c, c, o, u, n, t, i, n, g], 1, 100000]</attributes>
</department>
<employee>
<try>engineering 2 200000</try>
<fail/>
</employee>
<department>
<try>engineering 2 200000</try>
<string>
<try>engineering 2 200000</try>
<success> 2 200000.00\nAcmeCor</success>
<attributes>[e, n, g, i, n, e, e, r, i, n, g]</attributes>
</string>
<success>\nAcmeCorp 3\n</success>
<attributes>[[e, n, g, i, n, e, e, r, i, n, g], 2, 200000]</attributes>
</department>
<employee>
<try>AcmeCorp 3\n</try>
<fail/>
</employee>
<department>
<try>AcmeCorp 3\n</try>
<string>
<try>AcmeCorp 3\n</try>
<success> 3\n</success>
<attributes>[A, c, m, e, C, o, r, p]</attributes>
</string>
<fail/>
</department>
<team>
<try>AcmeCorp 3\n</try>
<string>
<try>AcmeCorp 3\n</try>
<success> 3\n</success>
<attributes>[A, c, m, e, C, o, r, p]</attributes>
</string>
<success>\n</success>
<attributes>[[A, c, m, e, C, o, r, p], 3]</attributes>
</team>
<employee>
<try></try>
<fail/>
</employee>
<department>
<try></try>
<string>
<try></try>
<fail/>
</string>
<fail/>
</department>
<team>
<try></try>
<string>
<try></try>
<fail/>
</string>
<fail/>
</team>
<corporation>
<try></try>
<string>
<try></try>
<fail/>
</string>
<fail/>
</corporation>
如果你修改你的 AST 以更好地模仿语法:
namespace client { namespace ast {
struct employee { int age; std::string surname; std::string forename; double salary; };
struct team { std::string name; int num_employees; };
struct department { std::string name; int num_teams; double budget; };
struct corporation { std::string name; int num_depts; };
struct input {
std::vector<employee> employees;
std::vector<team> teams;
std::vector<department> departments;
std::vector<corporation> corporations;
};
} }
现在,碰巧所有的属性强制规则都变得多余了,你可以简单地使用这个语法:
namespace parser
{
using namespace x3;
static auto string = lexeme[+graph];
static auto employee = int_ >> string >> string >> double_;
static auto team = string >> int_;
static auto department = string >> int_ >> double_;
static auto corporation = string >> int_;
auto const input = skip(blank) [
*(employee >> eol)
>> *(team >> eol)
>> *(department >> eol)
>> *(corporation >> eol)
];
}
这就是全部。我更喜欢帮助者在行结束时更具表现力:
static auto lines = [](auto p) { return *(p >> eol); };
auto const input = skip(blank) [
lines(employee)
>> lines(team)
>> lines(department)
>> lines(corporation)
];
注意
没有更多变体,打印就像您期望的那样简单:
for (auto& item : types.employees) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.teams) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.departments) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.corporations) { std::cout << boost::fusion::as_deque(item) << "\n"; }
团队/部门之间不再有歧义,因为它们只能按固定顺序出现
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace x3 = boost::spirit::x3;
namespace client { namespace ast {
struct employee { int age; std::string surname; std::string forename; double salary; };
struct team { std::string name; int num_employees; };
struct department { std::string name; int num_teams; double budget; };
struct corporation { std::string name; int num_depts; };
struct input {
std::vector<employee> employees;
std::vector<team> teams;
std::vector<department> departments;
std::vector<corporation> corporations;
};
} }
BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, age, surname, forename, salary)
BOOST_FUSION_ADAPT_STRUCT(client::ast::team, name, num_employees)
BOOST_FUSION_ADAPT_STRUCT(client::ast::department, name, num_teams, budget)
BOOST_FUSION_ADAPT_STRUCT(client::ast::corporation, name, num_depts)
BOOST_FUSION_ADAPT_STRUCT(client::ast::input, employees, teams, departments, corporations)
namespace client
{
namespace parser
{
namespace ascii = boost::spirit::x3::ascii;
using namespace x3;
auto const string
//= x3::rule<struct string_, std::string> {"string"}
= lexeme[+graph];
auto const employee
//= x3::rule<class employee, ast::employee>{"employee"}
= int_ >> string >> string >> double_;
auto const team
//= x3::rule<class team, ast::team>{"team"}
= string >> int_;
auto const department
//= x3::rule<class department, ast::department>{"department"}
= string >> int_ >> double_;
auto const corporation
//= x3::rule<class corporation, ast::corporation>{"corporation"}
= string >> int_;
auto lines = [](auto p) { return *(p >> eol); };
auto const input
//= x3::rule<struct _input, ast::input>{"input"}
= skip(blank) [
lines(employee)
>> lines(team)
>> lines(department)
>> lines(corporation)
];
}
}
int main()
{
namespace x3 = boost::spirit::x3;
using boost::spirit::x3::ascii::blank;
using x3::char_;
std::string const iss(R"(30 joe smith 100000.00
20 mary jo 100000.00
25 john doe 100000.00
teamA 1
teamB 1
teamC 1
accounting 1 100000.00
engineering 2 200000.00
AcmeCorp 3
)");
auto iter = iss.begin(), eof = iss.end();
client::ast::input types;
bool ok = parse(iter, eof, client::parser::input, types);
if (iter != eof) {
std::cout << "Remaining unparsed: '" << std::string(iter, eof) << "'\n";
}
std::cout << "Parsed: " << (100.0 * std::distance(iss.begin(), iter) / iss.size()) << "%\n";
std::cout << "ok = " << ok << std::endl;
for (auto& item : types.employees) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.teams) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.departments) { std::cout << boost::fusion::as_deque(item) << "\n"; }
for (auto& item : types.corporations) { std::cout << boost::fusion::as_deque(item) << "\n"; }
}
打印
Parsed: 100%
ok = 1
(30 joe smith 100000)
(20 mary jo 100000)
(25 john doe 100000)
(teamA 1)
(teamB 1)
(teamC 1)
(accounting 1 100000)
(engineering 2 200000)
(AcmeCorp 3)
关于c++ - X3,如何填充更复杂的 AST?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45124406/
我正在尝试检查 Go 源代码以制作一个工具。为此,我使用 ast.Inspect 函数。 我需要知道函数/方法内部如何使用 channel 。 我将此作为要检查的示例代码: package main
我正在为我自己的语言制作一个解释器作为一个业余爱好项目。目前我的解释器只是执行它看到的代码。我听说你应该让解析器从源代码生成 AST。所以我想知道,正如解析器所见,AST 实际上如何使事情比仅仅线性执
我正在为 JavaScript 实现一个突变测试工具。修改 AST 并针对修改后的代码执行测试用例。运行测试用例后,我想将修改后的 AST 恢复为原始 AST,以便我可以重复变异过程。但是,我不知道如
AST 文档:https://www.dartdocs.org/documentation/analyzer_experimental/0.8.0/analyzer/parseCompilationU
更新2:再次感谢@deepak-azad,我设法解决了我的问题:这里是主代码的链接:https://gist.github.com/1714641 更新:感谢@deepak-azad,我补充了代码,但
我正在编写一些 Go AST 代码,而编译器在这一行上令人窒息: var call ast.Expr = ast.CallExpr{Fun: ast.NewIdent("foo"), Args: []
我正在对 c 程序进行静态分析。我搜索了 antlr 网站,似乎没有合适的语法文件为 c 程序生成 ast。这是否意味着我必须从一开始就自己做。或者是有一个更快的方法。我还需要一个可以遍历解析器创建的
是否可以像这样采用带引号的 Elixir 表达式(AST 树): quote do: 1 + 1 => {:+, [context: Elixir, import: Kernel], [1, 1]}
我遇到了这个异常: unexpected AST node: query 我的查询是: SELECT u.user_id, u.username,u.email,u.phone,u.status,r
我是 Java 编程语言的初学者。我想从 java 源代码中提取 AST 并将 AST 打印到文件或标准输出。 我按照本教程学习了如何使用 AST。 http://www.programcreek.c
NodeVisitor 以深度优先的方式遍历 AST,并且在进入时仅访问每个节点一次。因此,用它做一些严肃的事情是有问题的。是否可以更改其默认行为? 最佳答案 也许有人会对一些草拟的例子感兴趣,如何做
目前,我正在努力用 Java 表示我用 SML 编写的 AST 树,这样我就可以随时用 Java 遍历它。 我想知道是否应该在 Java 中创建一个 Node 类,其中包含我想要表示的数据,以及一个数
我正在尝试修改/重构输入的 C 源代码。我试图在输入代码的每一行之后添加一个 printf 语句。 例如如果我的输入是 - void foo(){ // Sample input code
我目前正在使用 eclipse AST 来生成源代码。除了在大多数示例中,我是在独立应用程序中从头开始生成源代码,而不是在 eclipse 插件中。 当从 ASTParser 读取时,您可以通过调用
我有一个 HQL 查询: query = select item.itemNumber from items item where item.stock>0 and item.price it = q
根据 Om Next's documentation : query->ast (om.next/query->ast '[(:foo {:bar 1})]) Given a query expres
如果能学到一些有用的东西,我会非常感激,至于现在,我一直在盲目地行动。所以问题出在python的ast.NodeTransformer上。我想知道是否可以使用这种方式向现有类添加一个函数,而不是生气。
我们希望为 Elixir 开发一个静态代码分析器,以检测并发问题(主要是死锁和竞争条件)。我们对分析器的结构有了一些基本的了解,但我们的问题是哪种 AST 更适合这项任务。正如我们所了解的,Elixi
我在以下代码段中遇到错误 using (var session = Database.OpenSession()) { var q = from x in session.Query()
我正在使用以下 C# 代码: public IList GetAllByExpression(Expression> expression, int startIndex, int count, Fu
我是一名优秀的程序员,十分优秀!