3

我必须用 Java 为 BASIC 方言编写 Lexer。
我将所有 TokenType 分组在 Enum

public enum TokenType {
    INT("-?[0-9]+"),
    BOOLEAN("(TRUE|FALSE)"),
    PLUS("\\+"),
    MINUS("\\-"),
    //others.....
    }

该名称是 TokenType 名称,括号中是我用来匹配类型的正则表达式。
如果我想匹配 INT 类型,我使用“-?[0-9]+”。

但现在我有一个问题。我将 TokenType 的所有正则表达式放入 StringBuffer 中:

private String pattern() {
    StringBuffer tokenPatternsBuffer = new StringBuffer();
    for(TokenType token : TokenType.values())
        tokenPatternsBuffer.append("|(?<" + token.name() + ">" + token.getPattern() + ")");

    String tokenPatternsString = tokenPatternsBuffer.toString().substring(1);

    return tokenPatternsString;
    }

所以它返回一个字符串,如:

(?<INT>-?[0-9]+)|(?<BOOLEAN>(TRUE|FALSE))|(?<PLUS>\+)|(?<MINUS>\-)|(?<PRINT>PRINT)....

现在我使用这个字符串来创建一个模式

Pattern pattern = Pattern.compile(STRING);

然后我创建一个匹配器

Matcher match = pattern.match("line of code");

现在我想匹配所有的 TokenType 并将它们分组到 Token 的 ArrayList 中。如果代码语法正确,则返回一个 ArrayList of Token (Token name, value)。
但是如果语法不正确,我不知道如何退出while循环然后打印错误。
这是一段用于创建 Token 的 ArrayList 的代码。

private void lex() {
    ArrayList<Token> tokens = new ArrayList<Token>();
    int tokenSize = TokenType.values().length;
    int counter = 0;

     //Iterate over the arrayLinee (ArrayList of String) to get matches of pattern
     for(String linea : arrayLinee) {
         counter = 0;
         Matcher match = pattern.matcher(linea);

         while(match.find()) {
             System.out.println(match.group(1));
             counter = 0;

             for(TokenType token : TokenType.values()) {
                 counter++;
                 if(match.group(token.name()) != null) {
                     tokens.add(new Token(token , match.group(token.name())));
                     counter = 0;
                     continue;
                 }
             }

             if(counter==tokenSize) {
                 System.out.println("Syntax Error in line : " + linea);
                 break;
             }
         }

         tokenList.add("EOL");
     }
}

如果 for 循环遍历所有 TokenType 并且不匹配 TokenType 的任何正则表达式,则代码不会中断。如果语法不正确,如何返回错误?
或者你知道我在哪里可以找到开发词法分析器的信息吗?

4

4 回答 4

2

您需要做的就是在枚举类型的末尾添加一个额外的“INVALID”令牌,并使用“.+”之类的正则表达式(匹配所有内容)。因为正则表达式是按顺序计算的,所以只有在没有找到其他标记时才会匹配。然后,您检查列表中的最后一个令牌是否是 INVALID 令牌。

于 2014-09-09T23:39:44.030 回答
1

如果您使用 Java,我建议您尝试使用ANTLR 4来创建您的词法分析器。语法语法比正则表达式干净得多,从你的语法生成的词法分析器会自动支持报告语法错误。

于 2013-05-28T12:03:28.440 回答
0

如果您正在编写完整的词法分析器,我建议使用现有的语法构建器。Antlr 是一种解决方案,但我个人推荐使用parboiled,它允许用纯 Java 编写语法。

于 2013-05-28T12:10:52.617 回答
-1

不确定这是否得到了回答,或者您是否得到了答案,但词法分析器分为两个不同的阶段,扫描阶段和解析阶段。您可以将它们组合成一个单通道(正则表达式匹配),但如果您需要做的不仅仅是最基本的字符串翻译,您会发现单通道词法分析器有弱点。

在扫描阶段,您将根据您指定的特定标记将字符序列分开。您应该做的是包含您尝试解析的文本的示例。但是Wiki 有一个很好的例子,一个简单的文本词法分析器,可以将句子转换为标记(例如 str.split(' '))。因此,使用扫描仪,您将通过空格将文本块标记为块(这应该几乎总是第一个操作),然后您将根据其他标记进一步标记,例如您正在尝试的内容匹配。

然后解析/评估阶段将遍历每个令牌,并根据业务逻辑、语法规则等决定如何处理每个令牌,无论您设置什么。这可能是表达某种数学函数来执行(例如 max(3,2)),或者更常见的例子是查询语言构建。您可能会制作一个具有特定查询语言(想到 SOLR,以及任何 SQL/NoSQL DB)的 Web 应用程序,该语言被翻译成另一种语言以对数据源发出请求。词法分析器通常在 IDE 中用于代码提示和自动完成。

这不是基于代码的答案,但它应该让您了解如何解决问题。

于 2014-10-16T03:36:56.897 回答