如何描述识别通配符标识符的 lex 或 yacc 规则?
How to describe a lex or yacc rule to recognize wildcard identifier?
待解析的文本中有这样的文件系统相关命令的例子
infile abc*.txt
list abc*ff.txt
其中 abc*.txt 类似于 shell 命令的通用通配符参数。
不过,也有这样的数学表达式:
x=a*b
一个常见的表达式规则(在 yacc 文件中)是这样的:
expression:
expression '+' expression { $$ = + ; }
| expression '-' expression { $$ = - ; }
| expression '*' expression { $$ = * ; }
;
* 用作乘法运算符。
识别带 * 的令牌 IDENTIFIER 的规则如下:
[A-Za-z][A-Za-z0-9_\.\*]* {
yylval.strval = strdup(yytext); return IDENTIFIER; }
对于infile或list等文件系统命令相关的语法,如开头的,后面的token会被当作IDENTIFIER,可能会有*作为通配符来匹配文件名。
但是对于像
这样的表达式
x = a*b
这应该是一个表达式,但在上面的 lex 规则中,a*b 将被视为一个 IDENTIFIER。它变成了将标识符 a*b 的值赋给 x.
如何在lex或yacc中保持表达式的语法规则并添加通配符文件名?
在 flex 中,这一切都可以通过使用所谓的 Start Conditions 来处理,并且在手册中有很好的描述,示例与您的要求相似。
我做了一个小示例词法分析器来演示这个工作:
ws [ \t\n\r]+
%s FILENAME
%%
{ws} ; /* skip */
<<EOF>> ;
<INITIAL>infile BEGIN(FILENAME);
<INITIAL>list BEGIN(FILENAME);
<FILENAME>[A-Za-z][A-Za-z0-9_\.\*]* BEGIN(INITIAL);
"*" return(yytext[0]);
"+" return(yytext[0]);
"-" return(yytext[0]);
"/" return(yytext[0]);
[A-Za-z][A-Za-z0-9_]* return((int)("I"));
. printf("Bad character %c\n",yytext[1]);
我可以在调试模式下执行以显示其操作:
C:\Users\Brian>flex -d SOwildcard.l
C:\Users\Brian>gcc -o SOwildcard.exe lex.yy.c -lfl
C:\Users\Brian>SOwildcard
--(end of buffer or a NUL)
a + b
--accepting rule at line 13 ("a")
--accepting rule at line 4 (" ")
--accepting rule at line 10 ("+")
--accepting rule at line 4 (" ")
--accepting rule at line 13 ("b")
--(end of buffer or a NUL)
infile a*.txt
--accepting rule at line 4 ("
")
--accepting rule at line 6 ("infile")
--accepting rule at line 4 (" ")
--accepting rule at line 8 ("a*.txt")
--(end of buffer or a NUL)
variable * identifier
--accepting rule at line 4 ("
")
--accepting rule at line 13 ("variable")
--accepting rule at line 4 (" ")
--accepting rule at line 9 ("*")
--accepting rule at line 4 (" ")
--accepting rule at line 13 ("identifier")
--(end of buffer or a NUL)
list a*.*
--accepting rule at line 4 ("
")
--accepting rule at line 7 ("list")
--accepting rule at line 4 (" ")
--accepting rule at line 8 ("a*.*")
--(end of buffer or a NUL)
--accepting rule at line 4 ("
")
-^C
我知道你问过 lex,但我只有 flex。可能是相似的。
待解析的文本中有这样的文件系统相关命令的例子
infile abc*.txt
list abc*ff.txt
其中 abc*.txt 类似于 shell 命令的通用通配符参数。
不过,也有这样的数学表达式:
x=a*b
一个常见的表达式规则(在 yacc 文件中)是这样的:
expression:
expression '+' expression { $$ = + ; }
| expression '-' expression { $$ = - ; }
| expression '*' expression { $$ = * ; }
;
* 用作乘法运算符。
识别带 * 的令牌 IDENTIFIER 的规则如下:
[A-Za-z][A-Za-z0-9_\.\*]* {
yylval.strval = strdup(yytext); return IDENTIFIER; }
对于infile或list等文件系统命令相关的语法,如开头的,后面的token会被当作IDENTIFIER,可能会有*作为通配符来匹配文件名。
但是对于像
这样的表达式x = a*b
这应该是一个表达式,但在上面的 lex 规则中,a*b 将被视为一个 IDENTIFIER。它变成了将标识符 a*b 的值赋给 x.
如何在lex或yacc中保持表达式的语法规则并添加通配符文件名?
在 flex 中,这一切都可以通过使用所谓的 Start Conditions 来处理,并且在手册中有很好的描述,示例与您的要求相似。
我做了一个小示例词法分析器来演示这个工作:
ws [ \t\n\r]+
%s FILENAME
%%
{ws} ; /* skip */
<<EOF>> ;
<INITIAL>infile BEGIN(FILENAME);
<INITIAL>list BEGIN(FILENAME);
<FILENAME>[A-Za-z][A-Za-z0-9_\.\*]* BEGIN(INITIAL);
"*" return(yytext[0]);
"+" return(yytext[0]);
"-" return(yytext[0]);
"/" return(yytext[0]);
[A-Za-z][A-Za-z0-9_]* return((int)("I"));
. printf("Bad character %c\n",yytext[1]);
我可以在调试模式下执行以显示其操作:
C:\Users\Brian>flex -d SOwildcard.l
C:\Users\Brian>gcc -o SOwildcard.exe lex.yy.c -lfl
C:\Users\Brian>SOwildcard
--(end of buffer or a NUL)
a + b
--accepting rule at line 13 ("a")
--accepting rule at line 4 (" ")
--accepting rule at line 10 ("+")
--accepting rule at line 4 (" ")
--accepting rule at line 13 ("b")
--(end of buffer or a NUL)
infile a*.txt
--accepting rule at line 4 ("
")
--accepting rule at line 6 ("infile")
--accepting rule at line 4 (" ")
--accepting rule at line 8 ("a*.txt")
--(end of buffer or a NUL)
variable * identifier
--accepting rule at line 4 ("
")
--accepting rule at line 13 ("variable")
--accepting rule at line 4 (" ")
--accepting rule at line 9 ("*")
--accepting rule at line 4 (" ")
--accepting rule at line 13 ("identifier")
--(end of buffer or a NUL)
list a*.*
--accepting rule at line 4 ("
")
--accepting rule at line 7 ("list")
--accepting rule at line 4 (" ")
--accepting rule at line 8 ("a*.*")
--(end of buffer or a NUL)
--accepting rule at line 4 ("
")
-^C
我知道你问过 lex,但我只有 flex。可能是相似的。