2024-07-18 14:58:09 +01:00
|
|
|
|
|
|
|
%{
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include "lexer.hpp"
|
|
|
|
#include "interpreter.hpp"
|
|
|
|
#include "parser.hpp"
|
|
|
|
#include "location.hh"
|
|
|
|
|
|
|
|
// Original yyterminate() macro returns int. Since we're using Bison 3 variants
|
|
|
|
// as tokens, we must redefine it to change type from `int` to `Parser::semantic_type`
|
|
|
|
#define yyterminate() stela::Parser::make_END(stela::location());
|
|
|
|
|
|
|
|
// This will track current scanner location.
|
|
|
|
// Action is called when length of the token is known.
|
|
|
|
#define YY_USER_ACTION this->interpreter.increase_location(yyleng);
|
|
|
|
|
|
|
|
// !!!WARNING!!!
|
|
|
|
// Location API is used, but the location is not initialized, 'cause I'm lazy. When making
|
|
|
|
// a token with make_{something} method you can pass detailed token location. Current location
|
|
|
|
// is accessible with m_driver.location() method. All puzzle elements are there - just
|
|
|
|
// pass location value in every action code block below. I'm going to waste more time writing
|
|
|
|
// this excuse than putting this boilerplate below...
|
|
|
|
//
|
|
|
|
// Location class can be found in location.hh and posistion.hh files. It's just a bit too much
|
|
|
|
// boilerplate for this small example. Bummer.
|
|
|
|
%}
|
|
|
|
|
2024-07-18 23:22:38 +01:00
|
|
|
%option nodefault noyywrap noyylineno c++ yyclass="Lexer" prefix="stela_"
|
2024-07-18 14:58:09 +01:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
[a-z]+ {
|
|
|
|
std::cout << "Scanner: identifier [" << yytext << "]\n";
|
2024-07-18 23:22:38 +01:00
|
|
|
return stela::Parser::make_STRING(yytext, stela::location());
|
2024-07-18 14:58:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
\( {
|
|
|
|
std::cout << "Scanner: '('\n";
|
|
|
|
return stela::Parser::make_LEFTPAR(stela::location());
|
|
|
|
}
|
|
|
|
|
|
|
|
\) {
|
|
|
|
std::cout << "Scanner: ')'\n";
|
|
|
|
return stela::Parser::make_RIGHTPAR(stela::location());
|
|
|
|
}
|
|
|
|
|
|
|
|
; {
|
|
|
|
std::cout << "Scanner: ';'\n";
|
|
|
|
return stela::Parser::make_SEMICOLON(stela::location());
|
|
|
|
}
|
|
|
|
|
|
|
|
, {
|
|
|
|
std::cout << "Scanner: ','\n";
|
|
|
|
return stela::Parser::make_COMMA(stela::location());
|
|
|
|
}
|
|
|
|
|
|
|
|
[\n\t ] {
|
|
|
|
//cout << "Scanner: whitechar (ignored)" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
[1-9][0-9]* {
|
|
|
|
std::cout << "Scanner: decimal number: " << yytext << '\n';
|
|
|
|
uint64_t number = strtoull(yytext, 0, 10);
|
|
|
|
return stela::Parser::make_NUMBER(number, stela::location());
|
|
|
|
}
|
|
|
|
|
|
|
|
. {
|
|
|
|
std::cout << "Scanner: unknown character [" << yytext << "]\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
<<EOF>> { return yyterminate(); }
|
|
|
|
|
|
|
|
|
|
|
|
%%
|