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.
28 #include "tinygettext/tinygettext.hpp"
29 #include "physfs/physfs_stream.hpp"
36 Parser::Parser(bool translate)
37 : lexer(0), dictionary_manager(0), dictionary(0)
40 dictionary_manager = new TinyGetText::DictionaryManager();
41 dictionary_manager->set_charset("UTF-8");
48 delete dictionary_manager;
51 static std::string dirname(std::string filename)
53 std::string::size_type p = filename.find_last_of('/');
54 if(p == std::string::npos)
57 return filename.substr(0, p+1);
61 Parser::parse(const std::string& filename)
63 IFileStreambuf ins(filename);
64 std::istream in(&ins);
67 std::stringstream msg;
68 msg << "Parser problem: Couldn't open file '" << filename << "'.";
69 throw std::runtime_error(msg.str());
72 if(dictionary_manager) {
73 dictionary_manager->add_directory(dirname(filename));
74 dictionary = & (dictionary_manager->get_dictionary());
81 Parser::parse(std::istream& stream)
84 lexer = new Lexer(stream);
86 token = lexer->getNextToken();
87 Lisp* result = new Lisp(Lisp::TYPE_CONS);
88 result->v.cons.car = read();
89 result->v.cons.cdr = 0;
102 case Lexer::TOKEN_EOF: {
103 std::stringstream msg;
104 msg << "Parse Error at line " << lexer->getLineNumber() << ": "
105 << "Unexpected EOF.";
106 throw std::runtime_error(msg.str());
108 case Lexer::TOKEN_CLOSE_PAREN: {
109 std::stringstream msg;
110 msg << "Parse Error at line " << lexer->getLineNumber() << ": "
111 << "Unexpected ')'.";
112 throw std::runtime_error(msg.str());
114 case Lexer::TOKEN_OPEN_PAREN: {
115 result = new Lisp(Lisp::TYPE_CONS);
117 token = lexer->getNextToken();
118 if(token == Lexer::TOKEN_CLOSE_PAREN) {
119 result->v.cons.car = 0;
120 result->v.cons.cdr = 0;
124 if(token == Lexer::TOKEN_SYMBOL &&
125 strcmp(lexer->getString(), "_") == 0) {
126 // evaluate translation function (_ str) in place here
127 token = lexer->getNextToken();
128 if(token != Lexer::TOKEN_STRING)
129 throw std::runtime_error("Expected string after '(_'");
131 result = new Lisp(Lisp::TYPE_STRING);
133 std::string translation = dictionary->translate(lexer->getString());
134 result->v.string = new char[translation.size()+1];
135 memcpy(result->v.string, translation.c_str(), translation.size()+1);
137 size_t len = strlen(lexer->getString()) + 1;
138 result->v.string = new char[len];
139 memcpy(result->v.string, lexer->getString(), len);
141 token = lexer->getNextToken();
142 if(token != Lexer::TOKEN_CLOSE_PAREN)
143 throw std::runtime_error("Expected ')' after '(_ string'");
149 cur->v.cons.car = read();
150 if(token == Lexer::TOKEN_CLOSE_PAREN) {
154 cur->v.cons.cdr = new Lisp(Lisp::TYPE_CONS);
155 cur = cur->v.cons.cdr;
160 case Lexer::TOKEN_SYMBOL: {
161 result = new Lisp(Lisp::TYPE_SYMBOL);
162 size_t len = strlen(lexer->getString()) + 1;
163 result->v.string = new char[len];
164 memcpy(result->v.string, lexer->getString(), len);
167 case Lexer::TOKEN_STRING: {
168 result = new Lisp(Lisp::TYPE_STRING);
169 size_t len = strlen(lexer->getString()) + 1;
170 result->v.string = new char[len];
171 memcpy(result->v.string, lexer->getString(), len);
174 case Lexer::TOKEN_INTEGER:
175 result = new Lisp(Lisp::TYPE_INTEGER);
176 sscanf(lexer->getString(), "%d", &result->v.integer);
178 case Lexer::TOKEN_REAL:
179 result = new Lisp(Lisp::TYPE_REAL);
180 sscanf(lexer->getString(), "%f", &result->v.real);
182 case Lexer::TOKEN_TRUE:
183 result = new Lisp(Lisp::TYPE_BOOLEAN);
184 result->v.boolean = true;
186 case Lexer::TOKEN_FALSE:
187 result = new Lisp(Lisp::TYPE_BOOLEAN);
188 result->v.boolean = false;
192 // this should never happen
196 token = lexer->getNextToken();
200 } // end of namespace lisp