RayZaler 0.1
The free opto-mechanical simulation framework
ParserContext.h
1//
2// Copyright (c) 2024 Gonzalo José Carracedo Carballal
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as
6// published by the Free Software Foundation, either version 3 of the
7// License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this program. If not, see
16// <http://www.gnu.org/licenses/>
17//
18
19#ifndef _PARSER_CONTEXT_H
20#define _PARSER_CONTEXT_H
21
22#include <Vector.h>
23#include <list>
24#include <string>
25#include <variant>
26#include <Recipe.h>
27#include <stdexcept>
28
29#define PARSER_CONTEXT_MAX_RECURSION 20
30
31namespace RZ {
32 class ParserContext;
33}
34
35int yylex(RZ::ParserContext *ctx);
36void yyerror(RZ::ParserContext *ctx, const char *msg);
37int yyparse(RZ::ParserContext *ctx);
38
39namespace RZ {
41 std::string name;
42 std::string min_expr;
43 std::string max_expr;
44 std::string assign_expr;
45 };
46
47 typedef std::pair<std::string, std::string> ParserAssignExpr;
48 typedef std::list<ParserAssignExpr> ParserAssignList;
49
51
52 class ParserError : public std::runtime_error {
53 std::string m_msg;
54 std::string m_file;
55 int m_line = 0;
56 int m_char = 0;
57
58 public:
60 ParserError(std::string const &, int, int, std::string const &);
61
62 inline int
63 line() const
64 {
65 return m_line;
66 }
67
68 inline int
69 col() const
70 {
71 return m_char;
72 }
73
74 inline std::string const &
75 message() const
76 {
77 return m_msg;
78 }
79
80 inline std::string const &
81 file() const
82 {
83 return m_file;
84 }
85 };
86
87 typedef std::variant<
89 std::string,
91 std::list<std::string>,
92 ParserAssignExpr,
93 ParserAssignList,
94 RecipeContextType> BaseValueType;
95
96 class ValueType : public BaseValueType {
97 using BaseValueType::BaseValueType;
98
99 public:
100 static inline ValueType
101 undefined()
102 {
103 return ValueType();
104 }
105
106 inline bool
107 isUndefined() const
108 {
109 return index() == 0;
110 }
111
112 template<typename T>
113 inline operator T() const
114 {
115 return std::get<T>(*this);
116 }
117
118 template<typename T>
119 inline T &value()
120 {
121 return std::get<T>(*this);
122 }
123
124 inline std::string &
125 str()
126 {
127 return value<std::string>();
128 }
129
130 inline std::list<std::string> &
131 strList()
132 {
133 return value<std::list<std::string>>();
134 }
135 };
136
137
138 enum ParserState {
139 SEARCHING,
140 READING_IDENTIFIER,
141 READING_NUMBER,
142 READING_OPERATOR,
143 READING_STRING
144 };
145
147 std::string m_file = "<no file>";
148 ParserContext *m_parentContext = nullptr;
149 Recipe *m_rootRecipe = nullptr;
150 Recipe *m_recipe = nullptr;
151 std::string m_buf;
152 std::string m_lastToken;
153 std::list<std::set<std::string>> m_includeOnceContexts;
154 std::set<std::string> m_includeOnce;
155 std::list<std::string> m_searchPaths;
156
157 int m_recursion = 0;
158 int m_line = 0;
159 int m_char = 0;
160 bool m_newLine = false;
161 int m_tokLine = 0;
162 int m_tokChar = 0;
163 bool m_commentFound = false;
164 bool m_escaped = false;
165 bool m_havePrevious = false;
166 int m_saved = '\0';
167 int m_last = '\0';
168
169 std::list<ValueType> m_values;
170
171 bool isTerminator(int) const;
172 static bool isOperatorChar(int);
173 static bool isIdStartChar(int);
174 static bool isIdChar(int);
175 static bool isValidStartChar(int);
176 static void parseDOFDecl(ParserDOFDecl const &, Real &, Real &, Real &);
177 static bool looksLikeNumber(std::string const &);
178
179 int getChar();
180 bool returnChar();
181 bool lexNonString(int c);
182 bool lexString(int c);
183 std::string resolvePath(std::string const &path);
184 friend int ::yylex(ParserContext *ctx);
185 friend void ::yyerror(ParserContext *ctx, const char *msg);
186 friend int ::yyparse(RZ::ParserContext *ctx);
187
188 void pushIncludeOnce();
189 bool popIncludeOnce();
190
191 protected:
192 int tokenType() const;
193 std::string token() const;
194 int lex();
195 void error(const char *msg);
196
197 void import(std::string const &);
198 void script(std::string const &);
199 void registerParameter(ParserDOFDecl const &);
200 void registerDOF(ParserDOFDecl const &);
201 void registerVariable(ParserAssignExpr const &);
202 void registerPath(std::string const &name, std::list<std::string> const &);
203 void pushFrame(RecipeContextType, std::string const &name, ParserAssignList const & );
204 void pushOnPort(std::string const &name, std::string const &port);
205 void pushPort(std::string const &port);
206 void pushElementDefinition(std::string const &);
207 void popElementDefinition();
208 void popFrame();
209 void defineElement(std::string const &name, std::string const &factory, ParserAssignList const & = ParserAssignList());
210 void debugParamList(ParserAssignList const &);
211 bool alreadyImported(std::string const &path) const;
212 void addImportOnce(std::string const &path);
213
214 template<class T>
215 ValueType &value()
216 {
217 m_values.push_back(T());
218 return m_values.back();
219 }
220
221 ValueType &
222 dofDecl(
223 std::string const &name,
224 std::string const &min = "",
225 std::string const &max = "")
226 {
227 auto &decl = value<ParserDOFDecl>();
228 decl.value<ParserDOFDecl>().name = name;
229 decl.value<ParserDOFDecl>().min_expr = min;
230 decl.value<ParserDOFDecl>().max_expr = max;
231 return decl;
232 }
233
234 ValueType &
235 pathList(std::string const &first)
236 {
237 auto &val = value<std::list<std::string>>();
238 val.value<std::list<std::string>>().push_back(first);
239 return val;
240 }
241
242 ValueType &
243 contextType(RecipeContextType ctxType)
244 {
245 auto &val = value<RecipeContextType>();
246 val = ctxType;
247 return val;
248 }
249
250 ValueType &
251 assignExpr(std::string const &param, std::string const &expr)
252 {
253 auto &val = value<ParserAssignExpr>();
254 val.value<ParserAssignExpr>().first = param;
255 val.value<ParserAssignExpr>().second = expr;
256 return val;
257 }
258
259 ValueType &
260 assignString(std::string const &param, std::string const &str)
261 {
262 auto &val = value<ParserAssignExpr>();
263 val.value<ParserAssignExpr>().first = param;
264 val.value<ParserAssignExpr>().second = "\"" + str + "\"";
265 return val;
266 }
267
268 ValueType &
269 assignExprList(ParserAssignExpr const &expr)
270 {
271 auto &val = value<ParserAssignList>();
272 val.value<ParserAssignList>().push_back(expr);
273 return val;
274 }
275
276 ValueType &
277 assignExprList(std::string const &param, std::string const &expr)
278 {
279 auto &val = value<ParserAssignList>();
280 val.value<ParserAssignList>().push_back(ParserAssignExpr(param, expr));
281 return val;
282 }
283
284 ValueType &
285 assignStringList(std::string const &param, std::string const &str)
286 {
287 auto &val = value<ParserAssignList>();
288 val.value<ParserAssignList>().push_back(
289 ParserAssignExpr(param, '"' + str + '"'));
290 return val;
291 }
292
293 public:
294 ParserContext(Recipe *recipe, int recursion = 0);
295 ParserContext(ParserContext *parent, int recursion);
296
297 inline Recipe *
298 recipe() const
299 {
300 return m_recipe;
301 }
302
303 inline Recipe *
304 rootRecipe() const
305 {
306 return m_rootRecipe;
307 }
308
309 void setFile(std::string const &);
310 bool parse();
311 void addSearchPath(std::string const &path);
312 void inheritSearchPaths(ParserContext const *);
313 virtual int read() = 0;
314
315 };
316
318 using ParserContext::ParserContext;
319 FILE *m_fp = stdin;
320
321 public:
322 void setFile(FILE *fp, std::string const &name);
323 virtual int read() override;
324 virtual ~FileParserContext();
325 };
326
328 using ParserContext::ParserContext;
329 std::string m_contents;
330 unsigned int m_ptr = 0;
331
332 public:
333 void setContents(std::string const &contents, std::string const &name);
334 virtual int read() override;
335 virtual ~StringParserContext();
336 };
337}
338
339#endif // _PARSER_CONTEXT_H
Definition: ParserContext.h:317
Definition: ParserContext.h:146
Definition: ParserContext.h:52
Definition: Recipe.h:142
Definition: ParserContext.h:327
Definition: ParserContext.h:96
Definition: ParserContext.h:40
Definition: ParserContext.h:50