【问题标题】:Creating a Lexical Analyzer in C在 C 中创建词法分析器
【发布时间】:2013-08-23 06:25:34
【问题描述】:

我正在尝试用 C 创建一个词法分析器。 程序读取另一个程序作为输入转换成token,源码在这里-

#include <stdio.h>
#include <conio.h>
#include <string.h>

int main()  {
    FILE *fp;
    char read[50];
    char seprators [] = "\n";
    char *p;
    fp=fopen("C:\\Sum.c", "r");

    clrscr();

    while ( fgets(read, sizeof(read)-1, fp) !=NULL )    {
        //Get the first token
        p=strtok(read, seprators);

        //Get and print other tokens
        while (p!=NULL) {
            printf("%s\n", p);
            p=strtok(NULL, seprators);
        }
    }

    return 0;
}

而Sum.c的内容是-

#include <stdio.h>

int main()  {
    int x;
    int y;
    int sum;

    printf("Enter two numbers\n");
    scanf("%d%d", &x, &y);

    sum=x+y;

    printf("The sum of these numbers is %d", sum);

    return 0;
}

我没有得到正确的输出,只看到一个空白屏幕代替输出。

谁能告诉我我哪里出错了? 提前非常感谢你..

【问题讨论】:

  • 确保确保您的文件已成功打开。你永远不会检查它,运行时的当前工作目录通常不是你想的那样,特别是如果你是从 IDE 或其他类似工具运行的。验证fopen() 成功,如果没有,perror("Failed to open file."); 并退出。至少你会知道这是问题所在。
  • 如果要打印令牌,选择seprators 值为"\n"; 是错误的。
  • 如果你真的想创建一个词法分析器,我强烈推荐你使用 Flex (en.wikipedia.org/wiki/Flex_lexical_analyser)
  • @Michael:这可能是了解词法分析器如何工作的家庭作业。在这种情况下,Flex 是最糟糕的学习方式!
  • @dave- 你说得对……这是学术作业的一部分……

标签: c parsing lexical-analysis


【解决方案1】:

自从这个问题以来,你已经问了几个问题,所以我猜你已经继续前进了。关于您的问题和您开始解决类似问题的解决方案,有几点需要注意。 You'll also find that people can often be slow at answering things that are obvious homework。我们经常等到作业截止日期过去。 :-)

首先,我注意到您使用了一些特定于 Borland C 编译器的非标准特性,不会使解决方案具有可移植性或通用性。你可以在没有他们的情况下解决问题,这通常是一个不错的选择。例如,您将#include &lt;conio.h&gt; 用于clear the screen with a clrscr();,这可能是不必要的,并且与词法分析器问题无关。

我测试了这个程序,写出来的它可以工作!它将文件Sum.c 的所有行转录为stdout。如果您只看到一个空白屏幕,那是因为它找不到文件。要么您没有将其写入您的C:\ 目录,要么使用了不同的名称。正如@WhozCraig you need to check that the file was found and opened properly 已经提到的那样。

我看到您正在使用 C 函数 strtok 将输入划分为标记。有一些nice examples of using this in the documentation you could include in your code,比您的简单案例做得更多。正如@Grijesh Chauhan 所提到的,要考虑的分隔符比\n 或行尾要多。例如,空格和制表符呢?

但是,在程序中,事物并不总是由空格和行分隔。举个例子:

result=(number*scale)+total;

如果我们只使用空格作为分隔符,那么它不会识别所使用的单词,而只会提取整个表达式,这显然不是分词。我们可以将这些东西添加到分隔符列表中:

char seprators [] = "\n=(*)+;";

那么你的代码也会挑选出这些词。该策略仍然存在缺陷,因为在编程语言中,这些符号也是需要识别的标记。编程语言标记化的问题是标记之间没有明确的分隔符。

这背后有很多理论,但基本上我们必须写下构成我们想要识别的标记基础的模式,而不是查看它们之间的差距,因为正如已经显示的那样,没有'没有!这些模式通常写为regular expressions。计算机科学理论告诉我们,我们可以使用finite state automata 来匹配这些正则表达式。 Writing a lexer involves a particular style of coding,有这种风格:

while ( NOT <<EOF>> ) {
  switch ( next_symbol() ) {

     case state_symbol[1]: 
              ....
             break;

      case state_symbol[2]:
              ....
              break;

       default:
             error(diagnostic);
  }
}

所以,现在,也许学术任务的价值变得更加清晰了。

【讨论】:

  • 非常感谢您提供如此广泛的答案...我确实已经继续前进了,但是您的这个回答让我明白了我们在研究生院所做的实验室作业的重要性....?
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2010-11-02
  • 2017-02-20
  • 2022-10-22
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多