source: trunk/AISC/aisc_parser.h

Last change on this file was 17877, checked in by westram, 5 years ago
File size: 6.1 KB
Line 
1//   Coded by Ralf Westram (coder@reallysoft.de) in March 2011   //
2//   Institute of Microbiology (Technical University Munich)     //
3//   http://www.arb-home.de/                                     //
4
5#ifndef AISC_PARSER_H
6#define AISC_PARSER_H
7
8#ifndef AISC_TOKEN_H
9#include "aisc_token.h"
10#endif
11#ifndef AISC_LOCATION_H
12#include "aisc_location.h"
13#endif
14#ifndef AISC_INLINE_H
15#include "aisc_inline.h"
16#endif
17#ifndef ATTRIBUTES_H
18#include <attributes.h>
19#endif
20
21enum CommandType {
22    NO_COMMAND,
23    CT_IF = 1,
24    CT_ENDIF,
25    CT_ELSE,
26    CT_FOR,
27    CT_NEXT,
28    CT_ENDFOR,
29    CT_ELSEIF,
30    CT_FUNCTION,
31    CT_LABEL,
32    CT_OTHER_CMD,
33};
34
35struct Code {
36    Code *next;
37    char *str;
38
39    Location source;
40
41    CommandType    command;
42    const Command *cmd;
43
44    mutable struct for_data *fd;
45
46    Code *IF;
47    Code *ELSE;
48    Code *ENDIF;
49    Code *FOR;
50    Code *NEXT;
51    Code *ENDFOR;
52
53    Code() :
54        next(NULp),
55        str(NULp),
56        // default Location is invalid (ok for default Code)
57        command(NO_COMMAND),
58        cmd(NULp),
59        fd(NULp),
60        IF(NULp),
61        ELSE(NULp),
62        ENDIF(NULp),
63        FOR(NULp),
64        NEXT(NULp),
65        ENDFOR(NULp)
66    {}
67
68    Code(const Code& other) :
69        next(other.next),
70        str(nulldup(other.str)),
71        source(other.source),
72        command(other.command),
73        cmd(other.cmd),
74        fd(other.fd),
75        IF(other.IF),
76        ELSE(other.ELSE),
77        ENDIF(other.ENDIF),
78        FOR(other.FOR),
79        NEXT(other.NEXT),
80        ENDFOR(other.ENDFOR)
81    {}
82
83    DECLARE_ASSIGNMENT_OPERATOR(Code);
84    ~Code() {
85        delete next;
86        free(str);
87    }
88
89    void set_command(CommandType command_, const char *args) {
90        command = command_;
91        SKIP_SPACE_LF(args);
92        freedup(str, args);
93    }
94
95    void print_error_internal(const char *err, const char *launcher_file, int launcher_line) const {
96        source.print_error_internal(err, launcher_file, launcher_line);
97    }
98    void print_warning_internal(const char *warn, const char *launcher_file, int launcher_line) const {
99        source.print_warning_internal(warn, launcher_file, launcher_line);
100    }
101};
102
103
104class Parser : virtual Noncopyable {
105    // used to parse 'Data' and 'Code'
106
107    int         lastchar;
108    const char *last_line_start;
109
110    Location loc;
111
112    int error_flag;
113
114    void get_byte(const char *& io) {
115        lastchar = *(io++);
116        if (is_LF(lastchar)) {
117            last_line_start = io;
118            ++loc;
119        }
120    }
121
122    const char *currentLocation(const char *io);
123
124    void p_err(const char *io, const char *error);
125    void p_errf(const char *io, const char *formatString, ...) __ATTR__FORMAT_MEMBER(2);
126
127    void p_err_empty_braces(const char *io) { p_err(io, "{} found, missing contents"); }
128    void p_err_exp_line_terminator(const char *io) { p_err(io, "missing ',' or ';' or 'newline'"); }
129    void p_err_ill_atWord(const char *io) { p_err(io, "only header definitions may start with '@'"); }
130    void p_err_exp_atWord(const char *io) { p_err(io, "all words in header-definitions have to start with '@'"); }
131
132    void p_err_expected(const char *io, const char *expect)                     { p_errf(io, "Expected to see %s", expect); }
133    void p_err_exp_but_saw(const char *io, const char *expect, const char *saw) { p_errf(io, "Expected to see %s, but saw %s", expect, saw); }
134
135    void p_err_exp_string_but_saw(const char *io, const char *saw) { p_err_exp_but_saw(io, "string", saw); }
136    void p_err_exp_but_saw_EOF(const char *io, const char *expect) { p_err_exp_but_saw(io, expect, "end of file"); }
137
138    inline void expect_line_terminator(const char *in) {
139        if (!is_SEP_LF_EOS(lastchar)) p_err_exp_line_terminator(in);
140    }
141
142    void expect_and_skip_closing_brace(const char *& in, const char *openingBraceLocation) {
143        if (lastchar != '}') {
144            p_err_expected(in, "'}'");
145            fprintf(stderr, "%s: opening brace was here\n", openingBraceLocation);
146        }
147        get_byte(in);
148    }
149    void expect_and_skip(const char *& in, char expect) {
150        if (lastchar != expect) {
151            char buf[] = "'x'";
152            buf[1]     = expect;
153            p_err_expected(in, buf);
154        }
155        get_byte(in);
156    }
157
158    void skip_over_spaces(const char *& in) { while (is_SPACE(lastchar)) get_byte(in); }
159    void skip_over_spaces_and_comments(const char *& in) {
160        skip_over_spaces(in);
161        if (lastchar == '#') { // comment -> skip rest of line
162            while (!is_LF_EOS(lastchar)) get_byte(in);
163        }
164    }
165    void skip_over_spaces_and_comments_multiple_lines(const char *& in) {
166        while (1) {
167            skip_over_spaces_and_comments(in);
168            if (!is_LF(lastchar)) break;
169            get_byte(in);
170        }
171    }
172
173    void copyWordTo(const char*& in, char*& out) {
174        while (!is_SPACE_SEP_LF_EOS(lastchar)) {
175            *(out++) = lastchar;
176            get_byte(in);
177        }
178    }
179
180    void  copyTillQuotesTo(const char*& in, char*& out);
181    char *readWord(const char *& in);
182
183    char *SETSOURCE(const char *& in, enum TOKEN& foundTokenType);
184    char *parse_token(const char *& in, enum TOKEN& foundTokenType);
185
186    Token *parseBrace(const char *& in, const char *key);
187    TokenList *parseTokenList(const char *& in, class HeaderList& headerList);
188
189public:
190    Parser() {
191        lastchar = ' ';
192        last_line_start = NULp;
193        error_flag      = 0;
194    }
195
196    int get_sourceline() const { return loc.get_linenr(); }
197    const char *get_sourcename() const { return loc.get_path(); }
198    const Location& get_location() const { return loc; }
199
200    void set_source(const Location& other) {
201        aisc_assert(loc != other);
202        loc = other;
203    }
204    void set_source(const char *path, int linenumber) {
205        set_source(Location(linenumber, path));
206    }
207
208    void set_line_start(const char *start, int offset_in_line) {
209        last_line_start = start-offset_in_line;
210        lastchar        = ' ';
211    }
212
213    TokenListBlock *parseTokenListBlock(const char *& in);
214    class Code *parse_program(const char *in, const char *filename);
215};
216
217
218#else
219#error aisc_parser.h included twice
220#endif // AISC_PARSER_H
Note: See TracBrowser for help on using the repository browser.