001    /*
002     * $Id: RingFactoryTokenizer.java 3488 2011-01-13 19:40:36Z kredel $
003     */
004    
005    package edu.jas.application;
006    
007    
008    import java.io.BufferedReader;
009    import java.io.IOException;
010    import java.io.InputStreamReader;
011    import java.io.Reader;
012    import java.io.StreamTokenizer;
013    import java.util.ArrayList;
014    import java.util.Iterator;
015    import java.util.List;
016    import java.util.Scanner;
017    
018    import org.apache.log4j.Logger;
019    
020    import edu.jas.arith.BigComplex;
021    import edu.jas.arith.BigDecimal;
022    import edu.jas.arith.BigInteger;
023    import edu.jas.arith.BigQuaternion;
024    import edu.jas.arith.BigRational;
025    import edu.jas.arith.ModInteger;
026    import edu.jas.arith.ModIntegerRing;
027    import edu.jas.arith.ModLong;
028    import edu.jas.arith.ModLongRing;
029    import edu.jas.structure.Power;
030    import edu.jas.structure.RingElem;
031    import edu.jas.structure.RingFactory;
032    import edu.jas.ufd.Quotient;
033    import edu.jas.ufd.QuotientRing;
034    import edu.jas.poly.GenPolynomial;
035    import edu.jas.poly.GenPolynomialRing;
036    import edu.jas.poly.GenSolvablePolynomial;
037    import edu.jas.poly.GenSolvablePolynomialRing;
038    import edu.jas.poly.ModuleList;
039    import edu.jas.poly.OrderedModuleList;
040    import edu.jas.poly.TermOrder;
041    import edu.jas.poly.ExpVector;
042    import edu.jas.poly.PolynomialList;
043    import edu.jas.poly.RelationTable;
044    import edu.jas.poly.AlgebraicNumberRing;
045    import edu.jas.poly.AlgebraicNumber;
046    import edu.jas.poly.GenPolynomialTokenizer;
047    
048    
049    /**
050     * RingFactory Tokenizer. Used to read ring factories from input streams.
051     * It can read also QuotientRing factory.
052     * @author Heinz Kredel
053     */
054    
055    public class RingFactoryTokenizer {
056    
057    
058        private static final Logger logger = Logger.getLogger(RingFactoryTokenizer.class);
059    
060    
061        private final boolean debug = logger.isDebugEnabled();
062    
063    
064        private String[] vars;
065    
066    
067        private int nvars = 1;
068    
069    
070        private TermOrder tord;
071    
072    
073        private RelationTable table;
074    
075    
076        //private Reader in;
077        private final StreamTokenizer tok;
078    
079    
080        private final Reader reader;
081    
082    
083        private RingFactory fac;
084    
085    
086        private static enum coeffType {
087            BigRat, BigInt, ModInt, BigC, BigQ, BigD, ANrat, ANmod, RatFunc, ModFunc, IntFunc
088        };
089    
090    
091        private coeffType parsedCoeff = coeffType.BigRat;
092    
093    
094        private GenPolynomialRing pfac;
095    
096    
097        private static enum polyType {
098            PolBigRat, PolBigInt, PolModInt, PolBigC, PolBigD, PolBigQ, PolANrat, PolANmod, PolRatFunc, PolModFunc, PolIntFunc
099        };
100    
101    
102        private polyType parsedPoly = polyType.PolBigRat;
103    
104    
105        private GenSolvablePolynomialRing spfac;
106    
107    
108        /**
109         * No-args constructor reads from System.in.
110         */
111        public RingFactoryTokenizer() {
112            this(new BufferedReader(new InputStreamReader(System.in)));
113        }
114    
115    
116        /**
117         * Constructor with Ring and Reader.
118         * @param rf ring factory.
119         * @param r reader stream.
120         */
121        public RingFactoryTokenizer(GenPolynomialRing rf, Reader r) {
122            this(r);
123            if (rf == null) {
124                return;
125            }
126            if (rf instanceof GenSolvablePolynomialRing) {
127                pfac = rf;
128                spfac = (GenSolvablePolynomialRing) rf;
129            } else {
130                pfac = rf;
131                spfac = null;
132            }
133            fac = rf.coFac;
134            vars = rf.getVars();
135            if (vars != null) {
136                nvars = vars.length;
137            }
138            tord = rf.tord;
139            // relation table
140            if (spfac != null) {
141                table = spfac.table;
142            } else {
143                table = null;
144            }
145        }
146    
147    
148        /**
149         * Constructor with Reader.
150         * @param r reader stream.
151         */
152        @SuppressWarnings("unchecked")
153        public RingFactoryTokenizer(Reader r) {
154            //BasicConfigurator.configure();
155            vars = null;
156            tord = new TermOrder();
157            nvars = 1;
158            fac = new BigRational(1);
159    
160            //pfac = null;
161            pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars);
162    
163            //spfac = null;
164            spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars);
165    
166            reader = r;
167            tok = new StreamTokenizer(r);
168            tok.resetSyntax();
169            // tok.eolIsSignificant(true); no more
170            tok.eolIsSignificant(false);
171            tok.wordChars('0', '9');
172            tok.wordChars('a', 'z');
173            tok.wordChars('A', 'Z');
174            tok.wordChars('_', '_'); // for subscripts x_i
175            tok.wordChars('/', '/'); // wg. rational numbers
176            tok.wordChars(128 + 32, 255);
177            tok.whitespaceChars(0, ' ');
178            tok.commentChar('#');
179            tok.quoteChar('"');
180            tok.quoteChar('\'');
181            //tok.slashStarComments(true); does not work
182    
183        }
184    
185    
186        /**
187         * Initialize coefficient and polynomial factories.
188         * @param rf ring factory.
189         * @param ct coefficient type.
190         */
191        @SuppressWarnings("unchecked")
192        public void initFactory(RingFactory rf, coeffType ct) {
193            fac = rf;
194            parsedCoeff = ct;
195    
196            switch (ct) {
197            case BigRat:
198                pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars);
199                parsedPoly = polyType.PolBigRat;
200                break;
201            case BigInt:
202                pfac = new GenPolynomialRing<BigInteger>(fac, nvars, tord, vars);
203                parsedPoly = polyType.PolBigInt;
204                break;
205            case ModInt:
206                pfac = new GenPolynomialRing<ModInteger>(fac, nvars, tord, vars);
207                parsedPoly = polyType.PolModInt;
208                break;
209            case BigC:
210                pfac = new GenPolynomialRing<BigComplex>(fac, nvars, tord, vars);
211                parsedPoly = polyType.PolBigC;
212                break;
213            case BigQ:
214                pfac = new GenPolynomialRing<BigQuaternion>(fac, nvars, tord, vars);
215                parsedPoly = polyType.PolBigQ;
216                break;
217            case BigD:
218                pfac = new GenPolynomialRing<BigDecimal>(fac, nvars, tord, vars);
219                parsedPoly = polyType.PolBigD;
220                break;
221            case RatFunc:
222                pfac = new GenPolynomialRing<Quotient<BigInteger>>(fac, nvars, tord, vars);
223                parsedPoly = polyType.PolRatFunc;
224                break;
225            case ModFunc:
226                pfac = new GenPolynomialRing<Quotient<ModInteger>>(fac, nvars, tord, vars);
227                parsedPoly = polyType.PolModFunc;
228                break;
229            case IntFunc:
230                pfac = new GenPolynomialRing<GenPolynomial<BigRational>>(fac, nvars, tord, vars);
231                parsedPoly = polyType.PolIntFunc;
232                break;
233            default:
234                pfac = new GenPolynomialRing<BigRational>(fac, nvars, tord, vars);
235                parsedPoly = polyType.PolBigRat;
236            }
237        }
238    
239    
240        /**
241         * Initialize coefficient and solvable polynomial factories.
242         * @param rf ring factory.
243         * @param ct coefficient type.
244         */
245        @SuppressWarnings("unchecked")
246        public void initSolvableFactory(RingFactory rf, coeffType ct) {
247            fac = rf;
248            parsedCoeff = ct;
249    
250            switch (ct) {
251            case BigRat:
252                spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars);
253                parsedPoly = polyType.PolBigRat;
254                break;
255            case BigInt:
256                spfac = new GenSolvablePolynomialRing<BigInteger>(fac, nvars, tord, vars);
257                parsedPoly = polyType.PolBigInt;
258                break;
259            case ModInt:
260                spfac = new GenSolvablePolynomialRing<ModInteger>(fac, nvars, tord, vars);
261                parsedPoly = polyType.PolModInt;
262                break;
263            case BigC:
264                spfac = new GenSolvablePolynomialRing<BigComplex>(fac, nvars, tord, vars);
265                parsedPoly = polyType.PolBigC;
266                break;
267            case BigQ:
268                spfac = new GenSolvablePolynomialRing<BigQuaternion>(fac, nvars, tord, vars);
269                parsedPoly = polyType.PolBigQ;
270                break;
271            case BigD:
272                spfac = new GenSolvablePolynomialRing<BigDecimal>(fac, nvars, tord, vars);
273                parsedPoly = polyType.PolBigD;
274                break;
275            case RatFunc:
276                spfac = new GenSolvablePolynomialRing<Quotient<BigInteger>>(fac, nvars, tord, vars);
277                parsedPoly = polyType.PolRatFunc;
278                break;
279            case ModFunc:
280                spfac = new GenSolvablePolynomialRing<Quotient<ModInteger>>(fac, nvars, tord, vars);
281                parsedPoly = polyType.PolModFunc;
282                break;
283            case IntFunc:
284                spfac = new GenSolvablePolynomialRing<GenPolynomial<BigRational>>(fac, nvars, tord, vars);
285                parsedPoly = polyType.PolIntFunc;
286                break;
287            default:
288                spfac = new GenSolvablePolynomialRing<BigRational>(fac, nvars, tord, vars);
289                parsedPoly = polyType.PolBigRat;
290            }
291        }
292    
293    
294        /**
295         * Parsing method for comments. syntax: (* comment *) | /_* comment *_/
296         * without _ Does not work with this pushBack(), unused.
297         */
298        public String nextComment() throws IOException {
299            // syntax: (* comment *) | /* comment */ 
300            StringBuffer c = new StringBuffer();
301            int tt;
302            if (debug)
303                logger.debug("comment: " + tok);
304            tt = tok.nextToken();
305            if (debug)
306                logger.debug("comment: " + tok);
307            if (tt == '(') {
308                tt = tok.nextToken();
309                if (debug)
310                    logger.debug("comment: " + tok);
311                if (tt == '*') {
312                    if (debug)
313                        logger.debug("comment: ");
314                    while (true) {
315                        tt = tok.nextToken();
316                        if (tt == '*') {
317                            tt = tok.nextToken();
318                            if (tt == ')') {
319                                return c.toString();
320                            }
321                            tok.pushBack();
322                        }
323                        c.append(tok.sval);
324                    }
325                }
326                tok.pushBack();
327                if (debug)
328                    logger.debug("comment: " + tok);
329            }
330            tok.pushBack();
331            if (debug)
332                logger.debug("comment: " + tok);
333            return c.toString();
334        }
335    
336    
337        /**
338         * Parsing method for variable list. syntax: (a, b c, de) gives [ "a", "b",
339         * "c", "de" ]
340         * @return the next variable list.
341         * @throws IOException
342         */
343        public String[] nextVariableList() throws IOException {
344            List<String> l = new ArrayList<String>();
345            int tt;
346            tt = tok.nextToken();
347            //System.out.println("vList tok = " + tok);
348            if (tt == '(' || tt == '{') {
349                logger.debug("variable list");
350                tt = tok.nextToken();
351                while (true) {
352                    if (tt == StreamTokenizer.TT_EOF)
353                        break;
354                    if (tt == ')' || tt == '}')
355                        break;
356                    if (tt == StreamTokenizer.TT_WORD) {
357                        //System.out.println("TT_WORD: " + tok.sval);
358                        l.add(tok.sval);
359                    }
360                    tt = tok.nextToken();
361                }
362            }
363            Object[] ol = l.toArray();
364            String[] v = new String[ol.length];
365            for (int i = 0; i < v.length; i++) {
366                v[i] = (String) ol[i];
367            }
368            return v;
369        }
370    
371    
372        /**
373         * Parsing method for coefficient ring. syntax: Rat | Q | Int | Z | Mod
374         * modul | Complex | C | D | Quat | AN[ (var) ( poly ) | AN[ modul (var) (
375         * poly ) ] | RatFunc (var_list) | ModFunc modul (var_list) | IntFunc
376         * (var_list)
377         * @return the next coefficient factory.
378         * @throws IOException
379         */
380        @SuppressWarnings("unchecked")
381        public RingFactory nextCoefficientRing() throws IOException {
382            RingFactory coeff = null;
383            coeffType ct = null;
384            int tt;
385            tt = tok.nextToken();
386            if (tok.sval != null) {
387                if (tok.sval.equalsIgnoreCase("Q")) {
388                    coeff = new BigRational(0);
389                    ct = coeffType.BigRat;
390                } else if (tok.sval.equalsIgnoreCase("Rat")) {
391                    coeff = new BigRational(0);
392                    ct = coeffType.BigRat;
393                } else if (tok.sval.equalsIgnoreCase("D")) {
394                    coeff = new BigDecimal(0);
395                    ct = coeffType.BigD;
396                } else if (tok.sval.equalsIgnoreCase("Z")) {
397                    coeff = new BigInteger(0);
398                    ct = coeffType.BigInt;
399                } else if (tok.sval.equalsIgnoreCase("Int")) {
400                    coeff = new BigInteger(0);
401                    ct = coeffType.BigInt;
402                } else if (tok.sval.equalsIgnoreCase("C")) {
403                    coeff = new BigComplex(0);
404                    ct = coeffType.BigC;
405                } else if (tok.sval.equalsIgnoreCase("Complex")) {
406                    coeff = new BigComplex(0);
407                    ct = coeffType.BigC;
408                } else if (tok.sval.equalsIgnoreCase("Quat")) {
409                    coeff = new BigQuaternion(0);
410                    ct = coeffType.BigQ;
411                } else if (tok.sval.equalsIgnoreCase("Mod")) {
412                    tt = tok.nextToken();
413                    boolean openb = false;
414                    if (tt == '[') { // optional
415                        openb = true;
416                        tt = tok.nextToken();
417                    }
418                    if (tok.sval != null && tok.sval.length() > 0) {
419                        if (digit(tok.sval.charAt(0))) {
420                            BigInteger mo = new BigInteger(tok.sval);
421                            BigInteger lm = new BigInteger(Long.MAX_VALUE);
422                            if ( mo.compareTo(lm) < 0 ) {
423                                coeff = new ModLongRing(mo.getVal());
424                            } else {
425                                coeff = new ModIntegerRing(mo.getVal());
426                            }
427                            System.out.println("coeff = " + coeff + " :: " + coeff.getClass());
428                            ct = coeffType.ModInt;
429                        } else {
430                            tok.pushBack();
431                        }
432                    } else {
433                        tok.pushBack();
434                    }
435                    if (tt == ']' && openb) { // optional
436                        tt = tok.nextToken();
437                    }
438                } else if (tok.sval.equalsIgnoreCase("RatFunc")) {
439                    String[] rfv = nextVariableList();
440                    //System.out.println("rfv = " + rfv.length + " " + rfv[0]);
441                    int vr = rfv.length;
442                    BigInteger bi = new BigInteger();
443                    TermOrder to = new TermOrder(TermOrder.INVLEX);
444                    GenPolynomialRing<BigInteger> pcf = new GenPolynomialRing<BigInteger>(bi, vr, to, rfv);
445                    coeff = new QuotientRing(pcf);
446                    ct = coeffType.RatFunc;
447                } else if (tok.sval.equalsIgnoreCase("ModFunc")) {
448                    tt = tok.nextToken();
449                    RingFactory mi = new ModIntegerRing("19");
450                    if (tok.sval != null && tok.sval.length() > 0) {
451                        if (digit(tok.sval.charAt(0))) {
452                            mi = new ModIntegerRing(tok.sval);
453                        } else {
454                            tok.pushBack();
455                        }
456                    } else {
457                        tok.pushBack();
458                    }
459                    String[] rfv = nextVariableList();
460                    //System.out.println("rfv = " + rfv.length + " " + rfv[0]);
461                    int vr = rfv.length;
462                    TermOrder to = new TermOrder(TermOrder.INVLEX);
463                    GenPolynomialRing<ModInteger> pcf = new GenPolynomialRing<ModInteger>(mi, vr, to, rfv);
464                    coeff = new QuotientRing(pcf);
465                    ct = coeffType.ModFunc;
466                } else if (tok.sval.equalsIgnoreCase("IntFunc")) {
467                    String[] rfv = nextVariableList();
468                    //System.out.println("rfv = " + rfv.length + " " + rfv[0]);
469                    int vr = rfv.length;
470                    BigRational bi = new BigRational();
471                    TermOrder to = new TermOrder(TermOrder.INVLEX);
472                    GenPolynomialRing<BigRational> pcf = new GenPolynomialRing<BigRational>(bi, vr, to, rfv);
473                    coeff = pcf;
474                    ct = coeffType.IntFunc;
475                } else if (tok.sval.equalsIgnoreCase("AN")) {
476                    tt = tok.nextToken();
477                    if (tt == '[') {
478                        tt = tok.nextToken();
479                        RingFactory tcfac = new ModIntegerRing("19");
480                        if (tok.sval != null && tok.sval.length() > 0) {
481                            if (digit(tok.sval.charAt(0))) {
482                                tcfac = new ModIntegerRing(tok.sval);
483                            } else {
484                                tcfac = new BigRational();
485                                tok.pushBack();
486                            }
487                        } else {
488                            tcfac = new BigRational();
489                            tok.pushBack();
490                        }
491                        String[] anv = nextVariableList();
492                        //System.out.println("anv = " + anv.length + " " + anv[0]);
493                        int vs = anv.length;
494                        if (vs != 1) {
495                            logger.error("AlgebraicNumber only for univariate polynomials");
496                        }
497                        String[] ovars = vars;
498                        vars = anv;
499                        GenPolynomialRing tpfac = pfac;
500                        RingFactory tfac = fac;
501                        fac = tcfac;
502                        // pfac and fac used in nextPolynomial()
503                        if (tcfac instanceof ModIntegerRing) {
504                            pfac = new GenPolynomialRing<ModInteger>(tcfac, vs, new TermOrder(), anv);
505                        } else {
506                            pfac = new GenPolynomialRing<BigRational>(tcfac, vs, new TermOrder(), anv);
507                        }
508                        if (debug) {
509                            logger.debug("pfac = " + pfac);
510                        }
511                        GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac,reader);
512                        GenPolynomial mod = ptok.nextPolynomial();
513                        ptok = null;
514                        if (debug) {
515                            logger.debug("mod = " + mod);
516                        }
517                        pfac = tpfac;
518                        fac = tfac;
519                        vars = ovars;
520                        if (tcfac instanceof ModIntegerRing) {
521                            GenPolynomial<ModInteger> gfmod;
522                            gfmod = (GenPolynomial<ModInteger>) mod;
523                            coeff = new AlgebraicNumberRing<ModInteger>(gfmod);
524                            ct = coeffType.ANmod;
525                        } else {
526                            GenPolynomial<BigRational> anmod;
527                            anmod = (GenPolynomial<BigRational>) mod;
528                            coeff = new AlgebraicNumberRing<BigRational>(anmod);
529                            ct = coeffType.ANrat;
530                        }
531                        if (debug) {
532                            logger.debug("coeff = " + coeff);
533                        }
534                        tt = tok.nextToken();
535                        if (tt == ']') {
536                            //ok, no nextToken();
537                        } else {
538                            tok.pushBack();
539                        }
540                    } else {
541                        tok.pushBack();
542                    }
543                }
544            }
545            if (coeff == null) {
546                tok.pushBack();
547                coeff = new BigRational();
548                ct = coeffType.BigRat;
549            }
550            parsedCoeff = ct;
551            return coeff;
552        }
553    
554    
555        /**
556         * Parsing method for weight list. syntax: (w1, w2, w3, ..., wn)
557         * @return the next weight list.
558         * @throws IOException
559         */
560        public long[] nextWeightList() throws IOException {
561            List<Long> l = new ArrayList<Long>();
562            long[] w = null;
563            long e;
564            char first;
565            int tt;
566            tt = tok.nextToken();
567            if (tt == '(') {
568                logger.debug("weight list");
569                tt = tok.nextToken();
570                while (true) {
571                    if (tt == StreamTokenizer.TT_EOF)
572                        break;
573                    if (tt == ')')
574                        break;
575                    if (tok.sval != null) {
576                        first = tok.sval.charAt(0);
577                        if (digit(first)) {
578                            e = Long.parseLong(tok.sval);
579                            l.add(new Long(e));
580                            //System.out.println("w: " + e);
581                        }
582                    }
583                    tt = tok.nextToken(); // also comma
584                }
585            }
586            Object[] ol = l.toArray();
587            w = new long[ol.length];
588            for (int i = 0; i < w.length; i++) {
589                w[i] = ((Long) ol[ol.length - i - 1]).longValue();
590            }
591            return w;
592        }
593    
594    
595        /**
596         * Parsing method for weight array. syntax: ( (w11, ...,w1n), ..., (wm1,
597         * ..., wmn) )
598         * @return the next weight array.
599         * @throws IOException
600         */
601        public long[][] nextWeightArray() throws IOException {
602            List<long[]> l = new ArrayList<long[]>();
603            long[][] w = null;
604            long[] e;
605            char first;
606            int tt;
607            tt = tok.nextToken();
608            if (tt == '(') {
609                logger.debug("weight array");
610                tt = tok.nextToken();
611                while (true) {
612                    if (tt == StreamTokenizer.TT_EOF)
613                        break;
614                    if (tt == ')')
615                        break;
616                    if (tt == '(') {
617                        tok.pushBack();
618                        e = nextWeightList();
619                        l.add(e);
620                        //System.out.println("wa: " + e);
621                    } else if (tok.sval != null) {
622                        first = tok.sval.charAt(0);
623                        if (digit(first)) {
624                            tok.pushBack();
625                            tok.pushBack();
626                            e = nextWeightList();
627                            l.add(e);
628                            break;
629                            //System.out.println("w: " + e);
630                        }
631                    }
632                    tt = tok.nextToken(); // also comma
633                }
634            }
635            Object[] ol = l.toArray();
636            w = new long[ol.length][];
637            for (int i = 0; i < w.length; i++) {
638                w[i] = (long[]) ol[i];
639            }
640            return w;
641        }
642    
643    
644        /**
645         * Parsing method for split index. syntax: |i|
646         * @return the next split index.
647         * @throws IOException
648         */
649        public int nextSplitIndex() throws IOException {
650            int e = -1; // =unknown
651            int e0 = -1; // =unknown
652            char first;
653            int tt;
654            tt = tok.nextToken();
655            if (tt == '|') {
656                logger.debug("split index");
657                tt = tok.nextToken();
658                if (tt == StreamTokenizer.TT_EOF) {
659                    return e;
660                } else if (tok.sval != null) {
661                    first = tok.sval.charAt(0);
662                    if (digit(first)) {
663                        e = Integer.parseInt(tok.sval);
664                        //System.out.println("w: " + i);
665                    }
666                    tt = tok.nextToken();
667                    if (tt != '|') {
668                        tok.pushBack();
669                    }
670                }
671            } else if (tt == '[') {
672                logger.debug("split index");
673                tt = tok.nextToken();
674                if (tt == StreamTokenizer.TT_EOF) {
675                    return e;
676                }
677                if (tok.sval != null) {
678                    first = tok.sval.charAt(0);
679                    if (digit(first)) {
680                        e0 = Integer.parseInt(tok.sval);
681                        //System.out.println("w: " + i);
682                    }
683                    tt = tok.nextToken();
684                    if (tt == ',') {
685                        tt = tok.nextToken();
686                        if (tt == StreamTokenizer.TT_EOF) {
687                            return e;
688                        }
689                        if (tok.sval != null) {
690                            first = tok.sval.charAt(0);
691                            if (digit(first)) {
692                                e = Integer.parseInt(tok.sval);
693                                //System.out.println("w: " + i);
694                            }
695                        }
696                        if (tt != ']') {
697                            tok.pushBack();
698                        }
699                    }
700                }
701            } else {
702                tok.pushBack();
703            }
704            return e;
705        }
706    
707    
708        /**
709         * Parsing method for term order name. syntax: termOrderName = L, IL, LEX,
710         * G, IG, GRLEX, W(weights) |split index|
711         * @return the next term order.
712         * @throws IOException
713         */
714        public TermOrder nextTermOrder() throws IOException {
715            int evord = TermOrder.DEFAULT_EVORD;
716            int tt;
717            tt = tok.nextToken();
718            if (tt == StreamTokenizer.TT_EOF) { /* nop */
719            } else if (tt == StreamTokenizer.TT_WORD) {
720                // System.out.println("TT_WORD: " + tok.sval);
721                if (tok.sval != null) {
722                    if (tok.sval.equalsIgnoreCase("L")) {
723                        evord = TermOrder.INVLEX;
724                    } else if (tok.sval.equalsIgnoreCase("IL")) {
725                        evord = TermOrder.INVLEX;
726                    } else if (tok.sval.equalsIgnoreCase("INVLEX")) {
727                        evord = TermOrder.INVLEX;
728                    } else if (tok.sval.equalsIgnoreCase("LEX")) {
729                        evord = TermOrder.LEX;
730                    } else if (tok.sval.equalsIgnoreCase("G")) {
731                        evord = TermOrder.IGRLEX;
732                    } else if (tok.sval.equalsIgnoreCase("IG")) {
733                        evord = TermOrder.IGRLEX;
734                    } else if (tok.sval.equalsIgnoreCase("IGRLEX")) {
735                        evord = TermOrder.IGRLEX;
736                    } else if (tok.sval.equalsIgnoreCase("GRLEX")) {
737                        evord = TermOrder.GRLEX;
738                    } else if (tok.sval.equalsIgnoreCase("W")) {
739                        long[][] w = nextWeightArray();
740                        //int s = nextSplitIndex(); // no more
741                        return new TermOrder(w);
742                    }
743                }
744            }
745            int s = nextSplitIndex();
746            if (s <= 0) {
747                return new TermOrder(evord);
748            } else {
749                return new TermOrder(evord, evord, vars.length, s);
750            }
751        }
752    
753    
754        /**
755         * Parsing method for solvable polynomial relation table. syntax: ( p_1,
756         * p_2, p_3, ..., p_{n+3} ) semantics: p_{n+1} * p_{n+2} = p_{n+3} The next
757         * relation table is stored into the solvable polynomial factory.
758         * @throws IOException
759         */
760        @SuppressWarnings("unchecked")
761        public void nextRelationTable() throws IOException {
762            if (spfac == null) {
763                return;
764            }
765            RelationTable table = spfac.table;
766            List<GenPolynomial> rels = null;
767            GenPolynomial p;
768            GenSolvablePolynomial sp;
769            int tt;
770            tt = tok.nextToken();
771            if (tok.sval != null) {
772                if (tok.sval.equalsIgnoreCase("RelationTable")) {
773                    GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac,reader);
774                    rels = ptok.nextPolynomialList();
775                    ptok = null;
776                }
777            }
778            if (rels == null) {
779                tok.pushBack();
780                return;
781            }
782            for (Iterator<GenPolynomial> it = rels.iterator(); it.hasNext();) {
783                p = it.next();
784                ExpVector e = p.leadingExpVector();
785                if (it.hasNext()) {
786                    p = it.next();
787                    ExpVector f = p.leadingExpVector();
788                    if (it.hasNext()) {
789                        p = it.next();
790                        sp = new GenSolvablePolynomial(spfac);
791                        sp.doPutToMap(p.getMap());
792                        table.update(e, f, sp);
793                    }
794                }
795            }
796            if (debug) {
797                logger.info("table = " + table);
798            }
799            return;
800        }
801    
802    
803        /**
804         * Parsing method for polynomial set. syntax: coeffRing varList
805         * termOrderName polyList.
806         * @return the next polynomial set.
807         * @throws IOException
808         */
809        @SuppressWarnings("unchecked")
810        public GenPolynomialRing nextPolynomialRing() throws IOException {
811            //String comments = "";
812            //comments += nextComment();
813            //if (debug) logger.debug("comment = " + comments);
814    
815            RingFactory coeff = nextCoefficientRing();
816            logger.info("coeff = " + coeff);
817    
818            vars = nextVariableList();
819            String dd = "vars =";
820            for (int i = 0; i < vars.length; i++) {
821                dd += " " + vars[i];
822            }
823            logger.info(dd);
824            if (vars != null) {
825                nvars = vars.length;
826            }
827    
828            tord = nextTermOrder();
829            logger.info("tord = " + tord);
830            // check more TOs
831            initFactory(coeff, parsedCoeff); // global: nvars, tord, vars
832            // now pfac is initialized
833            return pfac;
834        }
835    
836    
837        /**
838         * Parsing method for solvable polynomial set. syntax: varList termOrderName
839         * relationTable polyList.
840         * @return the next solvable polynomial set.
841         * @throws IOException
842         */
843        @SuppressWarnings("unchecked")
844        public GenSolvablePolynomialRing nextSolvablePolynomialRing() throws IOException {
845            //String comments = "";
846            //comments += nextComment();
847            //if (debug) logger.debug("comment = " + comments);
848    
849            RingFactory coeff = nextCoefficientRing();
850            logger.info("coeff = " + coeff);
851    
852            vars = nextVariableList();
853            String dd = "vars =";
854            for (int i = 0; i < vars.length; i++) {
855                dd += " " + vars[i];
856            }
857            logger.info(dd);
858            if (vars != null) {
859                nvars = vars.length;
860            }
861    
862            tord = nextTermOrder();
863            logger.info("tord = " + tord);
864            // check more TOs
865    
866            initFactory(coeff, parsedCoeff); // must be because of symmetric read
867            initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars
868            //System.out.println("pfac = " + pfac);
869            //System.out.println("spfac = " + spfac);
870    
871            nextRelationTable();
872            if (logger.isInfoEnabled()) {
873                logger.info("table = " + table + ", tok = " + tok);
874            }
875            // now spfac is initialized
876            return spfac; 
877        }
878    
879    
880        private boolean digit(char x) {
881            return '0' <= x && x <= '9';
882        }
883    
884    
885        private boolean letter(char x) {
886            return ('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z');
887        }
888    
889    
890        // unused
891        public void nextComma() throws IOException {
892            int tt;
893            if (tok.ttype == ',') {
894                if (debug)
895                    logger.debug("comma: ");
896                tt = tok.nextToken();
897            }
898        }
899    
900    
901        /**
902         * Parse variable list from String.
903         * @param s String. Syntax: (n1,...,nk) or (n1 ... nk), brackest are also
904         *            optional.
905         * @return array of variable names found in s.
906         */
907        public static String[] variableList(String s) {
908            String[] vl = null;
909            if (s == null) {
910                return vl;
911            }
912            String st = s.trim();
913            if (st.length() == 0) {
914                return new String[0];
915            }
916            if (st.charAt(0) == '(') {
917                st = st.substring(1);
918            }
919            if (st.charAt(st.length() - 1) == ')') {
920                st = st.substring(0, st.length() - 1);
921            }
922            st = st.replaceAll(",", " ");
923            List<String> sl = new ArrayList<String>();
924            Scanner sc = new Scanner(st);
925            while (sc.hasNext()) {
926                String sn = sc.next();
927                sl.add(sn);
928            }
929            vl = new String[sl.size()];
930            int i = 0;
931            for (String si : sl) {
932                vl[i] = si;
933                i++;
934            }
935            return vl;
936        }
937    
938    }