/* Generated By:JavaCC: Do not edit this line. ArchiveParser.java */
package org.apache.commons.jrcs.rcs;

import java.util.Map;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.Reader;

/**
 * Parses an RCS/CVS style version control archive into an Archive.
 * This class is NOT thread safe.
 * 
 * @author <a href="mailto:juanco@suigeneris.org">Juanco Anez</a>
 * @version $Revision: 1.4 $ $Date: 2003/05/06 14:50:52 $
 * @see Archive
 */
class ArchiveParser implements ArchiveParserConstants {
  public ArchiveParser(InputStream in) {
    this(new FastCharStream(in));
  }

  static final String ident = "RCS ArchiveParser Parser $version$:";

  public static void main(String args[]) {
    ArchiveParser parser;
    if (args.length == 0)
    {
      System.out.println(ident + "  Reading from standard input . . .");
      parser = new ArchiveParser(System.in);
    }
    else if (args.length == 1)
    {
      System.out.println(ident + "  Reading from file " + args[0] + " . . .");
      try
      {
        parser = new ArchiveParser(new FileInputStream(args[0]));
      }
      catch (java.io.FileNotFoundException e)
      {
        System.out.println(ident + "  File " + args[0] + " not found.");
        return;
      }
    }
    else
    {
      System.out.println(ident+"  Usage is one of:");
      System.out.println("         java ArchiveParser < inputfile");
      System.out.println("OR");
      System.out.println("         java ArchiveParser inputfile");
      return;
    }
    parser.parse();
  }

  public static void load(Archive arc, InputStream input) throws ParseException
  {
      ArchiveParser parser = new ArchiveParser(input);
      parser.archive(arc);
  }

  public static void load(Archive arc, String fname) throws FileNotFoundException, ParseException
  {
    load(arc, new FileInputStream(fname) );
  }

  public void parse()
  {
    try
    {
      archive(null);
      System.out.println("RCS ArchiveParser Parser version 1.1:  RCS ArchiveParser parsed successfully.");
    }
    catch (ParseException e)
    {
      System.out.println("RCS ArchiveParser Parser version 1.1:  Encountered errors during parse.");
    }
  }

/**
* PARSER STARTS HERE
*/
  final public void archive(Archive arc) throws ParseException {
    admin(arc);
    label_1:
    while (true) {
      switch (jj_nt.kind) {
      case NUM:
        ;
        break;
      default:
        break label_1;
      }
      delta(arc);
    }
    desc(arc);
    label_2:
    while (true) {
      switch (jj_nt.kind) {
      case NUM:
        ;
        break;
      default:
        break label_2;
      }
      text(arc);
    }
    jj_consume_token(0);
  }

  final public void admin(Archive arc) throws ParseException {
    head(arc);
    switch (jj_nt.kind) {
    case BRANCH:
      branch(arc);
      break;
    default:
      ;
    }
    access(arc);
    symbols(arc);
    locks(arc);
    optionals(arc);
  }

