-
Notifications
You must be signed in to change notification settings - Fork 26
/
parser.h
231 lines (211 loc) · 6.9 KB
/
parser.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/*
* Calvin Neo
* Copyright (C) 2016 Calvin Neo <calvinneo@calvinneo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include <vector>
#include <iostream>
#include "tokenizer.h"
struct ParseNode {
void addpointer(ParseNode * ptrn, bool add_back = true);
void addchild(const ParseNode & n, bool add_back = true);
template <typename ... Args>
void addlist(const ParseNode & x, Args&& ... args) {
addchild(x);
addlist(std::forward<Args>(args)...);
}
template <typename ... Args>
void addlist(const ParseNode & x) {
addchild(x);
}
template<typename Iterator>
void addrange(Iterator begin, Iterator end) {
for (Iterator iter = begin; iter != end; iter++)
{
addchild(**iter);
}
}
void replace(int childid, const ParseNode & pn);
inline ParseNode & get(int child_index) {
return *(this->child[child_index]);
}
inline const ParseNode & get(int child_index) const {
return *(this->child[child_index]);
}
inline const ParseNode & const_get(int child_index) const {
return *(const_cast<const ParseNode *>(this)->child[child_index]);
}
void setattr(struct ParseAttr * pa);
const std::string & to_string() const { return fs.CurrentTerm.what; }
int length() const { return (int)child.size(); }
TokenMeta_T & get_token() { return this->fs.CurrentTerm.token; }
const TokenMeta_T & get_token() const { return this->fs.CurrentTerm.token; }
std::string & get_what() { return this->fs.CurrentTerm.what; }
const std::string & get_what() const { return this->fs.CurrentTerm.what; }
template <typename ... Args>
bool token_equals(const TokenMeta_T & token, Args&& ... args) const {
return (this->get_token() == token) || token_equals(std::forward<Args>(args)...);
}
bool token_equals(const TokenMeta_T & token) const { return this->get_token() == token; };
std::vector<ParseNode *>::iterator begin() { return child.begin(); }
std::vector<ParseNode *>::iterator end() { return child.end(); }
std::vector<ParseNode *>::const_iterator begin() const { return child.begin(); }
std::vector<ParseNode *>::const_iterator end() const { return child.end(); }
ParseNode(const ParseNode &);
//ParseNode(ParseNode &&) noexcept = delete;
ParseNode & operator= (const ParseNode &);
ParseNode() : father(nullptr), attr(nullptr) {}; // -Wreorder
ParseNode(const TokenizerState & s, ParseNode * fa, struct ParseAttr * att = nullptr) : fs(s) , father(fa), attr(att) {}
~ParseNode();
public: // temporary
TokenizerState fs;
std::vector<ParseNode *> child;
struct ParseNode * father = nullptr;
struct ParseAttr * attr = nullptr;
};
int parse(std::string code);
void preorder(ParseNode * ptree);
TokenizerState & get_tokenizer_state();
void print_error(const std::string & error_info, const ParseNode & node);
void print_error(const std::string & error_info);
void fatal_error(const std::string & error_info, const ParseNode & node);
void fatal_error(const std::string & error_info);
// yacc part code
// implement in for90.y
#define USE_TRIVIAL
#define USE_REUSE
#if defined USE_TRIVIAL
#define YYSTYPE ParseNode*
// X must be a newly-created ParseNode generated by `gen_` functions
// whose all childs are copied from arguments which are passed to `gen_` in the form of `ARG_IN`
#define RETURN_NT(X) new ParseNode(X)
inline ParseNode & YY2ARG(YYSTYPE X) {
// #define YY2ARG (X == nullptr? ParseNode(): *X)
if (X == nullptr)
{
fatal_error("null ParseNode during parsing");
}
else {
return *X;
}
}
#define ARG_IN const ParseNode &
#define ARG_OUT ParseNode &
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x, Args&& ... args) {
// for others, clear, because it's not needed as child
delete x;
x = nullptr;
CLEAN_DELETE(std::forward<Args>(args)...);
}
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x) {
delete x;
x = nullptr;
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x, Args&& ... args) {
// for some, do not clear, reuse as child
CLEAN_REUSE(std::forward<Args>(args)...);
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x) {
}
#elif defined USE_POINTER
#define YYSTYPE ParseNode*
#define RETURN_NT(X) new ParseNode(X)
inline ParseNode & YY2ARG(YYSTYPE X) {
// #define YY2ARG (X == nullptr? ParseNode(): *X)
if (X == nullptr)
{
fatal_error("null ParseNode during parsing");
return ParseNode{};
}
else {
return *X;
}
}
#define ARG_IN const ParseNode &
#define ARG_OUT ParseNode &
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x, Args&& ... args) {
}
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x) {
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x, Args&& ... args) {
CLEAN_REUSE(std::forward<Args>(args)...);
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x) {
}
#else // use RAII
#define YYSTYPE ParseNode
#define RETURN_NT(X) X
#define YY2ARG(X) X
#define ARG_IN const ParseNode &
#define ARG_OUT ParseNode &
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x, Args&& ... args) {
// do nothing
}
template <typename ... Args>
void CLEAN_DELETE(YYSTYPE & x) {
// do nothing
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x, Args&& ... args) {
// do nothing
CLEAN_REUSE(std::forward<Args>(args)...);
}
template <typename ... Args>
void CLEAN_REUSE(YYSTYPE & x) {
// do nothing
}
#endif
std::string tabber(const std::string &, bool tail_crlf = true); // add tab(`\t`) into the front of each line
ParseNode flatten_bin(const ParseNode & pn, bool recursion_direction_right);// eliminate left/right recursion of an binary tree
void flatten_bin_inplace(ParseNode & pn, bool recursion_direction_right); // eliminate left/right recursion of an binary tree in place
/***************
* by testing
* a 202kb code file will cause `sprintf` erase data elsewhere(when `MAX_CODE_LENGTH` is 32767)
* `MAX_CODE_LENGTH` should be enough
***************/
#define MAX_CODE_LENGTH 262143
struct ParseConfig {
bool for90 = true;
bool isdebug = false;
/***************
* source code from file/stdin
***************/
bool hasfile = false;
bool usefor = true;
bool usefarray = true;
/***************
* set true to add full qualifier for fortran's intrinsic functions
* e.g.
* for90std::forwritefree(...)
***************/
bool full_quali = false;
};
#ifdef _DEBUG
#define WHENDEBUG(THEN, ELSE) THEN
#else
#define WHENDEBUG(THEN, ELSE) ELSE
#endif // _DEBUG