public void run() {
   mainloop:
   while (true) {
     TokenWithTerminal<?> remove;
     synchronized (terminalAndInfos) {
       while (terminalAndInfos.size() == 0) {
         if (endOfToken) {
           break mainloop;
         }
         try {
           terminalAndInfos.wait();
         } catch (InterruptedException e) {
           // if interrupted, stop to work but the work is not ended (another thread may continue)
           return;
         }
       }
       remove = terminalAndInfos.remove(0);
     }
     try {
       remove.send(grammarParser);
     } catch (GrammarParserException e) {
       grammarParserException = e;
       workEnded = true;
       return;
     }
   }
   try {
     grammarParser.endOfInput();
     workEnded = true;
   } catch (GrammarParserException e) {
     grammarParserException = e;
     workEnded = true;
   }
 }
 public void receiveToken(final TokenWithTerminal<?> token) throws TokenMatchedException {
   synchronized (terminalAndInfos) {
     terminalAndInfos.add(token.copy());
     terminalAndInfos.notify();
   }
 }