Orocos Real-Time Toolkit  2.5.0
CommonParser.cpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Thu Jul 15 11:21:07 CEST 2004  CommonParser.cxx
00003 
00004                         CommonParser.cxx -  description
00005                            -------------------
00006     begin                : Thu July 15 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens at mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 #include <boost/bind.hpp>
00038 
00039 #include "parse_exception.hpp"
00040 #include "parser-debug.hpp"
00041 #include "CommonParser.hpp"
00042 
00043 namespace RTT {
00044     using boost::bind;
00045     using namespace detail;
00046 
00047     namespace {
00048         boost::spirit::classic::assertion<std::string> expect_eos("End of statement expected. Use a newline or ';' to separate statements.");
00049     }
00050 
00051     CommonParser::~CommonParser() {}
00052 
00053     CommonParser::CommonParser()
00054         : identchar( "a-zA-Z_0-9" ), skipeol(true),
00055           skipper( eol_skip_functor(skipeol) )
00056     {
00057         // we reserve a few words
00058         keywordstable =
00059             "do",
00060             "until",
00061             "done",
00062             "or",
00063             "and",
00064             "not",
00065             "include",
00066             "if",
00067             "define",
00068             "then",
00069             "else",
00070             "for",
00071             "foreach",
00072             "while",
00073             "true",
00074             "false",
00075             "async",
00076             "time",
00077             "const",
00078             "nothing", // do not exclude 'do nothing' !
00079             "yield",
00080             "var",
00081             "set",
00082             "alias",
00083             "sync",
00084             "send",
00085             "call",
00086             "collect",
00087             "collectIfDone",
00088             "return",
00089             "call",
00090             "try",
00091             "catch";
00092 
00093         BOOST_SPIRIT_DEBUG_RULE( idr );
00094         BOOST_SPIRIT_DEBUG_RULE( idlr );
00095         BOOST_SPIRIT_DEBUG_RULE( eos );
00096         BOOST_SPIRIT_DEBUG_RULE( notassertingeos );
00097         BOOST_SPIRIT_DEBUG_RULE( leos );
00098         BOOST_SPIRIT_DEBUG_RULE( endofkeyword );
00099         BOOST_SPIRIT_DEBUG_RULE( keywords );
00100         BOOST_SPIRIT_DEBUG_RULE( keyword );
00101         BOOST_SPIRIT_DEBUG_RULE( identifier );
00102         BOOST_SPIRIT_DEBUG_RULE( templ );
00103         BOOST_SPIRIT_DEBUG_RULE( tidentifier );
00104         BOOST_SPIRIT_DEBUG_RULE( identchar );
00105         BOOST_SPIRIT_DEBUG_RULE( notassertingidentifier );
00106         BOOST_SPIRIT_DEBUG_RULE( lexeme_identifier );
00107         BOOST_SPIRIT_DEBUG_RULE( lexeme_notassertingidentifier );
00108         BOOST_SPIRIT_DEBUG_RULE( type_name );
00109         BOOST_SPIRIT_DEBUG_RULE( skipper );
00110 
00111         // an identifier is a word which can be used to identify a
00112         // label, or be the name of an object or method.  it is required
00113         // to start with a letter, followed by any number of letters,
00114         // numbers, dashes, underscores or letters.  The keywords we
00115         // reserved above are excluded..
00116         keywords = keywordstable;
00117         endofkeyword = (~identchar) | eol_p | end_p;
00118         keyword = lexeme_d[keywords >> eps_p(endofkeyword)];
00119 
00120         // if a rule is going to be used inside a lexeme_d, then it
00121         // needs to be of a different type..  Since identifier is used
00122         // both inside and outside of lexeme_d, we need two versions of
00123         // it.  Those are provided here: lexeme_identifier and
00124         // identifier..
00125         idr  = lexeme_d[ alpha_p >> *identchar ][assign( lastparsedident )] - keyword;
00126         idlr = lexeme_d[ alpha_p >> *identchar ][assign( lastparsedident )] - keyword;
00127         // #warning " Rule on stack  ?? "
00128         //RULE( identifier_base, lexeme_d[ alpha_p >> *identchar ][assign( lastparsedident )] - as_lower_d[keywords] );
00129         //BOOST_SPIRIT_DEBUG_RULE( identifier_base );
00130         lexeme_identifier = idlr | keyword[bind( &CommonParser::seenillegalidentifier, this )];
00131         lexeme_notassertingidentifier = idlr;
00132 
00133         notassertingidentifier = idr >> !str_p("[]");
00134         identifier = (idr >> !str_p("[]")) | keyword[bind( &CommonParser::seenillegalidentifier, this )];
00135 
00136         // this is a recursive rule. 't' stands for 'template' and 'terminal' (followed by a '(')
00137         templ = ch_p('<') >> identifier >> *templ >> '>';
00138         tidentifier = identifier >> *templ; // >> eps_p( ch_p('(') ); // This is a hack: we expect always the form A<B<C>>(...)
00139 
00140         // end of statement is on a newline or a ';'
00141         //eos = lexeme_d[ *(space_p - eol_p) >> (eol_p | ch_p(';')) ];
00142         eos = expect_eos( notassertingeos ); // detect } as eos, but do not consume.
00143         notassertingeos = eol_p | ch_p(';') | eps_p(ch_p('}')); // detect } as eos, but do not consume.
00144         leos = *(space_p - eol_p) >> (eol_p | ch_p(';') | eps_p(ch_p('}')));
00145 
00146         chset<> t_identchar( "a-zA-Z-_0-9/<>." );
00147         type_name = lexeme_d[ alpha_p >> *t_identchar ] - keyword;
00148     }
00149 
00150     void CommonParser::seenillegalidentifier()
00151     {
00152         throw parse_exception_illegal_identifier( lastparsedident );
00153     }
00154 
00155 }