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