KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pegtl/main.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 Roberto Fernandez Bautista <[email protected]>
5 * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
26#include <pegtl.hpp>
27#include <pegtl/contrib/analyze.hpp>
28#include <pegtl/contrib/parse_tree.hpp>
29#include <pegtl/contrib/parse_tree_to_dot.hpp>
30#include <pegtl/contrib/trace.hpp>
31
32#include <filesystem>
33#include <iostream>
34
35using namespace tao::pegtl;
36
37//-------------------- Grammar definition ----------------------------------------------------
38
39struct LINE_CONTINUATION : seq<one<'&'>, eol>{};
40
44template <typename... EXCLUSION_RULES>
45struct STR_SEGMENT_EXCLUDING : plus<not_at<sor<eolf, LINE_CONTINUATION, EXCLUSION_RULES...>>, any>{};
46
50template <typename... EXCLUSION_RULES>
51struct STRING_EXCLUDING : plus<STR_SEGMENT_EXCLUDING<EXCLUSION_RULES...>, opt<LINE_CONTINUATION>> {};
52
56template <char... CHAR_TO_FIND>
57struct spaced_ch : seq<star<space>, one<CHAR_TO_FIND...>>{};
58
59// Definition of "Format"
60// # Format <current format number>
61struct CURRENT_FORMAT_NUMBER : plus<digit> {};
62struct FORMAT : seq<bol, TAO_PEGTL_STRING( "# FORMAT" ), star<space>, CURRENT_FORMAT_NUMBER>{};
63
64
65// Definition of part
66//.<Part name>_[(<Part number>)][:<Part version>][;<Description>]
67 // string filters:
68struct PART_NAME_FILTER : sor<spaced_ch<'('>, spaced_ch<':'>, spaced_ch<';'>>{};
69struct PART_NUMBER_FILTER : one<')'>{};
71
72 // part elements:
73struct PART_NAME : STRING_EXCLUDING<PART_NAME_FILTER> {};
74struct PART_NUMBER : STRING_EXCLUDING<PART_NUMBER_FILTER> {};
75struct PART_VERSION : STRING_EXCLUDING<PART_VERSION_FILTER> {};
77
78 // the part itself
79struct PART : seq
80 <
81 bol,
82 one<'.'>,
83 PART_NAME,
84 opt<seq<spaced_ch<'('>, PART_NUMBER, one<')'>>>,
85 opt<seq<spaced_ch<':'>, PART_VERSION>>,
86 opt<seq<spaced_ch<';'>, PART_DESCRIPTION>>
87 >
88{};
89
90
91struct UNMATCHED_CONTENT : STRING_EXCLUDING<FORMAT, PART> {}; //@todo remove once parser is complete
92
93
94struct GRAMMAR : plus
95 <
96 sor<FORMAT, PART, UNMATCHED_CONTENT>,
97 opt<eolf>
98 >
99{};
100
101//--------------------------Simple selector definition -----------------------------
102// disable all parse nodes by default
103template< typename PEGTL_RULE > struct SIMPLE_SELECTOR : std::false_type {};
104// enable only nodes that match certain rules:
105template<> struct SIMPLE_SELECTOR< STR_SEGMENT_EXCLUDING< PART_NAME_FILTER > > : std::true_type {};
106template<> struct SIMPLE_SELECTOR< STR_SEGMENT_EXCLUDING< PART_NUMBER_FILTER > > : std::true_type {};
107template<> struct SIMPLE_SELECTOR< STR_SEGMENT_EXCLUDING< PART_VERSION_FILTER > > : std::true_type {};
108template<> struct SIMPLE_SELECTOR< STR_SEGMENT_EXCLUDING<> > : std::true_type {};
109template<> struct SIMPLE_SELECTOR< CURRENT_FORMAT_NUMBER > : std::true_type {};
110template<> struct SIMPLE_SELECTOR< FORMAT > : std::true_type {};
111template<> struct SIMPLE_SELECTOR< PART > : std::true_type {};
112template<> struct SIMPLE_SELECTOR< PART_NAME > : std::true_type {};
113template<> struct SIMPLE_SELECTOR< PART_NUMBER > : std::true_type {};
114template<> struct SIMPLE_SELECTOR< PART_VERSION > : std::true_type {};
115template<> struct SIMPLE_SELECTOR< PART_DESCRIPTION > : std::true_type {};
116template<> struct SIMPLE_SELECTOR< UNMATCHED_CONTENT > : std::true_type {}; //@todo remove
117
118
119//--------------------------Complex selector definition -----------------------------
120// Helper function to clean up the tree
121struct FOLD_CONTENT : parse_tree::apply<FOLD_CONTENT>
122{
123 template <typename Node>
124 static void transform( Node& n )
125 {
126 if( n->children.size() == 1 )
127 {
128 n->children.pop_back();
129 }
130 else if( n->children.size() != 0 )
131 {
132 n->remove_content();
133 }
134 }
135};
136
137
138template <typename PEGTL_RULE>
139using COMPLEX_SELECTOR = parse_tree::selector<
140 PEGTL_RULE,
141 parse_tree::store_content::on<
147 UNMATCHED_CONTENT //@todo remove when parser complete. For debugging only
148 >,
149 parse_tree::remove_content::on<
150 FORMAT,
151 PART
152 >,
153 parse_tree::apply< FOLD_CONTENT >::on<
154 PART_NAME,
158 >
159 >;
160
161
162int main( int argc, char** argv )
163{
164 // .\test_pegtl.exe complex my_file.lib | dot -Tsvg > output.svg; .\output.svg
165
166 if( argc != 3 )
167 {
168 printf( "usage: %s <complex|simple> <filename>", argv[0] );
169 return -1;
170 }
171
172 std::string chosen_selector = argv[1];
173 std::filesystem::path filepath( argv[2] );
174
175 file_input in( filepath );
176
177 const std::size_t issues = tao::pegtl::analyze<GRAMMAR>();
178
179 if( issues > 0 )
180 {
181 std::cout << "\n***ERROR***: " << issues << " issues found in the grammar!\n";
182 return -1;
183 }
184
185 std::unique_ptr<parse_tree::node> root;
186
187 if( chosen_selector == "complex" )
188 {
189 root = parse_tree::parse<GRAMMAR, COMPLEX_SELECTOR>( in );
190 }
191 else if( chosen_selector == "simple" )
192 {
193 root = parse_tree::parse<GRAMMAR, SIMPLE_SELECTOR>( in );
194 }
195 else
196 {
197 printf( "Invalid selector '%s' requested. Valid values are: complex or simple. \n",
198 argv[1] );
199 printf( "usage: %s <complex|simple> <filename>\n", argv[0] );
200 }
201
202
203 if( root )
204 {
205 parse_tree::print_dot( std::cout, *root );
206 }
207 else
208 {
209 std::cout << "\n***ERROR***: No root tree node!\n";
210
211 // lets print out the trace for debugging
212 standard_trace<GRAMMAR>( in );
213 }
214
215 return 0;
216}
main()
parse_tree::selector< PEGTL_RULE, parse_tree::store_content::on< STR_SEGMENT_EXCLUDING< PART_NAME_FILTER >, STR_SEGMENT_EXCLUDING< PART_NUMBER_FILTER >, STR_SEGMENT_EXCLUDING< PART_VERSION_FILTER >, STR_SEGMENT_EXCLUDING<>, CURRENT_FORMAT_NUMBER, UNMATCHED_CONTENT >, parse_tree::remove_content::on< FORMAT, PART >, parse_tree::apply< FOLD_CONTENT >::on< PART_NAME, PART_NUMBER, PART_VERSION, PART_DESCRIPTION > > COMPLEX_SELECTOR
Definition: pegtl/main.cpp:159
static void transform(Node &n)
Definition: pegtl/main.cpp:124
Any text can span multiple lines using '&'.
Definition: pegtl/main.cpp:39
String with optional line continuation and exclusion rules.
Definition: pegtl/main.cpp:51
String segment( no line continuation ), with exclusion rules.
Definition: pegtl/main.cpp:45
Control character with or without preceding whitespace.
Definition: pegtl/main.cpp:57