为 lex/yacc 中的可打印字符创建规则

Creating a rule for a printable character in lex/yacc

我想为可打印字符(使用 C isprint() 函数 returns true 的任何字符创建语法规则。

为此,我在 lex 文件中创建了以下正则表达式规则:

[\x20-\x7E] { yylval.ch = strdup(yytext); return CHARACTER; }

正则表达式包含基于 ASCII 十六进制值的所有可打印字符。

在我第一次尝试时,这条规则位于底部,但显然没有包括之前已经说明的任何可打印字符,例如,如果我输入的是字符 '+' 并且我之前有一个规则:

"+" { return PLUS_OPERATOR; }

解析器接受它作为 PLUS_OPERATOR 而不是 CHARACTER

然后我尝试将字符规则放在我的扫描仪顶部,出于与以前相同的原因 - 以下所有字符在可打印范围内的规则都无法匹配。

我的问题是如何创建既匹配所有可打印字符又匹配特定字符的规则。

我唯一能想到的就是把它放在底部,并使用所有单字符正则表达式规则和字符规则的语法规则(例如CHAR : PLUS_OPERATOR | MINUS_OPERATOR | EQUAL_OPERATOR | CHARACTER

我的 lex 文件中有超过 3 个单字符规则,所以显然我正在寻找更优雅的解决方案。

唯一的解决方案是您提出的解决方案:创建一个非终端,它是所有相关终端的联合。

就我个人而言,如果将单字符标记写成它们自己,我发现语法更易读,所以我会写:

printable: '+' | '-' | '=' | CHAR

在 bison 文件和扫描仪中:

[-+=]        { yylval.ch = yytext[0]; return yylval.ch; } 
[[:print:]]  { yylval.ch = yytext[0]; return CHAR; }

(这又要求语义类型是 char 和 char* 字段的联合;优点是您无需担心释放为运算符字符创建的字符串。)

恐怕这已经是最优雅的了。