2 Copyright (C) 2021 David Knapp (Cloudwalk)
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "darkplaces.h"
26 // Tell the user that their stuff is broken, why it's broken, and where it's broken, so hopefully they fix it.
27 void Parse_Error(struct qparser_state_s *state, qparser_err_t error)
36 Con_Printf(CON_ERROR "Parse Error: %s: Unexpected token '%c', line %i, column %i\n", state->name, *state->pos, state->line, state->col);
39 Con_Printf(CON_ERROR "Parse Error: %s: Unexpected end-of-file\n", state->name);
46 longjmp(parse_error, 1);
49 // Advance forward in the stream as many times as 'count', cleanly.
50 void Parse_Next(struct qparser_state_s *state, size_t count)
56 Parse_Error(state, PARSE_ERR_EOF);
59 // Skips newlines, and handles different line endings.
60 static qbool Parse_Newline(struct qparser_state_s *state)
62 if(*state->pos == '\n')
64 if(*state->pos == '\r')
66 if(*state->pos + 1 == '\n')
78 // Skip all whitespace, as we normally know it.
79 static inline void Parse_Whitespace(struct qparser_state_s *state)
81 // TODO: Some languages enforce indentation style. Add a callback to override this.
82 while(*state->pos == ' ' || *state->pos == '\t')
86 // Skips the current line. Only useful for comments.
87 static inline void Parse_SkipLine(struct qparser_state_s *state)
89 while(!Parse_Newline(state))
93 static inline qbool Parse_Skip_Comments(struct qparser_state_s *state)
95 // Make sure these are both defined (or both not defined)
96 if((state->callback.CheckComment_Multiline_Start != NULL) ^ (state->callback.CheckComment_Multiline_End != NULL))
97 Sys_Error("Parse_Skip_Comments: CheckComment_Multiline_Start (or _End) == NULL");
99 // Assume language doesn't support the respective comment types if one of these are NULL.
100 if(state->callback.CheckComment_SingleLine && state->callback.CheckComment_SingleLine(state))
101 Parse_SkipLine(state);
102 else if(state->callback.CheckComment_Multiline_Start && state->callback.CheckComment_Multiline_Start(state))
106 Parse_Next(state, 1);
107 Parse_Newline(state);
108 } while (state->callback.CheckComment_Multiline_End(state));
116 // Skip all whitespace.
117 static inline void Parse_Skip(struct qparser_state_s *state)
120 * Repeat this until we run out of whitespace, newlines, and comments.
121 * state->pos should be left on non-whitespace when this returns.
124 Parse_Whitespace(state);
125 } while (Parse_Skip_Comments(state) || Parse_Newline(state));
128 // Skip to the next token that isn't whitespace. Hopefully a valid one.
129 char Parse_NextToken(struct qparser_state_s *state)
132 * This assumes state->pos is already on whitespace. Most of the time this
133 * doesn't happen automatically, but advancing the pointer here would break
134 * comment and newline handling when it does happen automatically.