abacus/src/parse/scanner.ll

80 lines
1.6 KiB
LLVM

%{
#include <sstream>
#include "parser-driver.hh"
#include "parser.hh"
%}
/* Avoid warnings because of unused functions */
%option noinput
%option nounput
/* Enable scan tracing */
%option debug
/* Assume single file, do no implement `yywrap` */
%option noyywrap
/* Let Flex track the line numbers */
%option yylineno
%{
// Run at each match
#define YY_USER_ACTION loc.columns(yyleng);
%}
blank [ \t\r]
int [0-9]+
%%
%{
// Run each time `yylex` is called
auto& loc = drv.location();
loc.step();
%}
{blank}+ loc.step();
\n+ loc.lines(yyleng); loc.step();
"+" return yy::parser::make_PLUS(loc);
"-" return yy::parser::make_MINUS(loc);
"*" return yy::parser::make_TIMES(loc);
"/" return yy::parser::make_DIVIDE(loc);
"(" return yy::parser::make_LPAREN(loc);
")" return yy::parser::make_RPAREN(loc);
{int} {
abacus::bignum::BigNum num;
std::stringstream(yytext) >> num;
return yy::parser::make_NUM(num, loc);
}
. {
using namespace yy;
using namespace std::string_literals;
throw parser::syntax_error(loc, "invalid character: "s + yytext);
}
<<EOF>> return yy::parser::make_EOF(loc);
%%
namespace abacus::parser {
void ParserDriver::scan_open() {
yy_flex_debug = scan_trace_p_;
if (filename_.empty() || filename_ == "-") {
yyin = stdin;
} else if ((yyin = fopen(filename_.c_str(), "r")) == nullptr) {
std::cerr << "cannot open " << filename_ << ": " << strerror(errno) << '\n';
exit(EXIT_FAILURE);
}
}
void ParserDriver::scan_close() {
fclose(yyin);
}
} // namespace abacus::parser