How to use a stack to parse a string
Asked Answered
F

2

7

I have a String:

String stringContent="{\\*\\listtable{\\list{\\listlevel{\\leveltext}{\\levelNumber}}}}"

How do I select values of all enclosing braces one by one in each pass like this:

"{\\levelNumber}"
"{\\leveltext}"
"{\\listlevel{\\leveltext}{\\levelNumber}}"
"{\\list{\\listlevel{\\leveltext}}}"
"{\\*\\listtable{\\list{\\listlevel{\\leveltext}}}}"

So far I've done this:

   public class StringExtracter {

public String stringofObject(Section parentSectionObject, String stringContent) {
    Stack stack=new Stack();
    String returnString = "";

    char arr[] = stringContent.toCharArray();


    for(int i=0;i<=arr.length;i++){

      while(arr[i]!='}'){
       if(arr[i]=='{'){
           stringContent=stringContent.substring(i+1);
           returnString=stringContent;
           System.out.println(stringContent);
           braces=true;
           Section sectionObject=new Section(parentSectionObject,stringContent);
          stack.push(arr[i]);


       }           

    }
    return returnString;
}

But the problem is that it is not detecting the right } like this. How should I be doing this?

Output as of now:

\*\listtable{\list{\listlevel{\leveltext}{\fefw}}}}
\list{\listlevel{\leveltext}{\fefw}}}}
\listlevel{\leveltext}{\fefw}}}}
\leveltext}{\fefw}}}}
\fefw}}}}
Fairish answered 8/8, 2015 at 10:27 Comment(3)
I am not sure what you are trying to do. What is Section parentSectionObject? Do you want to create tree or simply print all {..} elements?Naturism
@Naturism Thats observant of you. Yes I am creating a tree structure for all the strings I am extracting.Fairish
"{\\*\\listtable{\\list{\\listlevel{\\leveltext}}}}" is actually the root node. and the lists follow and then the listLevelFairish
S
2

Stack-based solution (problably could be simpler, but let's solve the problem first):

public class Main {

    public static class Node {
        public int level;
        public String content = "";
        public List<Node> children = new ArrayList<>();
    }

    public static void main(String[] args) {

        String input="{\\\\*\\\\listtable{\\\\list{\\\\listlevel{\\\\leveltext}{\\\\levelNumber}}}}";

        Node root = null;
        Stack<Node> stack = new Stack<>();

        for(char c: input.toCharArray()) {
            if (c == '{') {
                Node n = new Node();
                n.level = stack.size() + 1;
                n.content += c;
                stack.push(n);
                if (root == null) root = n;
            } else if (c == '}') {
                Node n = stack.pop();
                n.content += c;
                if (!stack.isEmpty()) {
                    stack.peek().children.add(n);
                }
            } else {
                stack.peek().content += c;
            }
        }

        TreeTraverser<Node> treeTraverser = new TreeTraverser<Node>() {
            @Override
            public Iterable<Node> children(Node root) {
                return root.children;
            }
        };

        for(Node node : treeTraverser.preOrderTraversal(root)) {
            String indent = String.format("%" + node.level + "s", " ");
            System.out.println(indent + node.content);
        }
    }
}

Note: Google's Guava library is needed for the TreeTraverser

Output:

 {\\*\\listtable}
  {\\list}
   {\\listlevel}
    {\\leveltext}
    {\\levelNumber}

Edit 1: modified to create a tree after additional input from the OP

Edit 2: modified to treat the siblings correctly

Spandau answered 8/8, 2015 at 11:15 Comment(4)
I've updated the code based on your last input, now the strings are stored in a tree.Spandau
I didn't put the siblings in the input string last time @mzc. It doesn't work with siblings in certain cases. See the input as String stringContent="{\\*\\listtable{\\list{\\listlevel{\\leveltext}{\\levelNumber}}}}" where leveltext and levelNumbers are siblingsFairish
Try it out, it should be fixedSpandau
Storing the objects in the stack was a good idea! This works!Fairish
N
0

I recommend you to, instead of using a for loop, create a variable called i and increase it in the while loop. You're checking for "arr[i]!='}'" in the while loop, but as it's inside the for loop, i never increases, and therefore it's always checking the same character.

Negris answered 8/8, 2015 at 10:34 Comment(2)
I'm recursively trying to drill down the text using substring. But I get the following above as of now *modifiedFairish
Try this: pastebin.com/r6uRgnB4. It outputs '{\leveltext} {\listlevel{\leveltext}} {\list{\listlevel{\leveltext}}} {*\listtable{\list{\listlevel{\leveltext}}}}' for me.Negris

© 2022 - 2024 — McMap. All rights reserved.