Flex/Lex:正则表达式匹配双字符
Flex/Lex: Regular Expression matches double characters
我有一个用 C++ 编写的 flex 程序需要完成以下规则:
我希望 yytext 接受以下内容:
○ 零个或以下字符之一 ABCDEFGH
例如 - 输入:
“三角形 ABC”是一个有效的形状,我希望程序打印“有效的形状”
“三角形 AAC”不是有效形状,因为它包含一个双 A,我希望程序在这种情况下不打印任何内容
“三角形 ABCD”不是有效的形状,因为它包含四个字母,在这种情况下我也希望程序不打印任何内容。
下面的代码以及我到目前为止尝试的正则表达式:
%{
/** Methods and Variables initialization **/
%}
corner corner" "[A-H]
line line" "[A-H]{2}
triangle triangle" "[A-H]{3}
square rectangle" "[A-H]{4}
poly pentagon" "[A-H]{5}
hexa hexagon" "[A-H]{6}
hepta heptagon" "[A-H]{7}
octa octagon" "[A-H]{8}
/** Below is the rule section -- yytext is the matched string returned to the program **/
%%
{corner}
{line} |
{triangle} |
{square} |
{poly} |
{hexa} |
{hepta} |
{octa} {
printf("Valid shape: %s", yytext);
}
.
%%
int main() {
yylex();
return 0;
}
// yywrap() - wraps the above rule section
int yywrap(void)
{
return 1;
}
当前输入:
三角形AAC
当前输出:
有效形状:三角形 AAC(我们不需要那个)
当前输入:
三角形AB
当前输出:
有效形状:三角形 ABC
这不是您通常会使用 (f)lex 解决的那种问题,因为基本的词法分析是微不足道的(只需在 space 处拆分行即可完成)并且详细错误分析有点超出 (f)lex 的舒适区,特别是因为无法使用正则表达式匹配“包含相同字符两次的字符串”。
不过,如 question asked by one of your classmates 所示,它可以通过 (f)lex 利用扫描器的排序规则来完成:
- 始终使用最长的匹配。
- 如果有两个或多个规则符合条件,请选择第一个。
这并没有解决重复字符的问题。解决这个问题的唯一方法是枚举所有可能性,在本例中有八种可能性。比链接问题中提出的方法更简单的方法是 [A-H]*A[A-H]*A[A-H]*|[A-H]*B[A-H]*B[A-H]*|[A-H]*C[A-H]*C[A-H]*...
.
让我们创建一组有序的规则,如下所示:
- 匹配具有重复字符的行
- 匹配字符过多的行
- 匹配字符数完全正确的行
- 其他都是错误。 (字符太少、形状名称无效、字母无效等)
所以这可能包括这个(省略了两个宏的定义,这很简单但很乏味):
/* 1. Dups */
[a-z]+\ {dups}$ { err("Duplicate letter"); }
/* 2. Too long */
{valid}[A-H]+$ { err("Too long"); }
/* 3. Just right */
{valid}$ { printf("Valid: %s\n", yytext); }
/* 4. Anything else */
.+ { err("Too short or invalid character"); }
/* Ignore newlines */
\n ;
我有一个用 C++ 编写的 flex 程序需要完成以下规则:
我希望 yytext 接受以下内容:
○ 零个或以下字符之一 ABCDEFGH
例如 - 输入:
“三角形 ABC”是一个有效的形状,我希望程序打印“有效的形状”
“三角形 AAC”不是有效形状,因为它包含一个双 A,我希望程序在这种情况下不打印任何内容
“三角形 ABCD”不是有效的形状,因为它包含四个字母,在这种情况下我也希望程序不打印任何内容。
下面的代码以及我到目前为止尝试的正则表达式:
%{
/** Methods and Variables initialization **/
%}
corner corner" "[A-H]
line line" "[A-H]{2}
triangle triangle" "[A-H]{3}
square rectangle" "[A-H]{4}
poly pentagon" "[A-H]{5}
hexa hexagon" "[A-H]{6}
hepta heptagon" "[A-H]{7}
octa octagon" "[A-H]{8}
/** Below is the rule section -- yytext is the matched string returned to the program **/
%%
{corner}
{line} |
{triangle} |
{square} |
{poly} |
{hexa} |
{hepta} |
{octa} {
printf("Valid shape: %s", yytext);
}
.
%%
int main() {
yylex();
return 0;
}
// yywrap() - wraps the above rule section
int yywrap(void)
{
return 1;
}
当前输入:
三角形AAC
当前输出:
有效形状:三角形 AAC(我们不需要那个)
当前输入:
三角形AB
当前输出:
有效形状:三角形 ABC
这不是您通常会使用 (f)lex 解决的那种问题,因为基本的词法分析是微不足道的(只需在 space 处拆分行即可完成)并且详细错误分析有点超出 (f)lex 的舒适区,特别是因为无法使用正则表达式匹配“包含相同字符两次的字符串”。
不过,如 question asked by one of your classmates 所示,它可以通过 (f)lex 利用扫描器的排序规则来完成:
- 始终使用最长的匹配。
- 如果有两个或多个规则符合条件,请选择第一个。
这并没有解决重复字符的问题。解决这个问题的唯一方法是枚举所有可能性,在本例中有八种可能性。比链接问题中提出的方法更简单的方法是 [A-H]*A[A-H]*A[A-H]*|[A-H]*B[A-H]*B[A-H]*|[A-H]*C[A-H]*C[A-H]*...
.
让我们创建一组有序的规则,如下所示:
- 匹配具有重复字符的行
- 匹配字符过多的行
- 匹配字符数完全正确的行
- 其他都是错误。 (字符太少、形状名称无效、字母无效等)
所以这可能包括这个(省略了两个宏的定义,这很简单但很乏味):
/* 1. Dups */
[a-z]+\ {dups}$ { err("Duplicate letter"); }
/* 2. Too long */
{valid}[A-H]+$ { err("Too long"); }
/* 3. Just right */
{valid}$ { printf("Valid: %s\n", yytext); }
/* 4. Anything else */
.+ { err("Too short or invalid character"); }
/* Ignore newlines */
\n ;