使用自定义Regex Java拆分字符串



我正在构建编译器。其中一些规格如下:

  • 字符串文字由美元符号(" $"(封闭,例如。$字符串样本$
  • 评论由"*" - 例如。*样本评论 *
  • 评论可以存在于操作之间的任何地方 - 例如。4 *样本评论 * 5-(这是不允许的(

现在,我必须拆分源代码行才能将其引入。示例案例:

PRINT $ THE FLOAT IS $ * DISPLAY THE RESULT *

正如我将其化的那样,它应该产生:

PRINT - token is KEYWORD
THE FLOAT IS - token is STRING_LITERAL
DISPLAY THE RESULT - token is COMMENT 

我想知道获取此问题的最有效方法。请注意,我仍然必须验证字符串文字和评论的情况。(例如,检查是否正确封闭(。到目前为止,我的方式是将每条线划分为白色空间,并且当Lexeme包含" $"或"*"时,我将验证字符串字面的字体。这是我的实现:

private void getLexemes(){
    for(String line : newSourceCode){
        String[] lexemesInALine = line.trim().split("[\s]+");
        for(String lexemeInALine : lexemesInALine){
            if(!(lexemeInALine.contains("$"))){
                lexemes.add(lexemeInALine);
                tempTokens.add(findToken(lexemeInALine));
                line = line.replaceFirst(lexemeInALine,"").trim();
            }else{
                validateStringType(line);
                break;
            }
        }

谢谢您的帮助。

我认为您的语言是确定性和无上下文的?这意味着,您无法使用正则表达式正确解析。

您需要的是在代币流上工作的状态机。Java配备了两个可能对您有用的类:StreamTokenizerStringTokenizer

但是您真正想要的是使用数十个解析器发生器之一。也许像Antlr一样。这里有很多描述:

https://en.wikipedia.org/wiki/comparison_of_parser_generators

如果所有这些失败,那是有限的状态机。沿着这些行

public class Parsy {
    enum State { string, comment, token }
    void parse(StringTokenizer tokenizer) {
        State state = State.token;
        List<String> tokens = new ArrayList<>();
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            // figure out type of token
            if (token.length() == 1) {
                char delim = token.charAt(0);
                switch (delim) {
                    case '$':
                        switch (state) {
                            case token: {
                                // a string literal has started, emit what we have, start a string
                                printOut(tokens, state);
                                tokens.clear();
                                tokens.add(token);
                                state = State.string;
                                break;
                            }
                            case string: { // parsing a string, so this ends it
                                printOut(tokens, state);
                                tokens.clear();
                                state = State.token;
                                break;
                            }
                            case comment: { // $ is ignored since we are in a comment
                                tokens.add(token);
                                break;
                            }
                        }
                        break;
                    // ...
                }
            } else {
                // not a delimiter token
                tokens.add(token);
            }
        } // end of while
    if (state != State.token) {
       System.out.println("Oops! Syntax error. I'm still parsing" + state);
     }
    }
}