【问题标题】:Parsers and Compilers for Dummies. Where to start? [duplicate]傻瓜解析器和编译器。从哪儿开始? [复制]
【发布时间】:2010-09-30 09:17:07
【问题描述】:

这是一个很好的listing,但是对于这个领域的一个完整的新手来说,什么是最好的。适合来自更高级别背景(VB6、C#、Java、Python)的人 - 不熟悉 C 或 C++。在这个阶段,我对手写解析比 Lex/Yacc 更感兴趣。

如果我的专业是计算机科学而不是心理学,我可能会在大学里上这门课。哦,好吧。

【问题讨论】:

  • 顺便说一句,手写解析器而不是使用 YACC/similar 确实有它的位置,但似乎词法分析/扫描阶段很少是手写的。此外,大多数成熟的编程语言似乎都类似于 Lex 和 Yacc。
  • 有 CPython 吗?我在看那个源代码,它似乎是手写的。我认为 PHP 似乎是 Yacc 的。我认为 Python 对我来说是最容易理解的。我不确定我是否遵循任何生成的 C 代码。

标签: parsing compiler-construction


【解决方案1】:

请看:learning to write a compiler

也很有趣:

还有更多关于这个主题的内容。但我可以简单介绍一下:

第一步是词法分析。字符流被转换为标记流。标记可以很简单,例如 ==

下一步是将令牌流转换为语法树或其他表示形式。这称为解析步骤。

在创建解析器之前,您需要编写语法。例如我们创建一个表达式解析器:

代币

addOp = '+' | '-';
mulOp = '*' | '/';
parLeft = '(';
parRight = ')';
number = digit, {digit};
digit = '0'..'9';

Each token can have different representations: + and = are both addOp and 
23 6643 and 223322 are all numbers.

语言

exp = term | exp, addOp, term;  
// an expression is a series of terms separated by addOps.
term = factor | term, mulOp, factor;
// a term is a series of factors separated by mulOps
factor = addOp, factor | parLeft, exp, parRight | number;
// a factor can be an addOp followed by another factor, 
// an expression enclosed in parentheses or a number.

词法分析器

我们创建一个遍历字符流的状态引擎,创建一个令牌

s00 
  '+', '-' -> s01       // if a + or - is found, read it and go to state s01.
  '*', '/' -> s02
  '('      -> s03
  ')'      -> s04
  '0'..'9' -> s05
  whitespace -> ignore and retry  // if a whitespace is found ignore it
  else ERROR      // sorry but we don't recognize this character in this state.
s01
  found TOKEN addOp     // ok we have found an addOp, stop reading and return token
s02 
  found TOKEN mulOp
s03
  found TOKEN parLeft
s04
  found TOKEN parRight
s05
  '0'..'9'     -> s05    // as long as we find digits, keep collecting them
  else found number      // last digit read, we have a number

解析器

现在是时候创建一个简单的解析器/评估器了。这在代码中是完整的。通常它们是使用表创建的。但我们保持简单。读取令牌并计算结果。

ParseExp
  temp = ParseTerm // start by reading a term
  while token = addOp do
    // as long as we read an addop keep reading terms
    if token('+') then temp = temp + ParseTerm  // + so we add the term
    if token('-') then temp = temp - ParseTerm  // - so we subtract the term
  od
  return temp // we are done with the expression

ParseTerm
  temp = ParseFactor
  while token = mulOp do
    if token('*') then temp = temp * ParseFactor
    if token('/') then temp = temp / ParseFactor
  od
  return temp

ParseFactor
  if token = addOp then
    if token('-') then return - ParseFactor  // yes we can have a lot of these
    if token('+') then return ParseFactor
  else if token = parLeft then
    return ParseExpression
    if not token = parRight then ERROR
  else if token = number then
    return EvaluateNumber   // use magic to translate a string into a number

这是一个简单的例子。在实际示例中,您将看到错误处理是解析器的重要组成部分。

我希望这可以澄清一点 ;-)。

【讨论】:

  • 谢谢。这是很棒的东西。我想有几个阶段让我感到困惑。现在我可以在每个阶段阅读更多内容。
  • 很好的答案!!
【解决方案2】:

如果您是一个完整的 n00b,那么最容易访问的资源(在该术语的两种意义上)可能是 Jack Crenshaw's tutorial。它远非全面,但对于入门而言,除了早已绝版的书籍之外,我想不出任何接近的东西。

【讨论】:

    【解决方案3】:

    我想推荐一篇我写的文章,名为Implementing Programming Languages using C# 4.0。我试图让新手可以使用它。不是很全面,但是之后应该更容易理解其他更高级的文本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 2012-06-13
      • 2013-10-21
      • 2012-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多