C 如何在Flex(词法分析器)中定义数字格式?
我需要的是: 可接受>1234和12.34 错误不可接受>12.34.56 L:C 如何在Flex(词法分析器)中定义数字格式?,c,compiler-construction,flex-lexer,lex,lexical-analysis,C,Compiler Construction,Flex Lexer,Lex,Lexical Analysis,我需要的是: 可接受>1234和12.34 错误不可接受>12.34.56 L: ... %% [0-9]+ printf("Number "); [0-9]+"."[0-9]+ printf("Decimal_Number "); "." printf("Dot "): %% ... 编译和运行后: Input : 1234 12.34 12.34.65 Output :
...
%%
[0-9]+ printf("Number ");
[0-9]+"."[0-9]+ printf("Decimal_Number ");
"." printf("Dot "):
%%
...
编译和运行后:
Input :
1234 12.34 12.34.65
Output :
Number Decimal_Number Decimal_Number Dot Number
如何打印错误而不是小数点或忽略它
是否可以将数字前后的空格定义为分隔符 这不是词法分析器的职责,而是解析器yacc或bison的职责。如果你定义。作为一个有效的符号,我们毫不奇怪
12.34.56
标记为
Decimal_Number Dot Number
关键是解析器不会有一个接受该令牌序列的规则,因此稍后会引发错误。空白通常被忽略,因此在数字之间强制使用空格是没有意义的,特别是在您可能有12.34+56.78而不会标记为十进制数二进制运算符十进制数的上下文中,因为它缺少空格。通常认为在解析器中检测12.34.56之类的错误比在扫描仪中检测更好。但也有一种观点认为,通过对错误进行词汇检测,可以产生更好的错误消息 如果你想这样做,你可以使用两种模式;第一种方法只检测正确的数字,第二种方法检测更大的字符串集,包括所有错误的字符串,但不检测任何合法的字符串。这取决于flex的匹配行为:它总是接受最长的匹配,如果最长的令牌由两个或多个规则匹配,它将使用第一个匹配规则 例如,假设您希望将点本身接受为“.”,将数字接受为数字标记,并在包含多个点的数字字符串上生成错误。你可以通过三条规则做到这一点:
/* If the token is just a dot, match it here */
\. { return '.'; }
/* Match integers without decimal points */
[[:digit:]]+ { return INTEGER; }
/* If the token is a number including a decimal point,
* match it here. This pattern will also match just '.',
* but the previous rules will be preferred.) */
[[:digit:]]*\.[[:digit:]]* { return FLOAT; }
/* This rule matches any sequence of dots and digits.
* That will also match single dots and correct numbers, but
* again, the previous rules are preferred. */
[.[:digit:]]+ { /* signal error */
return BADNUMBER; }
您需要非常小心使用上述解决方案。例如,最后一条规则将匹配。。和…,这可能是有效的标记,甚至是有效的序列。代币
例如,假设您的语言允许范围表达式,如4。。17表示从4到17的整数列表,或类似的列表。您的用户可能希望4..17被接受为范围表达式,但即使在添加规则时,上述内容也会产生BADNUMBER错误
".." { return RANGE; }
一开始,因为。。将在扫描的上一点匹配BADNUMBER
为了避免错误警报,我们需要修改BADNUMBER规则,以避免匹配包含两个或多个连续点的字符串。我们还需要确保4..17没有被lexed为4。然后是0.17。第二个问题可以通过坚持这样做来避免。开始和结束都不是数字标记,但这可能会激怒一些用户
因此,我们从实际的点标记开始:
"." { return '.'; }
".." { return RANGE; }
"..." { return ELLIPSIS; }
为了避免过度匹配后跟..的数字,我们可以使用flex的尾部上下文操作符。在这里,我们识别一个以a结尾的数字序列。仅当字符串后跟除a以外的其他内容时才作为数字:
现在我们需要修正错误规则。首先,我们将其限制为识别每个点后面跟一个数字的字符串。然后,与上面类似,我们匹配的情况是,有一个尾随的点后面没有另一个点:
[[:digit:]]*(\.[[:digit:]]+)+ { return BADNUMBER; }
[[:digit:]]*(\.[[:digit:]]+)+\./[^.] { return BADNUMBER; }
你可以检查我的程序来处理你的问题。但是,当你尝试使用莱克斯时,你应该知道,只要它与任何情况匹配,它就会起作用。 现在更改如下:
%%
[0-9]+ {printf("Number ");}
[0-9]+[.][0-9]*[.]+[0-9|.]* {printf("error ");}
[0-9]+[.][0-9]+ {printf("Decimal_Number ");}
%%
现在,程序可以按照您的需要工作
Input :
1234 12.34 12.34.65
Output :
Number Decimal_Number Error
你真的需要吗?12.34.56可能是一个语法错误,所以它不是一个词法错误真的很重要吗?所以没有一种方法可以实现我在Flex中所说的?也许可以搬走。定义还是什么?你的问题是一个XY问题,如果你真的想要,你可以在令牌中强制使用空格,就像你想要的一样,例如[0-9]+[0-9]+,但这是错误的,不应该被考虑。不,忽略空格的事情。有没有办法在Flex中返回错误或忽略12.34.56格式?谢谢,这很有帮助。感谢您的详细解释。在[0-9 |]中,|只是另一个字符,因此它将匹配文字|。@Md Shibbir Hossen-正是我想要的,非常感谢我添加的内容。{printfDot;},没有任何问题。不,这是或这里可能是0-9或。不是character |它在character类中,所以不,它不是或。这只是另一个角色。如果你想写一个数字或,你可以写[0-9.]。
Input :
1234 12.34 12.34.65
Output :
Number Decimal_Number Error