| /* Scanner for calc++. -*- C++ -*- |
| |
| Copyright (C) 2005-2015, 2018-2021 Free Software Foundation, Inc. |
| |
| This file is part of Bison, the GNU Compiler Compiler. |
| |
| 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 3 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, see <https://www.gnu.org/licenses/>. */ |
| |
| %{ /* -*- C++ -*- */ |
| # include <cerrno> |
| # include <climits> |
| # include <cstdlib> |
| # include <cstring> // strerror |
| # include <string> |
| # include "driver.hh" |
| # include "parser.hh" |
| %} |
| |
| %{ |
| #if defined __clang__ |
| # define CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) |
| #endif |
| |
| // Clang and ICC like to pretend they are GCC. |
| #if defined __GNUC__ && !defined __clang__ && !defined __ICC |
| # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) |
| #endif |
| |
| // Pacify warnings in yy_init_buffer (observed with Flex 2.6.4) |
| // and GCC 6.4.0, 7.3.0 with -O3. |
| #if defined GCC_VERSION && 600 <= GCC_VERSION |
| # pragma GCC diagnostic ignored "-Wnull-dereference" |
| #endif |
| |
| // This example uses Flex's C back end, yet compiles it as C++. |
| // So expect warnings about C style casts and NULL. |
| #if defined CLANG_VERSION && 500 <= CLANG_VERSION |
| # pragma clang diagnostic ignored "-Wold-style-cast" |
| # pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" |
| #elif defined GCC_VERSION && 407 <= GCC_VERSION |
| # pragma GCC diagnostic ignored "-Wold-style-cast" |
| # pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" |
| #endif |
| |
| #define FLEX_VERSION (YY_FLEX_MAJOR_VERSION * 100 + YY_FLEX_MINOR_VERSION) |
| |
| // Old versions of Flex (2.5.35) generate an incomplete documentation comment. |
| // |
| // In file included from src/scan-code-c.c:3: |
| // src/scan-code.c:2198:21: error: empty paragraph passed to '@param' command |
| // [-Werror,-Wdocumentation] |
| // * @param line_number |
| // ~~~~~~~~~~~~~~~~~^ |
| // 1 error generated. |
| #if FLEX_VERSION < 206 && defined CLANG_VERSION |
| # pragma clang diagnostic ignored "-Wdocumentation" |
| #endif |
| |
| // Old versions of Flex (2.5.35) use 'register'. Warnings introduced in |
| // GCC 7 and Clang 6. |
| #if FLEX_VERSION < 206 |
| # if defined CLANG_VERSION && 600 <= CLANG_VERSION |
| # pragma clang diagnostic ignored "-Wdeprecated-register" |
| # elif defined GCC_VERSION && 700 <= GCC_VERSION |
| # pragma GCC diagnostic ignored "-Wregister" |
| # endif |
| #endif |
| |
| #if FLEX_VERSION < 206 |
| # if defined CLANG_VERSION |
| # pragma clang diagnostic ignored "-Wconversion" |
| # pragma clang diagnostic ignored "-Wdocumentation" |
| # pragma clang diagnostic ignored "-Wshorten-64-to-32" |
| # pragma clang diagnostic ignored "-Wsign-conversion" |
| # elif defined GCC_VERSION |
| # pragma GCC diagnostic ignored "-Wconversion" |
| # pragma GCC diagnostic ignored "-Wsign-conversion" |
| # endif |
| #endif |
| |
| // Flex 2.6.4, GCC 9 |
| // warning: useless cast to type 'int' [-Wuseless-cast] |
| // 1361 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); |
| // | ^ |
| #if defined GCC_VERSION && 900 <= GCC_VERSION |
| # pragma GCC diagnostic ignored "-Wuseless-cast" |
| #endif |
| %} |
| |
| %option noyywrap nounput noinput batch debug |
| |
| %{ |
| // A number symbol corresponding to the value in S. |
| yy::parser::symbol_type |
| make_NUMBER (const std::string &s, const yy::parser::location_type& loc); |
| %} |
| |
| id [a-zA-Z][a-zA-Z_0-9]* |
| int [0-9]+ |
| blank [ \t\r] |
| |
| %{ |
| // Code run each time a pattern is matched. |
| # define YY_USER_ACTION loc.columns (yyleng); |
| %} |
| %% |
| %{ |
| // A handy shortcut to the location held by the driver. |
| yy::location& loc = drv.location; |
| // Code run each time yylex is called. |
| loc.step (); |
| %} |
| {blank}+ loc.step (); |
| \n+ loc.lines (yyleng); loc.step (); |
| |
| "-" return yy::parser::make_MINUS (loc); |
| "+" return yy::parser::make_PLUS (loc); |
| "*" return yy::parser::make_STAR (loc); |
| "/" return yy::parser::make_SLASH (loc); |
| "(" return yy::parser::make_LPAREN (loc); |
| ")" return yy::parser::make_RPAREN (loc); |
| ":=" return yy::parser::make_ASSIGN (loc); |
| |
| {int} return make_NUMBER (yytext, loc); |
| {id} return yy::parser::make_IDENTIFIER (yytext, loc); |
| . { |
| throw yy::parser::syntax_error |
| (loc, "invalid character: " + std::string(yytext)); |
| } |
| <<EOF>> return yy::parser::make_YYEOF (loc); |
| %% |
| |
| yy::parser::symbol_type |
| make_NUMBER (const std::string &s, const yy::parser::location_type& loc) |
| { |
| errno = 0; |
| long n = strtol (s.c_str(), NULL, 10); |
| if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE)) |
| throw yy::parser::syntax_error (loc, "integer is out of range: " + s); |
| return yy::parser::make_NUMBER ((int) n, loc); |
| } |
| |
| void |
| driver::scan_begin () |
| { |
| yy_flex_debug = trace_scanning; |
| if (file.empty () || file == "-") |
| yyin = stdin; |
| else if (!(yyin = fopen (file.c_str (), "r"))) |
| { |
| std::cerr << "cannot open " << file << ": " << strerror (errno) << '\n'; |
| exit (EXIT_FAILURE); |
| } |
| } |
| |
| void |
| driver::scan_end () |
| { |
| fclose (yyin); |
| } |