JustJinnyThings
JustJinnyThings

Reputation: 37

Java String index out of range '}' token not inluded/printing properly

I currently have this bit of code, which works except for the '}' token. If i enter something like

WOrd 023 {dOor "knob!"}

The output is

`WOrd 023 {dOor "knob!"}
WOrd
word
main.WordToken@33909752
023
23
main.NumberToken@55f96302
{
main.StartToken@3d4eac69
dOor
door
main.WordToken@42a57993
knob!
main.QuoteToken@75b84c92
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at main.ScannerBean.scan(ScannerBean.java:85)
at main.Assignment3.main(Assignment3.java:11)`

I'm pretty sure there is something wrong with the startIndex or endIndex, but so far I have made few improvements. With other inputs, the error does not show up, but the '}' still does not print as it should. I also noticed that the '-' and '+' tokens are also not printing. Original:

package main;
public class ScannerBean implements TokenInterface, ScannerBeanInterface{
String Input;
public ScannerBean(String Input){
    this.Input = Input;
}
public String getInput(){
    return Input;
}
public void setInput(String Input){
    this.Input = Input;
}
public void scan() {
      int startIndex = 0;
      int stopIndex = 0;
      String mySubstring = "";
      boolean isQuote = false;
      while (++stopIndex < Input.length()) {
       if (startIndex >= Input.length()) {
        break;
       }
       if (Input.charAt(startIndex) == '"' || isQuote) {

        isQuote = true;

        if (stopIndex + 1 < Input.length() && Input.charAt(stopIndex + 1) == '"') {


         mySubstring = Input.substring(startIndex+1, stopIndex+1);
         isQuote = false;
         startIndex = stopIndex + 2;
         TokenInterface tt=new QuoteToken(mySubstring);
            System.out.println(tt.getInput());

            TokenInterface quoteToken = new QuoteToken(mySubstring);
            System.out.println(quoteToken.toString());
        }
       }
        else if (Character.isLetter(Input.charAt(startIndex))){
            if (!Character.isLetter(Input.charAt(stopIndex)) || Input.charAt(stopIndex) == '}'){
                mySubstring = Input.substring(startIndex, stopIndex);
                startIndex = stopIndex + 1;

                TokenInterface tt=new WordToken(mySubstring);
                System.out.println(tt.getInput());

                WordTokenInterface w = new WordToken(mySubstring);
                System.out.println(w.getValue());

                System.out.println(w.toString());

            }
        }
        else if (Character.isDigit(Input.charAt(startIndex))){
            if(!Character.isDigit(Input.charAt(stopIndex))){
                mySubstring = Input.substring(startIndex, stopIndex);
                startIndex = stopIndex + 1;

                TokenInterface tt=new NumberToken(mySubstring);
                System.out.println(tt.getInput());

                NumberTokenInterface n = new NumberToken(mySubstring);
                System.out.println(n.getValue());

                System.out.println(n.toString());

            }
        }
        else if (Input.charAt(startIndex) == '{'){
            if(Input.charAt(stopIndex) != '{') {
                mySubstring = Input.substring(startIndex, stopIndex);
                startIndex = stopIndex;

                TokenInterface tt=new StartToken(mySubstring);
                System.out.println(tt.getInput());

                TokenInterface startToken = new StartToken(mySubstring);
                System.out.println(startToken.toString());
            }
        }
        else if (Input.charAt(startIndex) == '}'){
            if(Input.charAt(stopIndex) != '}') {
                mySubstring = Input.substring(startIndex, stopIndex);
                startIndex = stopIndex;

                TokenInterface tt=new EndToken(mySubstring);
                System.out.println(tt.getInput());

                TokenInterface endToken = new EndToken(mySubstring);
                System.out.println(endToken.toString());
            }
        }
        else if (Input.charAt(startIndex) == '-'){
            if(Input.charAt(startIndex) != '-' ){
                mySubstring = Input.substring(startIndex, startIndex+1);
                startIndex = stopIndex;

                TokenInterface tt=new MinusToken(mySubstring);
                System.out.println(tt.getInput());

                TokenInterface minusToken = new MinusToken(mySubstring);
                System.out.println(minusToken.toString());
            }
        }
        else if (Input.charAt(startIndex) == '+'){
            if(Input.charAt(startIndex) != '+' ){
                mySubstring = Input.substring(startIndex,stopIndex);
                startIndex = stopIndex + 1;

                TokenInterface tt=new PlusToken(mySubstring);
                System.out.println(tt.getInput());

                TokenInterface plusToken = new PlusToken(mySubstring);
                System.out.println(plusToken.toString());
            }
        }
        else if (Input.charAt(stopIndex) == ' '){
            startIndex++;
        }
}
}
}

Upvotes: 0

Views: 128

Answers (1)

Cinnam
Cinnam

Reputation: 1922

When you get the substring here

 else if (Input.charAt(startIndex) == '}'){
        if(Input.charAt(stopIndex) != '}') {
            mySubstring = Input.substring(startIndex, stopIndex);

startIndex is greater than stopIndex. I'd suggest rewriting the whole thing using java.util.Scanner, unless there's some good reason you can't or don't want to.

You can use its findWithinHorizon(Pattern, int) method to do most of the work for you, provided you give it correct Patterns. Be careful when using the next...() methods though - they always take a complete token (separated by delimiters on both sides), which is not what you want unless you change the delimiter.

Here's a simple example on how to work with it:

static final Pattern WORD = Pattern.compile("\\G[a-zA-Z]+");
static final Pattern NUMBER = Pattern.compile("\\G\\d+");
static final Pattern LEFT = Pattern.compile("\\G\\{");
static final Pattern RIGHT = Pattern.compile("\\G\\}");
static final Pattern QUOTES = Pattern.compile("\\G\"");
static final Pattern QUOTED_CHARS = Pattern.compile("\\G[^\"]*");
static final Pattern WHITESPACE = Pattern.compile("\\G\\s*");

public static void main(String[] args) {

    String s = "WOrd 023 \"\"{dOor \"knob!\"}";
    Scanner sc = new Scanner(s);

    while (true) {

        sc.skip(WHITESPACE);
        if (!sc.hasNext()) {
            break;
        }

        String token;

        if ((token = sc.findWithinHorizon(WORD, 0)) != null) {
            System.out.println("word: " + token);
        } else if ((token = sc.findWithinHorizon(NUMBER, 0)) != null) {
            System.out.println("number: " + token);
        } else if ((token = sc.findWithinHorizon(LEFT, 0)) != null) {
            System.out.println("left: " + token);
        } else if ((token = sc.findWithinHorizon(RIGHT, 0)) != null) {
            System.out.println("right: " + token);
        } else if ((token = sc.findWithinHorizon(QUOTES, 0)) != null) {
            token = sc.findWithinHorizon(QUOTED_CHARS, 0);
            System.out.println("quoted: '" + token + "'");
            sc.findWithinHorizon(QUOTES, 0);
        }
    }
}

For details take a look here:

http://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html

http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html

Upvotes: 1

Related Questions