]> www.ginac.de Git - ginac.git/blobdiff - ginac/parser/lexer.cpp
Happy New Year!
[ginac.git] / ginac / parser / lexer.cpp
index 894a2ad8afeef8ae484eca01274290dc00074815..b5d59ba6f7eedb332c6dd95a1ae89815591fd4cb 100644 (file)
@@ -1,11 +1,35 @@
-#include <string>
+/** @file lexer.cpp
+ *
+ *  Implementation of GiNaC's lexer. */
+
+/*
+ *  GiNaC Copyright (C) 1999-2019 Johannes Gutenberg University Mainz, Germany
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "lexer.h"
+#include "compiler.h"
+
 #include <iostream>
 #include <sstream>
-#include "lexer.hpp"
-#include "compiler.h"
+#include <string>
+#include <cstdio>
+
+namespace GiNaC {
 
-namespace GiNaC
-{
 /// Skip to the end of line
 static int skipline(std::istream* s);
 /// Skip to the next non-whitespace character
@@ -19,12 +43,12 @@ int lexer::gettok()
        // Skip any whitespace.
        c = skipspace(input, c, line_num);
 
-       // identifier: [a-zA-Z][a-zA-Z0-9]*
+       // identifier: [a-zA-Z][a-zA-Z0-9_]*
        if (isalpha(c)) { 
                str = c;
                do {
                        c = input->get();
-                       if (isalnum(c))
+                       if ( isalnum(c) || c=='_' )
                                str += c;
                        else
                                break;
@@ -35,13 +59,23 @@ int lexer::gettok()
                        return token_type::identifier;
        }
 
-       // Number: [0-9.]+
+       // Number: [0-9]+([.][0-9]*(eE[+-][0-9]+)*)*
        if (isdigit(c) || c == '.') {
                str = "";
                do {
                        str += c;
                        c = input->get();
                } while (isdigit(c) || c == '.');
+               if (c == 'E' || c == 'e') {
+                       str += 'E';
+                       c = input->get();
+                       if (isdigit(c))
+                               str += '+';
+                       do {
+                               str += c;
+                               c = input->get();
+                       } while (isdigit(c));
+               }
                return token_type::number;
        }
 
@@ -129,5 +163,18 @@ void lexer::switch_input(std::istream* in)
        c = ' ';
 }
 
-} // namespace GiNaC
+/// Symbolic name of current token (for error reporting)
+std::string lexer::tok2str(const int tok) const
+{
+       switch (tok) {
+               case lexer::token_type::identifier:
+               case lexer::token_type::number:
+                       return std::string("\"") + str + "\"";
+               case lexer::token_type::eof:
+                       return std::string("EOF");
+               default:
+                       return std::string("\"") + char(tok) + "\"";
+       }
+}
 
+} // namespace GiNaC