summaryrefslogtreecommitdiff
path: root/i/marvin
diff options
context:
space:
mode:
authorschodet2006-04-09 13:48:55 +0000
committerschodet2006-04-09 13:48:55 +0000
commit1cb15048a3da2076ea3d41b53b2791cbb8925eec (patch)
tree076208c18525b3c43699294064b1b6ea5bdb9ac2 /i/marvin
parent8943c165faa72b9fc141d2244be0bf7118179043 (diff)
Ajout du parser générique.
Voila, j'ai résolu mes problèmes éthiques comme dit djerem.
Diffstat (limited to 'i/marvin')
-rw-r--r--i/marvin/src/Makefile.defs1
-rw-r--r--i/marvin/src/config/Makefile.defs15
-rw-r--r--i/marvin/src/config/config_data.cc17
-rw-r--r--i/marvin/src/config/config_data.hh9
-rw-r--r--i/marvin/src/config/config_data.tcc11
-rw-r--r--i/marvin/src/config/parser.yy173
-rw-r--r--i/marvin/src/config/test_config.cc (renamed from i/marvin/src/config/test_config_data.cc)9
-rw-r--r--i/marvin/src/parser/Makefile.defs14
-rw-r--r--i/marvin/src/parser/parser.cc (renamed from i/marvin/src/config/config_parser.cc)90
-rw-r--r--i/marvin/src/parser/parser.hh (renamed from i/marvin/src/config/config_parser.hh)58
-rw-r--r--i/marvin/src/parser/test_parser.cc86
-rw-r--r--i/marvin/src/parser/yylexer.ll (renamed from i/marvin/src/config/lexer.ll)28
-rw-r--r--i/marvin/src/parser/yyparser.yy258
13 files changed, 497 insertions, 272 deletions
diff --git a/i/marvin/src/Makefile.defs b/i/marvin/src/Makefile.defs
index 0ad5bc1..cec8951 100644
--- a/i/marvin/src/Makefile.defs
+++ b/i/marvin/src/Makefile.defs
@@ -20,6 +20,7 @@ endif
CXXFLAGS += -fmessage-length=0
SUBDIRS = utils utils/meta \
+ parser \
interpreter config tester \
log serial timer \
data scheduler \
diff --git a/i/marvin/src/config/Makefile.defs b/i/marvin/src/config/Makefile.defs
index 823c9ea..a06f2a7 100644
--- a/i/marvin/src/config/Makefile.defs
+++ b/i/marvin/src/config/Makefile.defs
@@ -1,14 +1,5 @@
-PROGRAMS += test_config_data
+PROGRAMS += test_config
-config_OBJECTS = lexer.o parser.o config_data.o config_parser.o config.o
+config_OBJECTS = config_data.o config.o $(parser_OBJECTS)
-test_config_data_OBJECTS = $(config_OBJECTS) test_config_data.o
-
-EXTRA_CLEAN += parser.hh parser.cc lexer.hh lexer.cc
-
-parser.hh: parser.cc
-$(OBJ_DIR)/lexer.o: parser.hh
-
-lexer.hh: lexer.cc
-$(OBJ_DIR)/parser.o: lexer.hh
-$(OBJ_DIR)/config_parser.o: lexer.hh
+test_config_OBJECTS = $(config_OBJECTS) test_config.o
diff --git a/i/marvin/src/config/config_data.cc b/i/marvin/src/config/config_data.cc
index 2642e74..b126082 100644
--- a/i/marvin/src/config/config_data.cc
+++ b/i/marvin/src/config/config_data.cc
@@ -24,7 +24,7 @@
// }}}
#include "config.hh"
#include "config_data.hh"
-#include "config_parser.hh"
+#include "parser/parser.hh"
#include <stdexcept>
@@ -75,6 +75,21 @@ ConfigData::add (const std::string &id, any &val)
a.swap (val);
}
+/// Classe dérivé de Parser pour le parsing de conf.
+class ConfigParser : public Parser
+{
+ ConfigData &data_;
+ public:
+ /// Constructeur.
+ ConfigParser (ConfigData &data) : data_ (data) { }
+ /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est
+ /// détruit suite à l'appel.
+ virtual void assign (const std::string &id, any &val)
+ {
+ data_.add (id, val);
+ }
+};
+
/// Initialise (lit la ligne de commande et les fichiers de config.
void
ConfigData::init (int &argc, char **&argv, const std::string &file)
diff --git a/i/marvin/src/config/config_data.hh b/i/marvin/src/config/config_data.hh
index 8c8bf1f..51caabd 100644
--- a/i/marvin/src/config/config_data.hh
+++ b/i/marvin/src/config/config_data.hh
@@ -58,18 +58,9 @@ class ConfigData
/// Ajoute une valeur de configuration. VAL prend l'ancienne valeur ou un
/// any vide.
void add (const std::string &id, any &val);
- /// Ajoute une valeur de configuration, fonction générique. Attention,
- /// cette fonction est plus couteuse car elle fait une copie de
- /// la valeur.
- template<typename T>
- void add (const std::string &id, const T &val);
private:
/// Initialise (lit la ligne de commande et les fichiers de config.
void init (int &argc, char **&argv, const std::string &file);
- /// Lance le parseur sur un fichier.
- void parseFile (const std::string &file);
- /// Lance le parseur sur une chaîne.
- void parseString (const std::string &s);
};
#include "config_data.tcc"
diff --git a/i/marvin/src/config/config_data.tcc b/i/marvin/src/config/config_data.tcc
index 7e5b905..71fa6d6 100644
--- a/i/marvin/src/config/config_data.tcc
+++ b/i/marvin/src/config/config_data.tcc
@@ -57,14 +57,3 @@ ConfigData::get (const std::string &id, const T &defaut) const
return *v;
}
-/// Ajoute une valeur de configuration, fonction générique. Attention,
-/// cette fonction est plus couteuse car elle fait une copie de
-/// la valeur.
-template<typename T>
-void
-ConfigData::add (const std::string &id, const T &val)
-{
- any a (val);
- add (id, a);
-}
-
diff --git a/i/marvin/src/config/parser.yy b/i/marvin/src/config/parser.yy
deleted file mode 100644
index dc2be24..0000000
--- a/i/marvin/src/config/parser.yy
+++ /dev/null
@@ -1,173 +0,0 @@
-%{
-// marvin - programme du robot 2006. {{{
-//
-// Copyright (C) 2006 Nicolas Schodet
-//
-// Robot APB Team/Efrei 2006.
-// Web: http://assos.efrei.fr/robot/
-// Email: robot AT efrei DOT fr
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-//
-// }}}
-#include "config/config.hh"
-#include "config/config_data.hh"
-#include "config/config_parser.hh"
-
-// Fichiers d'en-tête générés.
-#include "parser.hh"
-#include "lexer.hh"
-
-#undef yyextra
-#define yyextra (yyget_extra (scanner))
-
-void yyerror (void *scanner, const char *e);
-
-%}
-
-%error-verbose
-%pure-parser
-%lex-param {void *scanner}
-%parse-param {void *scanner}
-%defines
-%union {
- char c;
- int i;
- double f;
- bool b;
- std::string *s;
- struct {
- any *a;
- Config::IntList *il;
- Config::FloatList *fl;
- Config::StringList *sl;
- } a;
-}
-
-%token<c> UNKNOWN
-%token<i> INT
-%token<f> FLOAT
-%token<s> ID STRING
-%token<b> BOOLEAN
-
-%type<a> int_list
-%type<a> float_list
-%type<a> string_list
-
-%destructor { delete $$; } ID STRING
-%destructor { delete $$.a; } int_list
-%destructor { delete $$.a; } float_list
-%destructor { delete $$.a; } string_list
-
-%%
-
-input:
- /* Nothing. */
- | confitem
- | input '\n' confitem
- | input '\n'
-;
-
-confitem:
- ID '=' BOOLEAN {
- yyextra->configData.add (*$1, $3);
- delete $1;
- }
- | ID '=' INT {
- yyextra->configData.add (*$1, $3);
- delete $1;
- }
- | ID '=' FLOAT {
- yyextra->configData.add (*$1, $3);
- delete $1;
- }
- | ID '=' STRING {
- yyextra->configData.add (*$1, *$3);
- delete $1;
- delete $3;
- }
- | ID '=' '(' int_list ')' {
- yyextra->configData.add (*$1, *$4.a);
- delete $1;
- delete $4.a;
- }
- | ID '=' '(' float_list ')' {
- yyextra->configData.add (*$1, *$4.a);
- delete $1;
- delete $4.a;
- }
- | ID '=' '(' string_list ')' {
- yyextra->configData.add (*$1, *$4.a);
- delete $1;
- delete $4.a;
- }
-;
-
-int_list:
- INT {
- $$.a = new any (Config::IntList ());
- $$.il = any_cast<Config::IntList> ($$.a);
- $$.il->push_back ($1);
- }
- | int_list INT {
- $1.il->push_back ($2);
- $$ = $1;
- }
-;
-
-float_list:
- FLOAT {
- $$.a = new any (Config::FloatList ());
- $$.fl = any_cast<Config::FloatList> ($$.a);
- $$.fl->push_back ($1);
- }
- | float_list FLOAT {
- $1.fl->push_back ($2);
- $$ = $1;
- }
-;
-
-string_list:
- STRING {
- $$.a = new any (Config::StringList ());
- $$.sl = any_cast<Config::StringList> ($$.a);
- $$.sl->push_back (*$1);
- delete $1;
- }
- | string_list STRING {
- $1.sl->push_back (*$2);
- $$ = $1;
- delete $2;
- }
-;
-
-%%
-
-/// Traite une erreur de Bison.
-void
-yyerror (void *scanner, const char *e)
-{
- yyextra->error (e);
-}
-
-/* Shut up warning for this wrongly declared static function. */
-static int
-yy_init_globals (yyscan_t yyscanner)
-{
- return yy_init_globals (yyscanner);
-}
-
-/* vim:ft=yacc:
-*/
diff --git a/i/marvin/src/config/test_config_data.cc b/i/marvin/src/config/test_config.cc
index 5643ce1..3b3e368 100644
--- a/i/marvin/src/config/test_config_data.cc
+++ b/i/marvin/src/config/test_config.cc
@@ -1,4 +1,4 @@
-// test_config_data.cc
+// test_config.cc
// marvin - programme du robot 2006. {{{
//
// Copyright (C) 2006 Nicolas Schodet
@@ -33,12 +33,11 @@ main (int argc, char **argv)
try
{
// Create manually the instance of the config class
- Config cd (argc, argv);
+ Config c (argc, argv);
// Example for getting the unique instance
- //Config &confInstance = Config::getInstance ();
-
+ Config &ci = Config::getInstance ();
for (int i = 1; i < argc; ++i)
- std::cout << cd.get (argv[i]) << std::endl;
+ std::cout << ci.get (argv[i]) << std::endl;
}
catch (const std::exception &e)
{
diff --git a/i/marvin/src/parser/Makefile.defs b/i/marvin/src/parser/Makefile.defs
new file mode 100644
index 0000000..61b4b97
--- /dev/null
+++ b/i/marvin/src/parser/Makefile.defs
@@ -0,0 +1,14 @@
+PROGRAMS += test_parser
+
+parser_OBJECTS = yylexer.o yyparser.o parser.o
+
+test_parser_OBJECTS = $(parser_OBJECTS) test_parser.o
+
+EXTRA_CLEAN += yyparser.hh yyparser.cc yylexer.hh yylexer.cc
+
+yyparser.hh: yyparser.cc
+$(OBJ_DIR)/yylexer.o: yyparser.hh
+
+yylexer.hh: yylexer.cc
+$(OBJ_DIR)/yyparser.o: yylexer.hh
+$(OBJ_DIR)/parser.o: yylexer.hh
diff --git a/i/marvin/src/config/config_parser.cc b/i/marvin/src/parser/parser.cc
index ee0a6e3..0c5a39e 100644
--- a/i/marvin/src/config/config_parser.cc
+++ b/i/marvin/src/parser/parser.cc
@@ -1,4 +1,4 @@
-// config_parser.cc
+// parser.cc
// marvin - programme du robot 2006. {{{
//
// Copyright (C) 2006 Nicolas Schodet
@@ -22,11 +22,10 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// }}}
-#include "config_parser.hh"
-#include "config.hh"
-
#include "parser.hh"
-#include "lexer.hh"
+
+#include "yyparser.hh"
+#include "yylexer.hh"
#include <stdexcept>
#include <sstream>
@@ -34,14 +33,13 @@
int yyparse (void *);
/// Constructeur.
-ConfigParser::ConfigParser (ConfigData &configData)
- : configData_ (configData)
+Parser::Parser (void)
{
}
/// Lance le parseur sur un fichier.
void
-ConfigParser::parseFile (const std::string &file)
+Parser::parseFile (const std::string &file)
{
FILE *f;
f = fopen (file.c_str (), "r");
@@ -52,7 +50,7 @@ ConfigParser::parseFile (const std::string &file)
// Crée un scanner, initialise son tampon d'entré, puis parse.
yyscan_t scanner;
YY_BUFFER_STATE buf;
- Extra e (configData_, *this, true);
+ Extra e (*this, true);
yylex_init (&scanner);
yyset_extra (&e, scanner);
buf = yy_create_buffer (f, YY_READ_BUF_SIZE, scanner);
@@ -62,13 +60,13 @@ ConfigParser::parseFile (const std::string &file)
yylex_destroy (scanner);
if (ret)
{
- if (e.errorValid_)
+ if (!e.error_.empty ())
throw std::runtime_error (e.error_);
else
throw std::runtime_error ("parse error");
}
}
- catch (const std::runtime_error &e)
+ catch (const std::exception &e)
{
fclose (f);
throw std::runtime_error ("in file \"" + file + "\": " + e.what ());
@@ -78,14 +76,14 @@ ConfigParser::parseFile (const std::string &file)
/// Lance le parseur sur une chaîne.
void
-ConfigParser::parseString (const std::string &s)
+Parser::parseString (const std::string &s)
{
try
{
// Crée un scanner, initialise son tampon d'entré, puis parse.
yyscan_t scanner;
YY_BUFFER_STATE buf;
- Extra e (configData_, *this, false);
+ Extra e (*this, false);
yylex_init (&scanner);
yyset_extra (&e, scanner);
buf = yy_scan_bytes (s.data (), s.size (), scanner);
@@ -94,35 +92,47 @@ ConfigParser::parseString (const std::string &s)
yylex_destroy (scanner);
if (ret)
{
- if (e.errorValid_)
+ if (!e.error_.empty ())
throw std::runtime_error (e.error_);
else
throw std::runtime_error ("parse error");
}
}
- catch (const std::runtime_error &e)
+ catch (const std::exception &e)
{
- throw std::runtime_error ("in config string \"" + s + "\": "
- + e.what ());
+ throw std::runtime_error ("in string \"" + s + "\": " + e.what ());
}
}
+/// Fonction appelée lors d'une affectation. VAL peut être modifié, il est
+/// détruit suite à l'appel.
+void
+Parser::assign (const std::string &id, any &val)
+{
+ throw std::runtime_error ("unexpected assignement");
+}
+
+/// Fonction appelée lors d'un appel. ARGS peut être modifié, il est
+/// détruit suite à l'appel.
+void
+Parser::call (const std::string &id, AnyList &args)
+{
+ throw std::runtime_error ("unexpected call");
+}
+
/// Constructeur pour initialiser les références.
-ConfigParser::Extra::Extra (ConfigData &configData_, ConfigParser
- &configParser_, bool useLine)
- : configData (configData_), configParser (configParser_),
- line (1), errorValid_ (false), useLine_ (useLine)
+Parser::Extra::Extra (Parser &parser, bool useLine)
+ : line (1), parser_ (parser), useLine_ (useLine)
{
}
/// Recueille l'erreur de bison.
void
-ConfigParser::Extra::error (const std::string &e)
+Parser::Extra::error (const std::string &e)
{
- if (!errorValid_)
+ if (error_.empty ())
{
error_ = e;
- errorValid_ = true;
if (useLine_)
{
std::stringstream os;
@@ -133,6 +143,38 @@ ConfigParser::Extra::error (const std::string &e)
}
}
+/// Fonction appelée lors d'une affectation par bison.
+bool
+Parser::Extra::assign (const std::string &id, any &val)
+{
+ try
+ {
+ parser_.assign (id, val);
+ }
+ catch (const std::exception &e)
+ {
+ error (e.what ());
+ return false;
+ }
+ return true;
+}
+
+/// Fonction appelée lors d'un appel par bison.
+bool
+Parser::Extra::call (const std::string &id, AnyList &args)
+{
+ try
+ {
+ parser_.call (id, args);
+ }
+ catch (const std::exception &e)
+ {
+ error (e.what ());
+ return false;
+ }
+ return true;
+}
+
/* Shut up warning for this wrongly declared static function. */
static int
yy_init_globals (yyscan_t yyscanner)
diff --git a/i/marvin/src/config/config_parser.hh b/i/marvin/src/parser/parser.hh
index abbf214..c07d645 100644
--- a/i/marvin/src/config/config_parser.hh
+++ b/i/marvin/src/parser/parser.hh
@@ -1,6 +1,6 @@
-#ifndef config_parser_hh
-#define config_parser_hh
-// config_parser.hh
+#ifndef parser_hh
+#define parser_hh
+// parser.hh
// marvin - programme du robot 2006. {{{
//
// Copyright (C) 2006 Nicolas Schodet
@@ -24,54 +24,64 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// }}}
+#include "utils/any.hh"
#include <string>
+#include <list>
-class ConfigData;
-
-/// Structure d'information passée au parser.
-class ConfigParser
+/// Classe de parsing. Pour l'utiliser, dériver une classe et implémenter les
+/// méthodes que l'on veut supporter.
+class Parser
{
public:
- struct Extra
+ /// Les types supportés sont bool, char, int, double, std::string,
+ /// IntList, DoubleList, StringList.
+ typedef std::list<int> IntList;
+ typedef std::list<double> DoubleList;
+ typedef std::list<std::string> StringList;
+ typedef std::list<any> AnyList;
+ /// Cette structure est passée au parser en bison, puis au lexer en flex.
+ class Extra
{
public:
/// Chaîne temporaire utilisée pendant l'analyse lexicale.
std::string tmp;
- /// Référence vers le ConfigData qui doit recevoir la configuration.
- ConfigData &configData;
- /// Référence vers l'instance de ConfigParser.
- ConfigParser &configParser;
/// Ligne courante.
int line;
private:
+ /// Référence vers l'instance de Parser.
+ Parser &parser_;
/// Permet de stocker l'erreur de bison.
std::string error_;
- /// Indique si error est significatif.
- bool errorValid_;
/// Utilise ou non le comptage de lignes.
bool useLine_;
public:
/// Constructeur pour initialiser les références.
- Extra (ConfigData &configData_, ConfigParser &configParser_,
- bool useLine);
+ Extra (Parser &parser, bool useLine);
/// Recueille l'erreur de bison.
void error (const std::string &e);
- /// Accés réservé pour ConfigParser.
- friend class ConfigParser;
+ /// Fonction appelée lors d'une affectation par bison.
+ bool assign (const std::string &id, any &val);
+ /// Fonction appelée lors d'un appel par bison.
+ bool call (const std::string &id, AnyList &args);
+ /// Accés réservé pour Parser.
+ friend class Parser;
};
- private:
- /// Référence vers le ConfigData qui doit recevoir la configuration.
- ConfigData &configData_;
public:
/// Constructeur.
- ConfigParser (ConfigData &configData);
+ Parser (void);
/// Lance le parseur sur un fichier.
void parseFile (const std::string &file);
/// Lance le parseur sur une chaîne.
void parseString (const std::string &s);
+ /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est
+ /// détruit suite à l'appel.
+ virtual void assign (const std::string &id, any &val);
+ /// Fonction appelée lors d'un appel. ARGS peut être modifié, il est
+ /// détruit suite à l'appel.
+ virtual void call (const std::string &id, AnyList &args);
};
-#define YY_EXTRA_TYPE ConfigParser::Extra *
+#define YY_EXTRA_TYPE Parser::Extra *
-#endif // config_parser_hh
+#endif // parser_hh
diff --git a/i/marvin/src/parser/test_parser.cc b/i/marvin/src/parser/test_parser.cc
new file mode 100644
index 0000000..dedbd83
--- /dev/null
+++ b/i/marvin/src/parser/test_parser.cc
@@ -0,0 +1,86 @@
+// test_parser.cc
+// marvin - programme du robot 2006. {{{
+//
+// Copyright (C) 2006 Nicolas Schodet
+//
+// Robot APB Team/Efrei 2006.
+// Web: http://assos.efrei.fr/robot/
+// Email: robot AT efrei DOT fr
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+#include "parser.hh"
+
+#include <iostream>
+#include <exception>
+
+class TestParser : public Parser
+{
+ public:
+ /// Fonction appelée lors d'une affectation. VAL peut être modifié, il est
+ /// détruit suite à l'appel.
+ virtual void assign (const std::string &id, any &val)
+ {
+ std::cout << id << " = " << val << std::endl;
+ }
+ /// Fonction appelée lors d'un appel. ARGS peut être modifié, il est
+ /// détruit suite à l'appel.
+ virtual void call (const std::string &id, AnyList &args)
+ {
+ std::cout << "call " << id << ' ' << args << std::endl;
+ }
+};
+
+int
+main (int argc, char **argv)
+{
+ try
+ {
+ if (argc <= 1)
+ {
+ std::cerr << "test_parser - test le parser.\n"
+ "Utilisation: test_parser [-f FILE | STRING]\n"
+ << std::endl;
+ }
+ TestParser tp;
+ for (int i = 1; i < argc; i++)
+ {
+ try
+ {
+ if (i + 1 < argc && strcmp (argv[i], "-f") == 0)
+ {
+ tp.parseFile (argv[++i]);
+ }
+ else
+ {
+ tp.parseString (argv[i]);
+ }
+ }
+ catch (const std::exception &e)
+ {
+ // L'erreur est humaine... heu, normale, elle fait parti du
+ // test donc pas de cerr.
+ std::cout << "error: " << e.what () << std::endl;
+ }
+ }
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << e.what () << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/i/marvin/src/config/lexer.ll b/i/marvin/src/parser/yylexer.ll
index 34522dc..34157b9 100644
--- a/i/marvin/src/config/lexer.ll
+++ b/i/marvin/src/parser/yylexer.ll
@@ -22,15 +22,13 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// }}}
-#include "config/config.hh"
-#include "config/config_parser.hh"
-#include "utils/any.hh"
-#include "parser.hh"
+#include "parser/parser.hh"
+#include "yyparser.hh"
%}
%option reentrant
-%option header-file="lexer.hh"
-%option outfile="lexer.cc"
+%option header-file="yylexer.hh"
+%option outfile="yylexer.cc"
%option bison-bridge
%option noyywrap nodefault nounput
@@ -39,9 +37,9 @@
INTDEC [+-]?[0-9]+
INTHEX "0x"[0-9a-fA-F]+
INTNUM {INTDEC}|{INTHEX}
-FLOAT1 [+-]?\.[0-9]+
-FLOAT2 [+-]?[0-9]+\.[0-9]*
-FLOATNUM {FLOAT1}|{FLOAT2}
+DOUBLE1 [+-]?\.[0-9]+
+DOUBLE2 [+-]?[0-9]+\.[0-9]*
+DOUBLENUM {DOUBLE1}|{DOUBLE2}
%%
@@ -60,9 +58,9 @@ FLOATNUM {FLOAT1}|{FLOAT2}
return ID;
}
-{FLOATNUM} {
- yylval->f = strtod (yytext, 0);
- return FLOAT;
+{DOUBLENUM} {
+ yylval->d = strtod (yytext, 0);
+ return DOUBLE;
}
{INTNUM} {
@@ -77,7 +75,11 @@ FLOATNUM {FLOAT1}|{FLOAT2}
\n {
yyextra->line++;
- return yytext[0];
+ return SEP;
+}
+
+; {
+ return SEP;
}
[=()] return yytext[0];
diff --git a/i/marvin/src/parser/yyparser.yy b/i/marvin/src/parser/yyparser.yy
new file mode 100644
index 0000000..e965ffd
--- /dev/null
+++ b/i/marvin/src/parser/yyparser.yy
@@ -0,0 +1,258 @@
+%{
+// marvin - programme du robot 2006. {{{
+//
+// Copyright (C) 2006 Nicolas Schodet
+//
+// Robot APB Team/Efrei 2006.
+// Web: http://assos.efrei.fr/robot/
+// Email: robot AT efrei DOT fr
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// }}}
+#include "parser/parser.hh"
+
+// Fichiers d'en-tête générés.
+#include "yyparser.hh"
+#include "yylexer.hh"
+
+#undef yyextra
+#define yyextra (yyget_extra (scanner))
+
+void yyerror (void *scanner, const char *e);
+
+%}
+
+%error-verbose
+%pure-parser
+%lex-param {void *scanner}
+%parse-param {void *scanner}
+%defines
+%union {
+ bool b;
+ char c;
+ int i;
+ double d;
+ std::string *s;
+ struct {
+ any *a;
+ Parser::IntList *il;
+ } il;
+ struct {
+ any *a;
+ Parser::DoubleList *dl;
+ } dl;
+ struct {
+ any *a;
+ Parser::StringList *sl;
+ } sl;
+ Parser::AnyList *al;
+}
+
+%token SEP
+
+%token<b> BOOLEAN
+%token<c> UNKNOWN
+%token<i> INT
+%token<d> DOUBLE
+%token<s> ID STRING
+
+%type<il> int_list int_list_i
+%type<dl> double_list double_list_i
+%type<sl> string_list string_list_i
+%type<al> arg_list
+
+%destructor { delete $$; } ID STRING
+%destructor { delete $$.a; } int_list int_list_i
+%destructor { delete $$.a; } double_list double_list_i
+%destructor { delete $$.a; } string_list string_list_i
+%destructor { delete $$; } arg_list
+
+%%
+
+input:
+ /* Nothing. */
+ | item
+ | input SEP item
+ | input SEP
+;
+
+item:
+ ID '=' BOOLEAN {
+ any a ($3);
+ if (!yyextra->assign (*$1, a))
+ YYERROR;
+ delete $1;
+ }
+ | ID '=' INT {
+ any a ($3);
+ if (!yyextra->assign (*$1, a))
+ YYERROR;
+ delete $1;
+ }
+ | ID '=' DOUBLE {
+ any a ($3);
+ if (!yyextra->assign (*$1, a))
+ YYERROR;
+ delete $1;
+ }
+ | ID '=' STRING {
+ any a (*$3);
+ if (!yyextra->assign (*$1, a))
+ YYERROR;
+ delete $1;
+ delete $3;
+ }
+ | ID '=' int_list {
+ if (!yyextra->assign (*$1, *$3.a))
+ YYERROR;
+ delete $1;
+ delete $3.a;
+ }
+ | ID '=' double_list {
+ if (!yyextra->assign (*$1, *$3.a))
+ YYERROR;
+ delete $1;
+ delete $3.a;
+ }
+ | ID '=' string_list {
+ if (!yyextra->assign (*$1, *$3.a))
+ YYERROR;
+ delete $1;
+ delete $3.a;
+ }
+ | ID arg_list {
+ if (!yyextra->call (*$1, *$2))
+ YYERROR;
+ delete $1;
+ delete $2;
+ }
+;
+
+int_list:
+ '(' int_list_i ')' {
+ $$ = $2;
+ }
+;
+
+int_list_i:
+ INT {
+ $$.a = new any (Parser::IntList ());
+ $$.il = any_cast<Parser::IntList> ($$.a);
+ $$.il->push_back ($1);
+ }
+ | int_list_i INT {
+ $1.il->push_back ($2);
+ $$ = $1;
+ }
+;
+
+double_list:
+ '(' double_list_i ')' {
+ $$ = $2;
+ }
+;
+
+double_list_i:
+ DOUBLE {
+ $$.a = new any (Parser::DoubleList ());
+ $$.dl = any_cast<Parser::DoubleList> ($$.a);
+ $$.dl->push_back ($1);
+ }
+ | double_list_i DOUBLE {
+ $1.dl->push_back ($2);
+ $$ = $1;
+ }
+;
+
+string_list:
+ '(' string_list_i ')' {
+ $$ = $2;
+ }
+;
+
+string_list_i:
+ STRING {
+ $$.a = new any (Parser::StringList ());
+ $$.sl = any_cast<Parser::StringList> ($$.a);
+ $$.sl->push_back (*$1);
+ delete $1;
+ }
+ | string_list_i STRING {
+ $1.sl->push_back (*$2);
+ $$ = $1;
+ delete $2;
+ }
+;
+
+arg_list:
+ /* empty */ {
+ $$ = new Parser::AnyList;
+ }
+ | arg_list BOOLEAN {
+ any a ($2);
+ $1->push_back (any ());
+ $1->back ().swap (a);
+ }
+ | arg_list INT {
+ any a ($2);
+ $1->push_back (any ());
+ $1->back ().swap (a);
+ }
+ | arg_list DOUBLE {
+ any a ($2);
+ $1->push_back (any ());
+ $1->back ().swap (a);
+ }
+ | arg_list STRING {
+ any a (*$2);
+ $1->push_back (any ());
+ $1->back ().swap (a);
+ delete $2;
+ }
+ | arg_list int_list {
+ $1->push_back (any ());
+ $1->back ().swap (*$2.a);
+ delete $2.a;
+ }
+ | arg_list double_list {
+ $1->push_back (any ());
+ $1->back ().swap (*$2.a);
+ delete $2.a;
+ }
+ | arg_list string_list {
+ $1->push_back (any ());
+ $1->back ().swap (*$2.a);
+ delete $2.a;
+ }
+;
+%%
+
+/// Traite une erreur de Bison.
+void
+yyerror (void *scanner, const char *e)
+{
+ yyextra->error (e);
+}
+
+/* Shut up warning for this wrongly declared static function. */
+static int
+yy_init_globals (yyscan_t yyscanner)
+{
+ return yy_init_globals (yyscanner);
+}
+
+/* vim:ft=yacc:
+*/