-
Notifications
You must be signed in to change notification settings - Fork 17
/
scanner.l
106 lines (92 loc) · 2.58 KB
/
scanner.l
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
%{
#include <cerrno>
#include <climits>
#include <cstdlib>
#include <cstring> // strerror
#include <string>
#include <iostream>
#include "driver.hh"
#include "parser.hh"
%}
%option noyywrap nounput noinput batch debug
%option c++
%option yyclass="Scanner"
%{
// Code definitions at the end of scanner.cpp
// 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
);
void Scanner::UpdateLocation() {
if (driver.location_debug) {
std::cerr << "Action called " << driver.location << std::endl;
}
driver.location.columns(yyleng);
}
%}
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 UpdateLocation();
%}
%%
%{
// A handy shortcut to the location held by the driver.
yy::location& loc = driver.location;
if (driver.location_debug) {
// Code run each time yylex is called.
std::cerr << "BEFORE " << loc << std::endl;
}
// loc.step();
if (driver.location_debug) {
std::cerr << "AFTER " << loc << std::endl;
}
%}
{blank}+ {
if (driver.location_debug) {
std::cerr << "Blank matched" << std::endl;
}
// loc.step();
}
\n+ {
if (driver.location_debug) {
std::cerr << "EOL called" << std::endl;
}
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);
";" return yy::parser::make_SEMICOLON(loc);
{int} return make_NUMBER(yytext, loc);
{id} {
if (driver.location_debug) {
std::cerr << "ID found " << yytext << std::endl;
}
return yy::parser::make_IDENTIFIER(yytext, loc);
}
. {
throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext));
}
<<EOF>> return yy::parser::make_END (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);
}