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 Unison::VFS::istream in(filename);
70 //IFileStreambuf ins(filename);
71 //std::istream in(&ins);
74 std::stringstream msg;
75 msg << "Parser problem: Couldn't open file '" << filename << "'.";
76 throw std::runtime_error(msg.str());
79 if(dictionary_manager) {
80 dictionary_manager->add_directory(dirname(filename));
81 dictionary = & (dictionary_manager->get_dictionary());
84 return parse(in, filename);
88 Parser::parse(std::istream& stream, const std::string& sourcename)
91 lexer = new Lexer(stream);
93 this->filename = sourcename;
94 token = lexer->getNextToken();
96 Lisp* result = new(obst) Lisp(Lisp::TYPE_CONS);
97 result->v.cons.car = read();
98 result->v.cons.cdr = 0;
107 Parser::parse_error(const char* msg) const
109 std::stringstream emsg;
110 emsg << "Parse Error at '" << filename << "' line " << lexer->getLineNumber()
112 throw std::runtime_error(emsg.str());
120 case Lexer::TOKEN_EOF: {
121 parse_error("Unexpected EOF.");
123 case Lexer::TOKEN_CLOSE_PAREN: {
124 parse_error("Unexpected ')'.");
126 case Lexer::TOKEN_OPEN_PAREN: {
127 result = new(obst) Lisp(Lisp::TYPE_CONS);
129 token = lexer->getNextToken();
130 if(token == Lexer::TOKEN_CLOSE_PAREN) {
131 result->v.cons.car = 0;
132 result->v.cons.cdr = 0;
136 if(token == Lexer::TOKEN_SYMBOL &&
137 strcmp(lexer->getString(), "_") == 0) {
138 // evaluate translation function (_ str) in place here
139 token = lexer->getNextToken();
140 if(token != Lexer::TOKEN_STRING)
141 parse_error("Expected string after '(_'");
143 result = new(obst) Lisp(Lisp::TYPE_STRING);
145 std::string translation = dictionary->translate(lexer->getString());
146 result->v.string = new(obst) char[translation.size()+1];
147 memcpy(result->v.string, translation.c_str(), translation.size()+1);
149 size_t len = strlen(lexer->getString()) + 1;
150 result->v.string = new(obst) char[len];
151 memcpy(result->v.string, lexer->getString(), len);
153 token = lexer->getNextToken();
154 if(token != Lexer::TOKEN_CLOSE_PAREN)
155 parse_error("Expected ')' after '(_ string'");
161 cur->v.cons.car = read();
162 if(token == Lexer::TOKEN_CLOSE_PAREN) {
166 Lisp *newcur = new(obst) Lisp(Lisp::TYPE_CONS);
167 cur->v.cons.cdr = newcur;
173 case Lexer::TOKEN_SYMBOL: {
174 result = new(obst) Lisp(Lisp::TYPE_SYMBOL);
175 size_t len = strlen(lexer->getString()) + 1;
176 result->v.string = new(obst) char[len];
177 memcpy(result->v.string, lexer->getString(), len);
180 case Lexer::TOKEN_STRING: {
181 result = new(obst) Lisp(Lisp::TYPE_STRING);
182 size_t len = strlen(lexer->getString()) + 1;
183 result->v.string = new(obst) char[len];
184 memcpy(result->v.string, lexer->getString(), len);
187 case Lexer::TOKEN_INTEGER:
188 result = new(obst) Lisp(Lisp::TYPE_INTEGER);
189 sscanf(lexer->getString(), "%d", &result->v.integer);
191 case Lexer::TOKEN_REAL:
192 result = new(obst) Lisp(Lisp::TYPE_REAL);
193 sscanf(lexer->getString(), "%f", &result->v.real);
195 case Lexer::TOKEN_TRUE:
196 result = new(obst) Lisp(Lisp::TYPE_BOOLEAN);
197 result->v.boolean = true;
199 case Lexer::TOKEN_FALSE:
200 result = new(obst) Lisp(Lisp::TYPE_BOOLEAN);
201 result->v.boolean = false;
205 // this should never happen
209 token = lexer->getNextToken();
213 } // end of namespace lisp