实现词法分析器

时间:2012-05-10 03:29:43

标签: java regex analyzer lexical

我有一个为语言c--实现词法分析器的任务。我们必须将c--代码转换为一系列将在内部表示为整数的标记,因为它更容易操作。该语言的一些词汇约定是有关键字,如double,else,if,int,return,void和while。还有特殊符号,如+ - * /< < => > = ==!= =; ,。 ()[] {} / * * / //。 标识符可以以任何字母或下划线开头,后跟字母,数字和下划线的任意组合。空格分隔标记并被忽略。数字可以是整数或小数,也可以使用注释行和块。

import java.io.*;
public class Lex {

    public static boolean contains(char[] a, char b){
        for (int i = 0; i < a.length; i++) {
            if(b == a[i])
                return true;
        }
        return false;
    } 
    public static void main(String args[]) throws FileNotFoundException, IOException{

        //Declaring token values as constant integers.
        final int T_DOUBLE = 0; 
        final int T_ELSE = 1;
        final int T_IF = 2; 
        final int T_INT = 3;
        final int T_RETURN = 4; 
        final int T_VOID = 5;
        final int T_WHILE = 6; 
        final int T_PLUS = 7;
        final int T_MINUS = 8; 
        final int T_MULTIPLICATION = 9;
        final int T_DIVISION = 10; 
        final int T_LESS = 11;
        final int T_LESSEQUAL = 12; 
        final int T_GREATER = 13;
        final int T_GREATEREQUAL = 14; 
        final int T_EQUAL = 16;
        final int T_NOTEQUAL = 17;
        final int T_ASSIGNOP = 18; 
        final int T_SMEICOLON = 19;
        final int T_PERIOD = 20; 
        final int T_LEFTPAREN = 21;
        final int T_RIGHTPAREN = 22; 
        final int T_LEFTBRACKET = 23;
        final int T_RIGHTBRACKET = 24; 
        final int T_LEFTBRACE = 25;
        final int T_RIGHTBRACE = 26; 
        final int T_ID = 27;
        final int T_NUM = 28;
        char[] letters_ = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D',
            'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_'};
        char[] numbers = {'0','1','2','3','4','5','6','7','8','9'};
        char[] symbols = {'+','-','*','/','<','>','!','=',':',',','.','(',')','[',']','{','}'};
        FileInputStream fstream = new FileInputStream("src\\testCode.txt");
        DataInputStream in = new DataInputStream(fstream);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        BufferedWriter bw1 = new BufferedWriter(new FileWriter(new File("src\\output.txt"), true));
        BufferedWriter bw2 = new BufferedWriter(new FileWriter(new File("src\\output2.txt"), true));
        String scanner;String temp = "";
        int n = 0;
        while((scanner = br.readLine()) != null){
            for (int i = 0; i < scanner.length(); i++) {
                for (int j = 0; j < scanner.length(); j++) {
                    if(contains(letters_,scanner.charAt(i)) || contains(numbers,scanner.charAt(i)) || contains(symbols,scanner.charAt(i))){
                        j++;
                        n++;
                        if(scanner.charAt(j) == ' ' || scanner.charAt(j) == '\n' || scanner.charAt(j) == '\t'){

                        }
                    }

                }

            }
        }

        in.close();


    }

}

这是我们的测试代码:

int fact(int x) {
// recursive factorial function 
   if (x>1) 
      return x * fact(x-1);
   else return 1;
}

void main(void) {
/* CS 311 project 2
A lexical analyzer */
   int x, y, z;
   double _funny;
   x = get_integer();
   _Funny = get_double();
   if (x>0) 
      print_line(fact(x));
   else if (_funny != 3.14) 
      print_line(x*_funny);
}

这应该是我们的输出

  

3 27 21 3 27 22 25 2 21 27 13 28 22 4 27 9 27 21 27 8 28 22 18 1 4 28   18 26 5 27 21 5 22 25 3 27 19 27 19 27 18 0 27 18 27 17 27 21 22 18 27   17 27 21 22 18 2 21 27 13 28 22 27 21 27 21 27 22 22 18 1 2 21 27 12   28 22 27 21 27 9 27 22 18 26

     

INT id leftparen INT id rightparen leftbrace IF leftparen id更大   num rightparen RETURN id multiplication id leftparen id minus num   rightparen semicolon ELSE RETURN num semicolon rightbrace VOID id   leftparen VOID rightparen leftbrace INT id逗号id逗号id   分号DOUBLE id分号id assignop id leftparen rightparen   分号id assignop id leftparen rightparen semicolon IF leftparen   id更大的数字右边的身份   rightparen semicolon ELSE IF leftparen id notequal num rightparen id   leftparen id multiplication id rightparen semicolon rightbrace

好的,我已根据用户John的建议编写了一些代码。我仍然对这将如何工作感到困惑。当我迭代第二个循环以找到空格或符号时我怎么知道在符号的ws之前出现了什么类型的标记。我已经尝试将字符串跳过一个字符串并使用case语句来确定它,但我认为它将整个文件写入字符串中,因此我的标记永远不会匹配。方法如何找到评论并安全地忽略它们?

2 个答案:

答案 0 :(得分:0)

有几种不同的方法来处理这个程序。如果不编写代码,我会尝试解释您需要做什么。

从您提交的示例中。

您的导师已经为您提供了该计划的密钥。 他已经给你输出,你可以构建一个状态表。

您可以查看输出并手动执行此操作以检查答案,也可以创建一个小程序来为您执行此操作。

这是一张左边是状态编号的表,右边是相应的字。

         3  int,  
         27 ID,
         21 leftparen, 
         22 right paren,
         25 left brace s, 
         2  if,
         13  greater, 

等等。

您需要创建输入缓冲区
2输出缓冲区
2环一个外环和一个内环
1个对应于状态表的case语句。

当你通过输入缓冲区时,你初始化外部循环 初始化内循环 比较第一个字符并确定它是否是有效字符? 如果没有增加循环,直到找到有效的字符

找到有效字符后,它就是令牌的开头。 然后通过查找空格或特殊符号来增加内部循环来查找标记的结尾。 然后使用case语句在一个缓冲区中输出数字,并输出与第二个缓冲区对应的单词。

然后打印出数字缓冲区。 然后打印出单词缓冲区。

然后将外循环增加到内循环+ 1 使内循环等于外循环

继续,直到找到文件结尾。如果他们符合您的教师输出,那么您就完蛋了如果不是,您有逻辑错误。然后检查哪个值无效,并查看该程序的那一部分。

已经20岁了。

答案 1 :(得分:0)

非常熟悉的尝试,除了我正在编写LLK分析器...在你的情况下,试着看看formal grammars的方式并且喜欢 - 你的步骤几乎是执行analisys之前的步骤那些语法。也许一些工作解析器(开源)像lex&amp;&amp; flex会有所帮助。

INHO,最简单的方法是逐字符地读取输入文件到一些字符串并检查,这个字符串是否匹配你的一个正则表达式...如果确实如此 - 将相应的代码写入输出并清除字符串你就是用作缓冲区。在这种情况下有两个问题:这在O(n * m)中有效,其中n是你的文本长度,m是你有正则表达式的数量(在值得的情况下),第二 - 你不能使用前缀表达式...我认为你不能有任何表达式让另一个表达式作为前缀(开头),否则这个表达式将无法访问。

相关问题