【问题标题】:Number of tokens in compiler编译器中的标记数
【发布时间】:2017-06-03 14:20:48
【问题描述】:

我想知道下面给出的语句中的令牌数量

a+++b---c

请告诉我代币的数量 我告诉我的 viva 老师有 7 个令牌,但他说这是错误的。

【问题讨论】:

  • 你尝试的代码是什么?
  • "a" "++" "+" "b" "--" "-" "c" 如stackoverflow.com/questions/7485088/… "C和C++的词法分析器中所说,尽量匹配最大的字符串当他们看到某些东西时他们可以”和en.wikipedia.org/wiki/Maximal_munch
  • 是的,这可能是 C/C++ 语句
  • @osgx:在 C 中,唯一的上下文标记化是对 #include 预处理器指令的特殊处理。除此之外,它只是对一组可能的模式进行最大程度的咀嚼。
  • 这听起来很像你的导师完全错了。你的导师说这些代币是什么?我很难想象除 7 之外的答案。

标签: c expression token lexical-analysis compiler-construction


【解决方案1】:

你是对的。有七个标记:(在 C 中)

a
++
+
b
--
-
c

【讨论】:

  • @akansh:耸耸肩。
  • @akanshsinghal 如果你相信你的导师,那你为什么要在这里问? (我想说,我相信答案也是 7,但如果你要告诉我你的导师也不同意我的观点,那又有什么意义呢?)
【解决方案2】:

根据 C 标准(C11 之前的草案):http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf

6.4 词法元素

3 标记是翻译阶段 7 和 8 中语言的最小词汇元素。标记的类别是:关键字、标识符、常量、字符串文字和标点符号。 ...

4 如果输入流已经被解析为预处理标记直到给定字符,下一个预处理标记是可以构成预处理标记的最长字符序列。 ... 6 示例 2 程序片段 x+++++y 被解析为 x ++ ++ + y,这违反了对增量运算符的约束,即使解析 x ++ + ++ y 可能会产生正确的表达式

6.4.6 标点符号 .. 标点符号:++ -- ... + - 之一

因此,https://en.wikipedia.org/wiki/Maximal_munch 规则的使用如 https://stackoverflow.com/a/7485174 中所述,并评论 a+++b 片段:What does the operation c=a+++b mean? Shahbaz Sep 20 2011:“C 和 C++ 的词法分析器,尝试匹配最大的当他们看到某些东西时,他们可以找到字符串......因此,当词法分析器看到第一个加号时,它会尝试下一个字符,它认为它可以将两个字符都匹配为++,然后继续查看下一个@987654339 @. 因此,解析器看到a ++ + b"

虽然 gcc 和 clang 的代码很复杂,并且可能在单个代码示例 (so they are not best guides to the language, as rici said) 中混合不同的标准翻译阶段,但我们可能会检查 ++-- 的解析实现。当它看到 char + 时,它可能会根据下一个 char 生成不同的令牌,如果也是 +,则发出 plusplus 令牌,否则发出 plus 令牌:

http://code.metager.de/source/xref/llvm/clang/lib/Lex/Lexer.cpp#3264

3264  case '+':
3265    Char = getCharAndSize(CurPtr, SizeTmp);
3266    if (Char == '+') {
3267      CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
3268      Kind = tok::plusplus;
3269    } else if (Char == '=') {
3270      CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
3271      Kind = tok::plusequal;
3272    } else {
3273      Kind = tok::plus;
3274    }
3275    break;

http://code.metager.de/source/xref/gnu/gcc/libcpp/lex.c#2633

2633    case '+':
2634      result->type = CPP_PLUS;
2635      if (*buffer->cur == '+')
2636        buffer->cur++, result->type = CPP_PLUS_PLUS;
2637      else if (*buffer->cur == '=')
2638        buffer->cur++, result->type = CPP_PLUS_EQ;
2639      break;

所以,a+++b---c 表达式的标记是 a ++ + b -- - c。顾问可能会说你错了,但只是想让你解释为什么你认为你数了 7。如果问题与给定的任务相同,并且它是根据 C 标准(或 C++,即相同的词法),你可以解释你的答案并向他展示语言标准的相关部分。

【讨论】:

  • Gcc 记录更难的情况:gcc.gnu.org/onlinedocs/cppinternals/Lexer.html "转义的换行符很乏味,因为理论上它们可以出现在任何地方——在 '+' 和 '+=' 标记的 '=' 之间。 ..此外,你不能确定只有一个——它们可能有任意长的序列。” ..“_cpp_lex_direct主体中的类似代码不能简单地检查'+'字符后的'='以确定它是否具有'+='令牌;它需要准备某种转义的换行符。这种情况使用函数get_effective_char"
  • Osgx: nikolai 说对了一件事:特定编译器的实现并不是该语言的指南。编译器可能有问题或不一致。或者,在这种情况下,它可能会尝试利用“as-if”规则来使用快捷方式。 clang 和 gcc 都至少将阶段一到三的部分组合成一个词法分析器算法,因此引用它们的实际代码并不能很好地说明标准;事实上,这可能会让学生感到困惑。
  • @rici,谢谢!有没有更好的带有分离阶段的代码示例?那么compcert呢:github.com/AbsInt/CompCert/blob/master/cparser/Lexer.mll#L305rule initial = parse .... | "++" { INC(currentLoc lexbuf) }
  • 我不知道,但肯定有可能。 CompCert 是一个有趣的编译器,但它并不假装验证所有阶段:(来自手册)“§6.10 预处理指令 CompCert C 编译器本身不执行预处理,但将此任务委托给外部 C 预处理器,例如GCC。假定外部预处理器符合 C99 标准。"
猜你喜欢
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-09
  • 2016-03-29
  • 1970-01-01
相关资源
最近更新 更多