  final public void optionals(Archive arc) throws ParseException {
    label_3:
    while (true) {
      switch (jj_nt.kind) {
      case COMMENT:
      case EXPAND:
      case ID:
        ;
        break;
      default:
        break label_3;
      }
      switch (jj_nt.kind) {
      case COMMENT:
        comment(arc);
        break;
      case EXPAND:
        expand(arc);
        break;
      case ID:
        newPhrase(arc.phrases);
        break;
      default:
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
  }

  final public void newPhrases(Map map) throws ParseException {
    label_4:
    while (true) {
      switch (jj_nt.kind) {
      case ID:
        ;
        break;
      default:
        break label_4;
      }
      newPhrase(map);
    }
  }

  final public void head(Archive arc) throws ParseException {
    Version v;
    jj_consume_token(HEAD);
    switch (jj_nt.kind) {
    case NUM:
      v = version();
                           arc.setHead(v);
      break;
    default:
      ;
    }
    jj_consume_token(28);
  }

  final public void branch(Archive arc) throws ParseException {
  Version v;
    jj_consume_token(BRANCH);
    switch (jj_nt.kind) {
    case NUM:
      v = version();
                             arc.setBranch(v);
      break;
    default:
      ;
    }
    jj_consume_token(28);
  }

  final public void access(Archive arc) throws ParseException {
    String name;
    jj_consume_token(ACCESS);
    label_5:
    while (true) {
      switch (jj_nt.kind) {
      case ID:
        ;
        break;
      default:
        break label_5;
      }
      name = id();
                           arc.addUser(name);
    }
    jj_consume_token(28);
  }

  final public void symbols(Archive arc) throws ParseException {
    String  s;
    Version v;
    jj_consume_token(SYMBOLS);
    label_6:
    while (true) {
      switch (jj_nt.kind) {
      case ID:
      case SYM:
        ;
        break;
      default:
        break label_6;
      }
      s = sym();
      jj_consume_token(29);
      v = version();
                                            arc.addSymbol(s, v);
    }
    jj_consume_token(28);
  }

  final public void locks(Archive arc) throws ParseException {
    String  name;
    Version v;
    jj_consume_token(LOCKS);
    label_7:
    while (true) {
      switch (jj_nt.kind) {
      case ID:
        ;
        break;
      default:
        break label_7;
      }
      name = id();
      jj_consume_token(29);
      v = version();
                                            arc.addLock(name, v);
    }
    jj_consume_token(28);
    switch (jj_nt.kind) {
    case STRICT:
      jj_consume_token(STRICT);
      jj_consume_token(28);
               arc.setStrictLocking(true);
      break;
    default:
      ;
    }
  }

  final public void comment(Archive arc) throws ParseException {
  String s;
    jj_consume_token(COMMENT);
    switch (jj_nt.kind) {
    case STRING:
      s = string();
                            arc.setComment(s);
      break;
    default:
      ;
    }
    jj_consume_token(28);
  }

  final public void expand(Archive arc) throws ParseException {
 String s;
    jj_consume_token(EXPAND);
    switch (jj_nt.kind) {
    case STRING:
      s = string();
                           arc.setExpand(s);
      break;
    default:
      ;
    }
    jj_consume_token(28);
  }

  final public void newPhrase(Map map) throws ParseException {
  String key;
  String value;
  StringBuffer values = new StringBuffer();
    key = id();
    label_8:
    while (true) {
      switch (jj_nt.kind) {
      case ID:
      case STRING:
      case NUM:
        ;
        break;
      default:
        break label_8;
      }
      value = word();
                     values.append(" " + value);
    }
    jj_consume_token(28);
    if (map != null) map.put(key, values.toString());
  }

  final public String word() throws ParseException {
  String result, right;
    result = simpleWord();
    switch (jj_nt.kind) {
    case 29:
      right = range();
                                             result = result + right;
      break;
    default:
      ;
    }
    {if (true) return result;}
    throw new Error("Missing return statement in function");
  }

  final public String simpleWord() throws ParseException {
    String  result;
    Version v;
    switch (jj_nt.kind) {
    case ID:
      result = id();
      break;
    case NUM:
      v = version();
                 result = v.toString();
      break;
    case STRING:
      result = string();
      break;
    default:
      jj_consume_token(-1);
      throw new ParseException();
    }
   {if (true) return result;}
    throw new Error("Missing return statement in function");
  }

  final public String range() throws ParseException {
    String rightSide;
    jj_consume_token(29);
    rightSide = simpleWord();
      {if (true) return ":" + rightSide;}
    throw new Error("Missing return statement in function");
  }

  final public void desc(Archive arc) throws ParseException {
  String s;
    jj_consume_token(DESC);
    s = string();
                          arc.setDesc(s);
  }

  final public void delta(Archive arc) throws ParseException {
    Version   v;
    Node      node;
    int[]     d;
    String    s;
    v = version();
       node = arc.newNode(v);
    jj_consume_token(DATE);
    d = date();
                              node.setDate(d);
    jj_consume_token(28);
    jj_consume_token(AUTHOR);
    s = id();
                              node.setAuthor(s);
    jj_consume_token(28);
    jj_consume_token(STATE);
    switch (jj_nt.kind) {
    case ID:
      s = id();
                            node.setState(s);
      break;
    default:
      ;
    }
    jj_consume_token(28);
    jj_consume_token(BRANCHES);
    label_9:
    while (true) {
      switch (jj_nt.kind) {
      case NUM:
        ;
        break;
      default:
        break label_9;
      }
      v = version();
                                 node.addBranch(arc.newBranchNode(v));
    }
    jj_consume_token(28);
    jj_consume_token(NEXT);
    switch (jj_nt.kind) {
    case NUM:
      v = version();
                                 node.setRCSNext(arc.newNode(v));
      break;
    default:
      ;
    }
    jj_consume_token(28);
    newPhrases(node.phrases);
  }

  final public void text(Archive arc) throws ParseException {
  Version v;
  Node node;
  String log;
  String txt;
    v = version();
      node = arc.getNode(v);
    jj_consume_token(LOG);
    log = string();
      node.setLog(log);
    newPhrases(node.phrases);
    jj_consume_token(TEXT);
    txt = string();
       node.setText(txt);
  }

  final public String id() throws ParseException {
                    Token t;
    t = jj_consume_token(ID);
                                             {if (true) return t.image;}
    throw new Error("Missing return statement in function");
  }

  final public String sym() throws ParseException {
  Token t;
    switch (jj_nt.kind) {
    case SYM:
      t = jj_consume_token(SYM);
      break;
    case ID:
      t = jj_consume_token(ID);
      break;
    default:
      jj_consume_token(-1);
      throw new ParseException();
    }
    {if (true) return t.image;}
    throw new Error("Missing return statement in function");
  }

  final public Version version() throws ParseException {
  Version v;
  int   n, r;
    n = num();
    v = new Version(n);
    label_10:
    while (true) {
      switch (jj_nt.kind) {
      case 30:
        ;
        break;
      default:
        break label_10;
      }
      jj_consume_token(30);
      n = num();
                    v.__addBranch(n);
    }
    {if (true) return v;}
    throw new Error("Missing return statement in function");
  }

  final public int[] date() throws ParseException {
  int[] n = new int[6];
    n[0] = num();
    jj_consume_token(30);
    n[1] = num();
    jj_consume_token(30);
    n[2] = num();
    jj_consume_token(30);
    n[3] = num();
    jj_consume_token(30);
    n[4] = num();
    jj_consume_token(30);
    n[5] = num();
   {if (true) return n;}
    throw new Error("Missing return statement in function");
  }

  final public int num() throws ParseException {
              Token t;
    t = jj_consume_token(NUM);
                                      {if (true) return Integer.parseInt(t.image);}
    throw new Error("Missing return statement in function");
  }

  final public String string() throws ParseException {
 Token t;
    t = jj_consume_token(STRING);
                 {if (true) return Archive.unquoteString(t.image);}
    throw new Error("Missing return statement in function");
  }

  public ArchiveParserTokenManager token_source;
  public Token token, jj_nt;

  public ArchiveParser(CharStream stream) {
    token_source = new ArchiveParserTokenManager(stream);
    token = new Token();
    token.next = jj_nt = token_source.getNextToken();
  }

  public void ReInit(CharStream stream) {
    token_source.ReInit(stream);
    token = new Token();
    token.next = jj_nt = token_source.getNextToken();
  }

  public ArchiveParser(ArchiveParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    token.next = jj_nt = token_source.getNextToken();
  }

  public void ReInit(ArchiveParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    token.next = jj_nt = token_source.getNextToken();
  }

  final private Token jj_consume_token(int kind) throws ParseException {
    Token oldToken = token;
    if ((token = jj_nt).next != null) jj_nt = jj_nt.next;
    else jj_nt = jj_nt.next = token_source.getNextToken();
    if (token.kind == kind) {
      return token;
    }
    jj_nt = token;
    token = oldToken;
    throw generateParseException();
  }

  final public Token getNextToken() {
    if ((token = jj_nt).next != null) jj_nt = jj_nt.next;
    else jj_nt = jj_nt.next = token_source.getNextToken();
    return token;
  }

  final public Token getToken(int index) {
    Token t = token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  }

  public ParseException generateParseException() {
    Token errortok = token.next;
    int line = errortok.beginLine, column = errortok.beginColumn;
    String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;
    return new ParseException("Parse error at line " + line + ", column " + column + ".  Encountered: " + mess);
  }

  final public void enable_tracing() {
  }

  final public void disable_tracing() {
  }

}
