4 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "tinygettext/tinygettext.hpp"
28 #include "physfs/physfs_stream.hpp"
31 #include "obstack/obstackpp.hpp"
33 #include "gameconfig.hpp"
38 Parser::Parser(bool translate)
39 : lexer(0), dictionary_manager(0), dictionary(0)
42 dictionary_manager = new TinyGetText::DictionaryManager();
43 dictionary_manager->set_charset("UTF-8");
44 if (config && (config->locale != "")) dictionary_manager->set_language(config->locale);
52 obstack_free(&obst, NULL);
54 delete dictionary_manager;
57 static std::string dirname(const std::string& filename)
59 std::string::size_type p = filename.find_last_of('/');
60 if(p == std::string::npos)
63 return filename.substr(0, p+1);
67 Parser::parse(const std::string& filename)
69 IFileStreambuf ins(filename);
70 std::istream in(&ins);
73 std::stringstream msg;
74 msg << "Parser problem: Couldn't open file '" << filename << "'.";
75 throw std::runtime_error(msg.str());
78 if(dictionary_manager) {
79 dictionary_manager->add_directory(dirname(filename));
80 dictionary = & (dictionary_manager->get_dictionary());
83 return parse(in, filename);
87 Parser::parse(std::istream& stream, const std::string& sourcename)
90 lexer = new Lexer(stream);
92 this->filename = sourcename;
93 token = lexer->getNextToken();
95 Lisp* result = new(obst) Lisp(Lisp::TYPE_CONS);
96 result->v.cons.car = read();
97 result->v.cons.cdr = 0;
106 Parser::parse_error(const char* msg) const
108 std::stringstream emsg;
109 emsg << "Parse Error at '" << filename << "' line " << lexer->getLineNumber()
111 throw std::runtime_error(emsg.str());
119 case Lexer::TOKEN_EOF: {
120 parse_error("Unexpected EOF.");
122 case Lexer::TOKEN_CLOSE_PAREN: {
123 parse_error("Unexpected ')'.");
125 case Lexer::TOKEN_OPEN_PAREN: {
126 result = new(obst) Lisp(Lisp::TYPE_CONS);
128 token = lexer->getNextToken();
129 if(token == Lexer::TOKEN_CLOSE_PAREN) {
130 result->v.cons.car = 0;
131 result->v.cons.cdr = 0;
135 if(token == Lexer::TOKEN_SYMBOL &&
136 strcmp(lexer->getString(), "_") == 0) {
137 // evaluate translation function (_ str) in place here
138 token = lexer->getNextToken();
139 if(token != Lexer::TOKEN_STRING)
140 parse_error("Expected string after '(_'");
142 result = new(obst) Lisp(Lisp::TYPE_STRING);
144 std::string translation = dictionary->translate(lexer->getString());
145 result->v.string = new(obst) char[translation.size()+1];
146 memcpy(result->v.string, translation.c_str(), translation.size()+1);
148 size_t len = strlen(lexer->getString()) + 1;
149 result->v.string = new(obst) char[len];
150 memcpy(result->v.string, lexer->getString(), len);
152 token = lexer->getNextToken();
153 if(token != Lexer::TOKEN_CLOSE_PAREN)
154 parse_error("Expected ')' after '(_ string'");
160 cur->v.cons.car = read();
161 if(token == Lexer::TOKEN_CLOSE_PAREN) {
165 Lisp *newcur = new(obst) Lisp(Lisp::TYPE_CONS);
166 cur->v.cons.cdr = newcur;
172 case Lexer::TOKEN_SYMBOL: {
173 result = new(obst) Lisp(Lisp::TYPE_SYMBOL);
174 size_t len = strlen(lexer->getString()) + 1;
175 result->v.string = new(obst) char[len];
176 memcpy(result->v.string, lexer->getString(), len);
179 case Lexer::TOKEN_STRING: {
180 result = new(obst) Lisp(Lisp::TYPE_STRING);
181 size_t len = strlen(lexer->getString()) + 1;
182 result->v.string = new(obst) char[len];
183 memcpy(result->v.string, lexer->getString(), len);
186 case Lexer::TOKEN_INTEGER:
187 result = new(obst) Lisp(Lisp::TYPE_INTEGER);
188 sscanf(lexer->getString(), "%d", &result->v.integer);
190 case Lexer::TOKEN_REAL:
191 result = new(obst) Lisp(Lisp::TYPE_REAL);
192 sscanf(lexer->getString(), "%f", &result->v.real);
194 case Lexer::TOKEN_TRUE:
195 result = new(obst) Lisp(Lisp::TYPE_BOOLEAN);
196 result->v.boolean = true;
198 case Lexer::TOKEN_FALSE:
199 result = new(obst) Lisp(Lisp::TYPE_BOOLEAN);
200 result->v.boolean = false;
204 // this should never happen
208 token = lexer->getNextToken();
212 } // end of namespace lisp