home *** CD-ROM | disk | FTP | other *** search
/ Online Today 2000 January / Onto0100.iso / pc / JAVA / MSJAVX86.EXE / xmldso.cab / XML4IE3.cab / com / ms / xml / parser / ContentModel.class (.txt) < prev    next >
Encoding:
Java Class File  |  1997-10-10  |  6.3 KB  |  361 lines

  1. package com.ms.xml.parser;
  2.  
  3. import com.ms.xml.om.Element;
  4. import com.ms.xml.util.Name;
  5. import com.ms.xml.util.XMLOutputStream;
  6. import java.io.IOException;
  7. import java.util.BitSet;
  8. import java.util.Enumeration;
  9. import java.util.Hashtable;
  10. import java.util.Vector;
  11.  
  12. public class ContentModel {
  13.    Node content;
  14.    Terminal end;
  15.    Vector terminalnodes;
  16.    Hashtable symboltable;
  17.    Vector symbols;
  18.    Vector Dtrans;
  19.    static final byte EMPTY = 1;
  20.    static final byte ANY = 2;
  21.    static final byte ELEMENTS = 4;
  22.    byte type;
  23.  
  24.    final Node parseList(Parser var1) throws ParseException {
  25.       Hashtable var2 = new Hashtable();
  26.       var2.put(var1.name, var1.name);
  27.       Object var3 = this.parseNode(var1);
  28.       int var4 = var1.token;
  29.       switch (var1.token) {
  30.          case 41:
  31.             return (Node)var3;
  32.          case 44:
  33.             var1.nextToken();
  34.             var3 = new Sequence((Node)var3, this.parseNode(var1));
  35.             break;
  36.          case 124:
  37.             var1.nextToken();
  38.             if (var1.token == -4) {
  39.                if (var2.contains(var1.name)) {
  40.                   var1.error("Warning: Repeated element in content model: " + var1.name);
  41.                } else {
  42.                   var2.put(var1.name, var1.name);
  43.                }
  44.             }
  45.  
  46.             var3 = new Choice((Node)var3, this.parseNode(var1));
  47.             break;
  48.          default:
  49.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  50.       }
  51.  
  52.       while(var1.token != 41) {
  53.          if (var4 == 44 && var1.token == 44) {
  54.             var1.nextToken();
  55.             var3 = new Sequence((Node)var3, this.parseNode(var1));
  56.          } else if (var4 == 124 && var1.token == 124) {
  57.             var1.nextToken();
  58.             if (var1.token == -4) {
  59.                if (var2.contains(var1.name)) {
  60.                   var1.error("Repeated element in content model: " + var1.name);
  61.                } else {
  62.                   var2.put(var1.name, var1.name);
  63.                }
  64.             }
  65.  
  66.             var3 = new Choice((Node)var3, this.parseNode(var1));
  67.          } else {
  68.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  69.          }
  70.       }
  71.  
  72.       return (Node)var3;
  73.    }
  74.  
  75.    public String toString() {
  76.       String var1;
  77.       switch (this.type) {
  78.          case 1:
  79.             var1 = "EMPTY";
  80.             break;
  81.          case 2:
  82.             var1 = "ANY";
  83.             break;
  84.          case 3:
  85.          default:
  86.             var1 = "*UNKNOWN*";
  87.             break;
  88.          case 4:
  89.             var1 = "ELEMENTS";
  90.       }
  91.  
  92.       return "Content: type=" + var1;
  93.    }
  94.  
  95.    final boolean checkContent(Context var1, Element var2, Parser var3) throws ParseException {
  96.       if (this.type == 2) {
  97.          var1.matched = true;
  98.          return true;
  99.       } else {
  100.          Name var4 = var2.getTagName();
  101.          if (var4 == null && var2.getType() == 1) {
  102.             var4 = Parser.namePCDATA;
  103.          }
  104.  
  105.          if (var4 != null) {
  106.             Integer var5 = (Integer)this.symboltable.get(var4);
  107.             if (var5 != null) {
  108.                int var6 = var5;
  109.                int var7 = ((int[])this.Dtrans.elementAt(var1.state))[var6];
  110.                if (var7 == -1) {
  111.                   var3.error("Pattern mismatch in '" + var4 + "'. Expected " + this.expectedElements(var1.state));
  112.                } else {
  113.                   var1.state = var7;
  114.                   var1.matched = ((int[])this.Dtrans.elementAt(var1.state))[this.symbols.size()] > 0;
  115.                }
  116.  
  117.                return true;
  118.             }
  119.  
  120.             var3.error("Unknown element '" + var4 + "' in content of '" + var1.ed.name + "'");
  121.          } else {
  122.             var3.error("Invalid element in content of '" + var1.ed.name + "'");
  123.          }
  124.  
  125.          return false;
  126.       }
  127.    }
  128.  
  129.    final Node parseMixed(Parser var1) throws ParseException {
  130.       Hashtable var3 = new Hashtable();
  131.       var1.parseKeyword(-18, "PCDATA");
  132.       Object var2 = new Terminal(this, var1.name);
  133.       var3.put(var1.name, var1.name);
  134.       var1.nextToken();
  135.       switch (var1.token) {
  136.          case 41:
  137.             var2 = new Closure((Node)var2);
  138.             if (var1.lookahead == 42) {
  139.                var1.nextToken();
  140.             }
  141.             break;
  142.          case 124:
  143.             for(; var1.token == 124; var2 = new Choice((Node)var2, this.parseNode(var1))) {
  144.                var1.nextToken();
  145.                if (var1.token == -4) {
  146.                   if (var3.contains(var1.name)) {
  147.                      var1.error("Repeated element in content model: " + var1.name);
  148.                   } else {
  149.                      var3.put(var1.name, var1.name);
  150.                   }
  151.                }
  152.             }
  153.  
  154.             if (var1.token == 41) {
  155.                if (var1.lookahead == 42) {
  156.                   var1.nextToken();
  157.                   var2 = new Closure((Node)var2);
  158.                } else {
  159.                   var1.error("Expected '*' instead of: " + var1.tokenString(var1.token));
  160.                }
  161.             } else {
  162.                var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  163.             }
  164.             break;
  165.          default:
  166.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  167.       }
  168.  
  169.       var1.nextToken();
  170.       return (Node)var2;
  171.    }
  172.  
  173.    final Node finishNode(Parser var1, Node var2) throws ParseException {
  174.       Object var3;
  175.       switch (var1.lookahead) {
  176.          case 42:
  177.             var1.nextToken();
  178.             var3 = new Closure(var2);
  179.             break;
  180.          case 43:
  181.             var1.nextToken();
  182.             var3 = new ClosurePlus(var2);
  183.             break;
  184.          case 63:
  185.             var1.nextToken();
  186.             var3 = new Qmark(var2);
  187.             break;
  188.          default:
  189.             var3 = var2;
  190.       }
  191.  
  192.       var1.nextToken();
  193.       return (Node)var3;
  194.    }
  195.  
  196.    public void save(Name var1, XMLOutputStream var2) throws IOException {
  197.       switch (this.type) {
  198.          case 1:
  199.             var2.writeChars("EMPTY");
  200.             return;
  201.          case 2:
  202.             var2.writeChars("ANY");
  203.             return;
  204.          case 4:
  205.             if (this.content != null) {
  206.                ((Sequence)this.content).left.save(var2, 35, 0, var1);
  207.                return;
  208.             }
  209.          case 3:
  210.          default:
  211.       }
  212.    }
  213.  
  214.    final boolean acceptEmpty() {
  215.       if (this.type != 2 && this.type != 1) {
  216.          Node var1 = ((Sequence)this.content).left;
  217.          return var1 instanceof Qmark || var1 instanceof Closure;
  218.       } else {
  219.          return true;
  220.       }
  221.    }
  222.  
  223.    final Vector expectedElements(int var1) {
  224.       int[] var2 = (int[])this.Dtrans.elementAt(var1);
  225.       Vector var3 = new Vector();
  226.       Enumeration var4 = this.terminalnodes.elements();
  227.  
  228.       while(var4.hasMoreElements()) {
  229.          Name var5 = ((Terminal)var4.nextElement()).name;
  230.          if (var5 != null && !var3.contains(var5)) {
  231.             Integer var6 = (Integer)this.symboltable.get(var5);
  232.             if (var6 != null && var2[var6] != -1) {
  233.                var3.addElement(var5);
  234.             }
  235.          }
  236.       }
  237.  
  238.       return var3;
  239.    }
  240.  
  241.    final void initContent(Context var1, Parser var2) throws ParseException {
  242.       var1.state = 0;
  243.       if (this.Dtrans != null && this.Dtrans.size() > 0) {
  244.          var1.matched = ((int[])this.Dtrans.elementAt(var1.state))[this.symbols.size()] > 0;
  245.       } else {
  246.          var1.matched = true;
  247.       }
  248.    }
  249.  
  250.    final void parseModel(Parser var1) throws ParseException {
  251.       this.terminalnodes = new Vector();
  252.       this.symboltable = new Hashtable();
  253.       this.symbols = new Vector();
  254.       this.content = this.parseRootNode(var1);
  255.       this.end = new Terminal(this, (Name)null);
  256.       this.content = new Sequence(this.content, this.end);
  257.       int var2 = this.terminalnodes.size();
  258.       BitSet[] var3 = new BitSet[var2];
  259.  
  260.       for(int var4 = 0; var4 < var2; ++var4) {
  261.          var3[var4] = new BitSet(var2);
  262.       }
  263.  
  264.       this.content.calcfollowpos(var3);
  265.       Vector var17 = new Vector();
  266.       this.Dtrans = new Vector();
  267.       Vector var5 = new Vector();
  268.       Hashtable var6 = new Hashtable();
  269.       BitSet var7 = new BitSet(var2);
  270.       var6.put(var7, new Integer(-1));
  271.       int var8 = 0;
  272.       BitSet var9 = this.content.firstpos(var2);
  273.       var6.put(var9, new Integer(var17.size()));
  274.       var5.addElement(var9);
  275.       var17.addElement(var9);
  276.       int[] var10 = new int[this.symbols.size() + 1];
  277.       this.Dtrans.addElement(var10);
  278.       if (var9.get(this.end.pos)) {
  279.          var10[this.symbols.size()] = 1;
  280.       }
  281.  
  282.       while(var5.size() > 0) {
  283.          int[] var11 = (int[])this.Dtrans.elementAt(var8);
  284.          var9 = (BitSet)var5.elementAt(0);
  285.          var5.removeElementAt(0);
  286.  
  287.          for(int var12 = 0; var12 < this.symbols.size(); ++var12) {
  288.             Name var13 = (Name)this.symbols.elementAt(var12);
  289.             BitSet var14 = new BitSet(var2);
  290.  
  291.             for(int var15 = 0; var15 < var2; ++var15) {
  292.                if (var9.get(var15) && ((Terminal)this.terminalnodes.elementAt(var15)).name == var13) {
  293.                   var14.or(var3[var15]);
  294.                }
  295.             }
  296.  
  297.             Integer var20 = (Integer)var6.get(var14);
  298.             int var16;
  299.             if (var20 == null) {
  300.                var16 = var17.size();
  301.                var6.put(var14, new Integer(var16));
  302.                var5.addElement(var14);
  303.                var17.addElement(var14);
  304.                var10 = new int[this.symbols.size() + 1];
  305.                this.Dtrans.addElement(var10);
  306.                if (var14.get(this.end.pos)) {
  307.                   var10[this.symbols.size()] = 1;
  308.                }
  309.             } else {
  310.                var16 = var20;
  311.             }
  312.  
  313.             var11[var12] = var16;
  314.          }
  315.  
  316.          ++var8;
  317.       }
  318.  
  319.    }
  320.  
  321.    final Node parseNode(Parser var1) throws ParseException {
  322.       Object var2;
  323.       switch (var1.token) {
  324.          case -4:
  325.             var2 = new Terminal(this, var1.name);
  326.             break;
  327.          case 40:
  328.             var1.nextToken();
  329.             var2 = this.parseList(var1);
  330.             break;
  331.          default:
  332.             var2 = null;
  333.             var1.error("Illegal token in content model: " + var1.tokenString(var1.token));
  334.       }
  335.  
  336.       return this.finishNode(var1, (Node)var2);
  337.    }
  338.  
  339.    final Node parseRootNode(Parser var1) throws ParseException {
  340.       Object var2;
  341.       switch (var1.token) {
  342.          case -4:
  343.             var2 = new Terminal(this, var1.name);
  344.             break;
  345.          case 40:
  346.             var1.nextToken();
  347.             if (var1.token == 35) {
  348.                return this.parseMixed(var1);
  349.             }
  350.  
  351.             var2 = this.parseList(var1);
  352.             break;
  353.          default:
  354.             var2 = null;
  355.             var1.error("Expected ANY, EMPTY or '(' instead of: " + var1.tokenString(var1.token));
  356.       }
  357.  
  358.       return this.finishNode(var1, (Node)var2);
  359.    }
  360. }
  361.