blob: 93127d5295224ea98e6c6d394f7b1d1c8ab08909 [file] [log] [blame]
Václav Kubernát8cd63422018-03-19 17:10:13 +01001/*
2 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
Václav Kubernátd6662962018-03-22 17:41:33 +01003 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
Václav Kubernát8cd63422018-03-19 17:10:13 +01004 *
5 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
6 *
7*/
8#pragma once
9#include <boost/spirit/home/x3.hpp>
Václav Kubernát8cd63422018-03-19 17:10:13 +010010#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
Václav Kubernátd6662962018-03-22 17:41:33 +010011
Václav Kubernát8cd63422018-03-19 17:10:13 +010012#include <boost/fusion/adapted/struct/adapt_struct.hpp>
13#include <boost/fusion/include/adapt_struct.hpp>
Václav Kubernátd6662962018-03-22 17:41:33 +010014#include <vector>
15
Václav Kubernát8cd63422018-03-19 17:10:13 +010016#include "CTree.hpp"
Václav Kubernát94938b72018-05-04 15:12:24 +020017#include "utils.hpp"
Václav Kubernát8cd63422018-03-19 17:10:13 +010018namespace x3 = boost::spirit::x3;
19namespace ascii = boost::spirit::x3::ascii;
20
21using x3::alpha;
22using x3::alnum;
23using x3::lit;
24using x3::char_;
25using x3::_attr;
26using x3::lexeme;
27using ascii::space;
28
Václav Kubernátd6662962018-03-22 17:41:33 +010029struct ParserContext {
Václav Kubernát8cd63422018-03-19 17:10:13 +010030 ParserContext(const CTree& tree);
31 const CTree& m_tree;
Václav Kubernátd6662962018-03-22 17:41:33 +010032 std::string m_curPath;
Václav Kubernát8cd63422018-03-19 17:10:13 +010033};
34
35struct parser_context_tag;
36
Václav Kubernátd6662962018-03-22 17:41:33 +010037struct container_ {
38 container_() {}
39 container_(const std::string& name);
40
41 bool operator==(const container_& b) const;
42
43 char m_first = ' ';
Václav Kubernát8cd63422018-03-19 17:10:13 +010044 std::string m_name;
45};
46
47BOOST_FUSION_ADAPT_STRUCT(container_, m_first, m_name)
48
Václav Kubernátd6662962018-03-22 17:41:33 +010049struct path_ {
50 bool operator==(const path_& b) const;
Václav Kubernát8cd63422018-03-19 17:10:13 +010051 std::vector<container_> m_nodes;
52};
53
54BOOST_FUSION_ADAPT_STRUCT(path_, m_nodes)
55
Václav Kubernátd6662962018-03-22 17:41:33 +010056struct cd_ {
57 bool operator==(const cd_& b) const;
Václav Kubernát8cd63422018-03-19 17:10:13 +010058 path_ m_path;
59};
60
61BOOST_FUSION_ADAPT_STRUCT(cd_, m_path)
62
63
Václav Kubernátd6662962018-03-22 17:41:33 +010064struct container_class {
Václav Kubernát8cd63422018-03-19 17:10:13 +010065 template <typename T, typename Iterator, typename Context>
Václav Kubernátd6662962018-03-22 17:41:33 +010066 void on_success(Iterator const&, Iterator const&, T& ast, Context const& context)
67 {
68 ast.m_name = ast.m_first + ast.m_name;
69 auto& parserContext = x3::get<parser_context_tag>(context);
70 const auto& tree = parserContext.m_tree;
71
72 if (tree.isContainer(parserContext.m_curPath, ast.m_name)) {
73 if (!parserContext.m_curPath.empty()) {
74 parserContext.m_curPath += '/';
75 }
76 parserContext.m_curPath += ast.m_name;
77 } else {
78 throw InvalidNodeException("No container with the name \"" + ast.m_name + "\" in \"" + parserContext.m_curPath + "\"");
79 }
80 }
Václav Kubernát8cd63422018-03-19 17:10:13 +010081};
82
Václav Kubernátd6662962018-03-22 17:41:33 +010083struct path_class {
Václav Kubernát8cd63422018-03-19 17:10:13 +010084 template <typename T, typename Iterator, typename Context>
Václav Kubernátd6662962018-03-22 17:41:33 +010085 void on_success(Iterator const&, Iterator const&, T&, Context const&)
86 {
87 }
Václav Kubernát8cd63422018-03-19 17:10:13 +010088};
89
Václav Kubernátd6662962018-03-22 17:41:33 +010090struct cd_class {
Václav Kubernát8cd63422018-03-19 17:10:13 +010091 template <typename T, typename Iterator, typename Context>
Václav Kubernátd6662962018-03-22 17:41:33 +010092 void on_success(Iterator const&, Iterator const&, T&, Context const&)
93 {
94 }
Václav Kubernát8cd63422018-03-19 17:10:13 +010095};
96
97
Václav Kubernátd6662962018-03-22 17:41:33 +010098x3::rule<container_class, container_> const container = "container";
99x3::rule<path_class, path_> const path = "path";
100x3::rule<cd_class, cd_> const cd = "cd";
Václav Kubernát8cd63422018-03-19 17:10:13 +0100101
Václav Kubernát8cd63422018-03-19 17:10:13 +0100102
Václav Kubernátd6662962018-03-22 17:41:33 +0100103auto const identifier =
104 lexeme[
105 ((alpha | char_("_")) >> *(alnum | char_("_") | char_("-") | char_(".")))
106 ];
Václav Kubernát8cd63422018-03-19 17:10:13 +0100107
108auto const container_def =
Václav Kubernátd6662962018-03-22 17:41:33 +0100109 identifier;
110
Václav Kubernát8cd63422018-03-19 17:10:13 +0100111auto const path_def =
112 container % '/';
113
114auto const cd_def =
115 lit("cd") >> path >> x3::eoi;
116
117BOOST_SPIRIT_DEFINE(container)
118BOOST_SPIRIT_DEFINE(path)
119BOOST_SPIRIT_DEFINE(cd)