Java 用一些规则替换嵌套字符串

Java 用一些规则替换嵌套字符串,java,parsing,syntax,nested,stack,Java,Parsing,Syntax,Nested,Stack,字符串中有3条规则: 它包含单词或组(用括号括起来),组可以嵌套 如果单词或组之间有空格,则这些单词或组应附加“+” 例如: "a b" needs to be "+a +b" "a (b c)" needs to be "+a +(+b +c)" "aa|bb|(cc|(ff gg)) hh" needs to be "+(aa bb (cc (+ff +gg))) +hh" 如果单词或组之间有一个|,则这些单词或组应该用括号括起来。 例如: 考虑所有规则,下面是另一个示例: "a b"

字符串中有3条规则:

  • 它包含单词或组(用括号括起来),组可以嵌套

  • 如果单词或组之间有空格,则这些单词或组应附加“+”

  • 例如:

    "a b" needs to be "+a +b"
    "a (b c)" needs to be "+a +(+b +c)"
    
    "aa|bb|(cc|(ff gg)) hh" needs to be "+(aa bb (cc (+ff +gg))) +hh"
    
  • 如果单词或组之间有一个
    |
    ,则这些单词或组应该用括号括起来。 例如:
  • 考虑所有规则,下面是另一个示例:

    "a b" needs to be "+a +b"
    "a (b c)" needs to be "+a +(+b +c)"
    
    "aa|bb|(cc|(ff gg)) hh" needs to be "+(aa bb (cc (+ff +gg))) +hh"
    
    我曾尝试使用regex、stack和,但仍然无法完全解决这个问题

    任何人都可以分享这个问题的逻辑或伪代码吗

    新编辑: 还有一条更重要的规则:竖条具有更高的优先级

    例如:

    aa | bb hh cc | dd(a | b)
    需要是
    +(aa bb)+hh+(cc dd)+(a b))

    (aa-dd)| bb | cc(ee-ff)|(gg-hh)
    需要是
    +(+aa+dd)bb-cc+(+ee+ff)(+gg+hh))

    新编辑: 为了解决优先级问题,我找到了一种在调用Sunil Dabburi的方法之前添加括号的方法

    例如:

    aa | bb hh cc | dd(a | b)
    将是
    (aa | bb)hh(cc | dd)(a | b)

    (aa-dd)| bb | cc(ee-ff)|(gg-hh)
    将是
    ((aa-dd)| bb | cc)((ee-ff)|(gg-hh))


    因为性能对我的应用程序来说不是一个大问题,所以这种方式至少可以让它对我起作用。我想JavaCC工具可以很好地解决这个问题。希望其他人能继续讨论并提出这个问题。

    我试图解决这个问题。不确定它是否在所有情况下都有效。通过问题中给出的输入进行验证,结果良好

  • 我们需要先格式化管道。这将有助于添加必要的括号和间距
  • 作为管道处理的一部分生成的空间可能会干扰表达式中可用的实际空间。所以使用$symbol来掩盖它们
  • 要处理空间,它很棘手,因为偏执需要单独处理。所以我遵循的方法是找到一组从外部开始到内部的妄想
  • 所以通常我们有
    。现在
    左侧部分
    可以为空,类似的
    右侧部分
    可以为空。我们需要处理这些案件。 此外,如果
    右侧部分
    以空格开头,我们需要根据空格要求向
    左侧部分
    添加“+”

    注意:我不确定对
    (a | b)
    的期望是什么。如果结果应该是
    ((a b))
    (a b)
    。我将纯粹根据它的定义来使用
    ((a b))

    下面是工作代码:

    public class Test {
    
        public static void main(String[] args) {
            String input = "aa|bb hh cc|dd (a|b)";
            String result = formatSpaces(formatPipes(input)).replaceAll("\\$", " ");
            System.out.println(result);
        }
    
        private static String formatPipes(String input) {
    
            while (true) {
                char[] chars = input.toCharArray();
                int pIndex = input.indexOf("|");
    
                if (pIndex == -1) {
                    return input;
                }
    
                input = input.substring(0, pIndex) + '$' + input.substring(pIndex + 1);
    
                int first = pIndex - 1;
                int closeParenthesesCount = 0;
                while (first >= 0) {
    
                    if (chars[first] == ')') {
                        closeParenthesesCount++;
                    }
    
                    if (chars[first] == '(') {
                        if (closeParenthesesCount > 0) {
                            closeParenthesesCount--;
                        }
                    }
    
                    if (chars[first] == ' ') {
                        if (closeParenthesesCount == 0) {
                            break;
                        }
                    }
                    first--;
                }
    
                String result;
    
                if (first > 0) {
                    result = input.substring(0, first + 1) + "(";
                } else {
                    result = "(";
                }
    
                int last = pIndex + 1;
                int openParenthesesCount = 0;
                while (last <= input.length() - 1) {
    
                    if (chars[last] == '(') {
                        openParenthesesCount++;
                    }
    
                    if (chars[last] == ')') {
                        if (openParenthesesCount > 0) {
                            openParenthesesCount--;
                        }
                    }
    
                    if (chars[last] == ' ') {
                        if (openParenthesesCount == 0) {
                            break;
                        }
                    }
                    last++;
                }
    
                if (last >= input.length() - 1) {
                    result = result + input.substring(first + 1) + ")";
                } else {
                    result = result + input.substring(first + 1, last) + ")" + input.substring(last);
                }
    
                input = result;
            }
        }
    
        private static String formatSpaces(String input) {
    
            if (input.isEmpty()) {
                return "";
            }
    
            int startIndex = input.indexOf("(");
            if (startIndex == -1) {
                if (input.contains(" ")) {
                    String result = input.replaceAll(" ", " +");
                    if (!result.trim().startsWith("+")) {
                        result = '+' + result;
                    }
                    return result;
                } else {
                    return input;
                }
            }
    
            int endIndex = startIndex + matchingCloseParenthesesIndex(input.substring(startIndex));
    
            if (endIndex == -1) {
                System.out.println("Invalid input!!!");
                return "";
            }
    
            String first = "";
            String last = "";
            if (startIndex > 0) {
                first = input.substring(0, startIndex);
            }
            if (endIndex < input.length() - 1) {
                last = input.substring(endIndex + 1);
            }
    
            String result = formatSpaces(first);
            String parenthesesStr = input.substring(startIndex + 1, endIndex);
            if (last.startsWith(" ") && first.isEmpty()) {
                result = result + "+";
            }
    
            result = result + "("
                    + formatSpaces(parenthesesStr)
                    + ")"
                    + formatSpaces(last);
    
            return result;
        }
    
        private static int matchingCloseParenthesesIndex(String input) {
            int counter = 1;
            char[] chars = input.toCharArray();
            for (int i = 1; i < chars.length; i++) {
                char ch = chars[i];
                if (ch == '(') {
                    counter++;
                } else if (ch == ')') {
                    counter--;
                }
    
                if (counter == 0) {
                    return i;
                }
            }
            return -1;
        }
    
    }
    
    公共类测试{
    公共静态void main(字符串[]args){
    字符串输入=“aa | bb hh cc | dd(a | b)”;
    字符串结果=formatSpaces(formatPipes(输入)).replaceAll(“\\$”,”);
    系统输出打印项次(结果);
    }
    专用静态字符串格式管道(字符串输入){
    while(true){
    char[]chars=input.toCharArray();
    int pIndex=input.indexOf(“|”);
    如果(pIndex==-1){
    返回输入;
    }
    input=input.substring(0,pIndex)+“$”+input.substring(pIndex+1);
    int first=pIndex-1;
    int close括号计数=0;
    而(第一个>=0){
    如果(字符[第一个]==')'){
    闭括号计数++;
    }
    如果(字符[第一个]=='('){
    如果(闭括号计数>0){
    闭括号计数--;
    }
    }
    如果(字符[第一个]=''){
    如果(闭括号计数==0){
    打破
    }
    }
    第一--;
    }
    字符串结果;
    如果(第一个>0){
    结果=输入。子字符串(0,第一个+1)+“(”;
    }否则{
    result=“(”;
    }
    int last=pIndex+1;
    int open圆括号计数=0;
    while(最后0){
    开括号计数--;
    }
    }
    如果(字符[最后]=''){
    if(open圆括号计数==0){
    打破
    }
    }
    last++;
    }
    if(last>=input.length()-1){
    结果=结果+输入。子字符串(第一个+1)+“”;
    }否则{
    结果=结果+输入.子字符串(第一个+1,最后一个)+““””+输入.子字符串(最后一个);
    }
    输入=结果;
    }
    }
    专用静态字符串格式空间(字符串输入){
    if(input.isEmpty()){
    返回“”;
    }
    int startIndex=input.indexOf(“”);
    如果(startIndex==-1){
    if(input.contains(“”){
    字符串结果=input.replaceAll(“,”+”);
    如果(!result.trim().startsWith(“+”)){
    结果=“+”+结果;
    }
    返回结果;
    }否则{
    返回输入;
    }
    }
    int-endIndex=startIndex+matchingclose括号索引(input.substring(startIndex));
    如果(endIndex=-1){
    System.out.println(“无效输入!!!”;
    返回“”;
    }
    字符串优先=”;
    字符串last=“”;
    如果(起始索引>0){
    第一个=输入子字符串(0,startIndex);
    }
    if(endIndex@ParameterizedTest
        @CsvSource({
                "a b,+a +b",
                "a (b c),+a +(+b +c)",
                "a|b,(a b)",
                "a|b|c,(a b c)",
                "aa|bb|(cc|(ff gg)) hh,+(aa bb (cc (+ff +gg))) +hh",
                "(aa(bb(cc|ee)|ff) gg),(+aa(bb(cc ee) ff) +gg)",
                "(a b),(+a +b)",
                "(a(c|d) b),(+a(c d) +b)",
                "bb(cc|ee),bb(cc ee)",
                "((a|b) (a b)|b (c|d)|e),(+(a b) +((+a +b) b) +((c d) e))"
        })
        void testTransformString(String input, String output) {
            Assertions.assertEquals(output, transformString(input));
        }
    
        @ParameterizedTest
        @CsvSource({
                "a b,+a +b",
                "a b c,+a +b +c",
                "a|b,(a b)",
                "(a b),(+a +b)",
                "(a|b),(a b)",
                "a|b|c,(a b c)",
                "(aa|bb cc|dd),(+(aa bb) +(cc dd))",
                "(aa|bb|ee cc|dd),(+(aa bb ee) +(cc dd))",
                "aa|bb|cc|ff gg hh,+(aa bb cc ff) +gg +hh"
        })
        void testTransformBasic(String input, String output) {
            Assertions.assertEquals(output, transformBasic(input));
        }