作为一个学习 Lex 词法分析程序的例子,下面的 lex 程序将会生成一个分析 LaTeX 中命令的词法分析器。下面的程序包含了很多 lex 语言的语法,正则表达式除外。正则表达式的用法网上比较多,这里不再赘述。
程序:tex_command.l
/* 第一部分:C++ 开头程序 */
%{
#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <format>
enum class token_t : int
{
eof = 0,
unused,
command,
};
inline std::string my_command_name;
%}
/* 第二部分(零):状态定义 */
%s MAKEATLETTER
/* 第二部分(一):正则表达式定义 */
command_no_at [A-Za-z]+
command_with_at [@A-Za-z]+
/* 第二部分(二):动作 */
%%
\\makeatletter {
BEGIN MAKEATLETTER;
my_command_name = yytext;
return static_cast<int>(token_t::command);
}
\\makeatother {
BEGIN INITIAL;
my_command_name = yytext;
return static_cast<int>(token_t::command);
}
<INITIAL>\\{command_no_at} |
<MAKEATLETTER>\\{command_with_at} {
my_command_name = yytext;
return static_cast<int>(token_t::command);
}
. { return static_cast<int>(token_t::unused); } /* 抑制输出,注意顺序,必须放在最后 */
%%
/* 第三部分:辅助函数 */
/* 若 yywrap 返回 0,则继续扫描;返回 1,则词法分析器返回报告文件已结束的 0。*/
int yywrap()
{
return 1;
}
int main(int argn, char** argv)
{
if (argn > 1)
{
if ((yyin = std::fopen(argv[1], "r")) == NULL)
{
std::cout << std::format("Can't open file {0}", argv[1]) << std::endl;
return 1;
}
}
else
yyin = stdin;
token_t ret;
do
{
ret = static_cast<token_t>(yylex());
if (ret > token_t::unused)
{
std::cout << std::endl <<
std::format("yylex returns with: {}", static_cast<int>(ret)) << std::endl;
std::cout << std::format("yytext is: {}", yytext) << std::endl;
switch (ret)
{
case token_t::command:
{
std::cout << std::format("command name is: {}", my_command_name) << std::endl;
break;
}
default:
break;
}
}
} while (ret != token_t::eof);
if (yyin)
std::fclose(yyin);
}
程序:run_lex.bat
win_flex --outfile=lex.yy.cpp --noline --wincompat %1
注意,需要使用最新的 MSVC 编译器并打开最新 C++ 标准才能编译。
测试输入数据
$$ {\latex}
\@for\relax
\makeatletter
\@for\relax
\makeatother
\@for
$$
测试输出
yylex returns with: 2
yytext is: \latex
command name is: \latex
yylex returns with: 2
yytext is: \relax
command name is: \relax
yylex returns with: 2
yytext is: \makeatletter
command name is: \makeatletter
yylex returns with: 2
yytext is: \@for
command name is: \@for
yylex returns with: 2
yytext is: \relax
command name is: \relax
yylex returns with: 2
yytext is: \makeatother
command name is: \makeatother
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)