【发布时间】:2011-07-28 23:08:55
【问题描述】:
除了不关闭评论/*...,C 语言中的词法错误是什么?
【问题讨论】:
标签: c compiler-errors lexical-analysis
除了不关闭评论/*...,C 语言中的词法错误是什么?
【问题讨论】:
标签: c compiler-errors lexical-analysis
格式错误的浮点常量(例如123.34e 或123.45.33)。
【讨论】:
词法错误:
0xe-2,它看起来像一个表达式,但根据标准实际上是一个语法错误——一个奇怪的极端情况,由 pp-tokens 规则产生。 【讨论】:
非法身份
int 3d = 1;
非法的预处理指令
#define x 1
意外的令牌
if [0] {}
无法解析的id
while (0) {}
【讨论】:
如果放在字符串或注释之外的任何地方,C 中的 [@$`] 和其他类似的符号(可能来自 unicode)是否会出现词法错误?它们不构成该语言的任何有效词汇序列。它们无法通过词法分析器,因为词法分析器无法将它们识别为任何类型的有效标记。通常,词法分析器是基于 FSM 或正则表达式的,因此这些符号只是无法识别的输入。
例如在下面的代码中有几个词法错误:
int main(void){
` int a = 3;
@ —
return 0;
}
我们可以通过将它提供给 gcc 来支持它,这给了
../a.c: In function ‘main’:
../a.c:2: error: stray ‘`’ in program
../a.c:3: error: stray ‘@’ in program
../a.c:3: error: stray ‘\342’ in program
../a.c:3: error: stray ‘\200’ in program
../a.c:3: error: stray ‘\224’ in program
GCC 很聪明,并且会进行错误恢复,因此它解析了一个函数定义(它知道我们在“main”中),但这些错误绝对看起来像词法错误,它们不是语法错误,这是正确的。 GCC 的词法分析器没有可以从这些符号构建的任何类型的标记。请注意,它甚至将一个三字节的 UTF-8 符号视为三个无法识别的符号。
【讨论】:
如果编译器根据此语法进行词法分析,则基本上任何不符合 ISO C 9899/1999 附件 A.1“词法语法”的内容都是词法错误。以下是一些示例:
"abc<EOF> // invalid string literal (from Ira Baxter's answer) (ISO C 9899/1999 6.4.4.5)
'a<EOF> // invalid char literal (6.4.4.4)
EOF 是文件的结尾。
double a = 1e*3; // misguided floating point literal (6.4.4.2)
int a = 0x0g; // invalid integer hex literal (6.4.4.1)
int a = 09; // invalid octal literal (6.4.4.1)
char a = 'aa'; // too long char literal (from Joel's answer, 6.4.4.4)
double a = 0x1p1q; // invalid hexadecimal floating point constant (6.4.4.2)
// instead of q, only a float suffix, that is 'f', 'l', 'F' or 'L' is allowed.
// invalid header name (6.4.7)
#include <<a.h>
#include ""a.h"
【讨论】:
0[0-7]* 匹配时,我认为是。
这里有一些:
"abc<EOF>
其中 EOF 是文件的结尾。事实上,很多词位中间的EOF应该会产生错误:
0x<EOF>
我认为在字符串中使用错误的转义是非法的:
"ab\qcd"
浮点指数可能有问题
1e+%
可以说,您不应该在预处理器指令的末尾添加内容:
#if x %
【讨论】:
"abc<EOL> 是一个词法错误吗? (行尾而不是文件尾)
yacc 规则来检查这个语法QUOTE LETTERS QUOTE,或者一个lex 正则表达式来完成\"[a-z]*\" 的工作(当然是简化版)。现在,这是 lex 还是语法错误,取决于实现?还是有一些我们都同意的默认值?