.l
%option noyywrap
%option nounput
%option noinput
%{
#include <cstdlib>
#include <string>
#include "sysy.tab.hpp"
using namespace std;
%}
WhiteSpace [ \t\n\r]*
[] 表示一个字符集合,可以匹配其中任意一个字符。
\t 表示制表符(tab)。
\n 表示换行符(newline)。
\r 表示回车符(carriage return)。
* 表示匹配前一个字符零次或多次,即可以出现也可以不出现
?非贪婪匹配 代替 *
+? 代替 +
LineComment "
. 表示匹配任意一个字符(除了换行符之外)
Identifier [a-zA-Z_][a-zA-Z0-9_]*
以字母或下划线开头 后跟零个或多个字母、数字或下划线的标识符
连接
Decimal [1-9][0-9]*
表示一个十进制整数,首位为 1 到 9,后跟零个或多个数字
连接
Octal 0[0-7]*
表示一个八进制整数,以 0 开头,后跟零个或多个 0 到 7 的数字。
Hexadecimal 0[xX][0-9a-fA-F]+
表示一个十六进制整数,以 0x 或 0X 开头,后跟至少一个 0 到 9 或 a 到 f(大小写均可)的数字。
`+` 表示匹配前一个字符一次或多次,即至少出现一次。
%%
{WhiteSpace} { }
{LineComment} { }
"int" { return INT; }
"return" { return RETURN; }
在Flex的正则表达式中,可以直接使用字符串来匹配输入流中的相应内容
{Identifier} { yylval.str_val = new string(yytext); return IDENT; }
将Flex识别出来的标识符的字符串值(即yytext)
存储在yylval变量的str_val成员中
return的IDENT是在Bison的.y文件中定义的一个token类型
(表示已经识别出一个标识符)
{Decimal} { yylval.int_val = strtol(yytext, nullptr, 0); return INT_CONST; }
strtol将字符串转换为长整型数值
需要转换的字符串,函数将返回长整型的数值,根据字符串的内容自动选择转换的进制
{Octal} { yylval.int_val = strtol(yytext, nullptr, 0); return INT_CONST; }
{Hexadecimal} { yylval.int_val = strtol(yytext, nullptr, 0); return INT_CONST; }
. { return yytext[0]; }
表示返回字符流的第一个字符作为token
如果Flex扫描器无法识别输入中的任何一个模式,
则会将下一个字符作为一个通用token返回给Bison解析器。
在Bison解析器中,这个通用token通常被视为错误,
表示在源代码中存在语法错误
%%
.y
%code requires {
#include <memory>
#include <string>
}
%{
#include <iostream>
#include <memory>
#include <string>
int yylex();
void yyerror(std::unique_ptr<std::string> &ast, const char *s);
using namespace std;
%}
%parse-param { std::unique_ptr<std::string> &ast }
%union {
std::string *str_val;
int int_val;
}
%token INT RETURN
%token <str_val> IDENT
%token <int_val> INT_CONST
%type <str_val> FuncDef FuncType Block Stmt Number
%%
CompUnit
: FuncDef {
ast = unique_ptr<string>($1);
}
;
FuncDef
: FuncType IDENT '(' ')' Block {
auto type = unique_ptr<string>($1);
auto ident = unique_ptr<string>($2);
auto block = unique_ptr<string>($5);
$$ = new string(*type + " " + *ident + "() " + *block);
}
;
FuncType
: INT {
$$ = new string("int");
}
;
Block
: '{' Stmt '}' {
auto stmt = unique_ptr<string>($2);
$$ = new string("{ " + *stmt + " }");
}
;
Stmt
: RETURN Number ';' {
auto number = unique_ptr<string>($2);
$$ = new string("return " + *number + ";");
}
;
Number
: INT_CONST {
$$ = new string(to_string($1));
}
;
%%
void yyerror(unique_ptr<string> &ast, const char *s) {
cerr << "error: " << s << endl;
}