带有用Java编写的正则表达式的BASIC Lexer

时间:2013-05-28 11:58:25

标签: java regex token lexer

我必须使用Java编写一个Lexer方言的Lexer代码。
我将Enum中的所有TokenType分组

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

名称是TokenType名称,括号中有我用来匹配Type的正则表达式。
如果我想匹配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 = Pattern.compile(STRING);

然后我创建了一个Matcher

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

现在我想匹配所有TokenType并将它们分组到Token的ArrayList中。如果代码语法正确,则返回Token的ArrayList(令牌名称,值)。
但我不知道如果语法错误然后打印错误,如何退出while循环 这是用于创建令牌的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 个答案:

答案 0 :(得分:1)

如果您使用的是Java,我建议您尝试ANTLR 4来创建词法分析器。语法语法比正则表达式更清晰,从语法生成的词法分析器将自动支持报告语法错误。

答案 1 :(得分:1)

您需要做的就是添加额外的&#34; INVALID&#34;你的枚举类型末尾的标记,带有#34;。+&#34;等正则表达式。 (匹配一切)。由于正则表达式按顺序进行评估,因此只有在找不到其他标记时才会匹配。然后,检查列表中的最后一个令牌是否为INVALID令牌。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

不确定这是否得到了回答,或者您得到了答案,但词法分析器分为两个不同的阶段,即扫描阶段和解析阶段。您可以将它们组合成一个单一的传递(正则表达式匹配),但是如果您需要执行除最基本的字符串翻译之外的任何操作,您将发现单个传递词法分析器存在缺陷。

在扫描阶段,您可以根据您指定的特定令牌将字符序列分开。您应该做的是包含您尝试解析的文本的示例。但Wiki has a great example简单的文本词法分析器将句子变为标记(例如str.split(&#39;&#39;))。因此,使用扫描仪,您将通过空格将文本块标记为块(这应该是几乎总是第一个动作),然后您将基于其他标记进一步进行标记化,例如什么你试图匹配。

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

这不是一个基于代码的答案,但它的答案可以让您了解如何解决问题。