2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined(INCLUDED_SCRIPT_SCRIPTTOKENISER_H)
23 #define INCLUDED_SCRIPT_SCRIPTTOKENISER_H
25 #include "iscriplib.h"
27 class ScriptTokeniser : public Tokeniser
40 typedef bool (ScriptTokeniser::*Tokenise)(char c);
44 SingleCharacterInputStream<TextInputStream> m_istream;
45 std::size_t m_scriptline;
46 std::size_t m_scriptcolumn;
48 char m_token[MAXTOKEN];
59 CharType charType(const char c)
63 case '\n': return eNewline;
64 case '"': return eCharQuote;
65 case '/': return eCharSolidus;
66 case '*': return eCharStar;
67 case '{': case '(': case '}': case ')': case '[': case ']': case ',': case ':': return (m_special) ? eCharSpecial : eCharToken;
81 void push(Tokenise state)
83 ASSERT_MESSAGE(m_state != m_stack + 2, "token parser: illegal stack push");
88 ASSERT_MESSAGE(m_state != m_stack, "token parser: illegal stack pop");
91 void add(const char c)
93 if(m_write < m_token + MAXTOKEN - 1)
100 ASSERT_MESSAGE(m_write > m_token, "no char to remove");
104 bool tokeniseDefault(char c)
111 globalErrorStream() << Unsigned(getLine()) << ":" << Unsigned(getColumn()) << ": unexpected end-of-line before token\n";
117 push(Tokenise(&ScriptTokeniser::tokeniseToken));
121 push(Tokenise(&ScriptTokeniser::tokeniseSpecial));
125 push(Tokenise(&ScriptTokeniser::tokeniseQuotedToken));
128 push(Tokenise(&ScriptTokeniser::tokeniseSolidus));
135 bool tokeniseToken(char c)
144 m_emit = true; // emit token
147 #if 0 //SPoG: ignore comments in the middle of tokens.
148 push(Tokenise(&ScriptTokeniser::tokeniseSolidus));
160 bool tokeniseQuotedToken(char c)
167 globalErrorStream() << Unsigned(getLine()) << ":" << Unsigned(getColumn()) << ": unexpected end-of-line in quoted token\n";
180 push(Tokenise(&ScriptTokeniser::tokeniseEndQuote));
187 bool tokeniseSolidus(char c)
197 m_emit = true; // emit single slash
206 push(Tokenise(&ScriptTokeniser::tokeniseComment));
207 break; // dont emit single slash
210 push(Tokenise(&ScriptTokeniser::tokeniseBlockComment));
211 break; // dont emit single slash
217 bool tokeniseComment(char c)
222 if(state() == Tokenise(&ScriptTokeniser::tokeniseToken))
225 m_emit = true; // emit token immediatly preceding comment
230 bool tokeniseBlockComment(char c)
235 push(Tokenise(&ScriptTokeniser::tokeniseEndBlockComment));
239 bool tokeniseEndBlockComment(char c)
245 if(state() == Tokenise(&ScriptTokeniser::tokeniseToken))
248 m_emit = true; // emit token immediatly preceding comment
250 break; // dont emit comment
252 break; // no state change
255 push(Tokenise(&ScriptTokeniser::tokeniseBlockComment));
260 bool tokeniseEndQuote(char c)
263 m_emit = true; // emit quoted token
266 bool tokeniseSpecial(char c)
269 m_emit = true; // emit single-character token
273 /// Returns true if a token was successfully parsed.
281 if(!((*this).*state())(c))
303 m_eof = !m_istream.readChar(m_current);
305 return m_write != m_token;
308 const char* fillToken()
325 ScriptTokeniser(TextInputStream& istream, bool special)
335 m_stack[0] = Tokenise(&ScriptTokeniser::tokeniseDefault);
336 m_eof = !m_istream.readChar(m_current);
337 m_token[MAXTOKEN - 1] = '\0';
347 const char* getToken()
359 ASSERT_MESSAGE(!m_unget, "can't unget more than one token");
362 std::size_t getLine() const
366 std::size_t getColumn() const
368 return m_scriptcolumn;
373 inline Tokeniser& NewScriptTokeniser(TextInputStream& istream)
375 return *(new ScriptTokeniser(istream, true));
378 inline Tokeniser& NewSimpleTokeniser(TextInputStream& istream)
380 return *(new ScriptTokeniser(istream, false));