/* 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 . */ %{ /* -*- C++ -*- */ # include # include # include # include // strerror # include # 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)); } <> 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); }