lojix/logic/src/main/com/thesett/aima/logic/fol/isoprologparser/PrologParser.java
public Term listFunctor() throws SourceCodeException
    {
        // Get the interned names of the nil and cons functors.
        int nilId = interner.internFunctorName("nil", 0);
        int consId = interner.internFunctorName("cons", 2);

        // A list always starts with a '['.
        Token leftDelim = consumeToken(LSQPAREN);

        // Check if the list contains any arguments and parse them if so.
        Term[] args = null;

        Token nextToken = tokenSource.peek();

        switch (nextToken.kind)
        {
        case LPAREN:
        case LSQPAREN:
        case INTEGER_LITERAL:
        case FLOATING_POINT_LITERAL:
        case STRING_LITERAL:
        case VAR:
        case FUNCTOR:
        case ATOM:
            args = arglist();
            break;

        default:
        }

        // Work out what the terminal element in the list is. It will be 'nil' unless an explicit cons '|' has
        // been used to specify a different terminal element. In the case where cons is used explciitly, the
        // list prior to the cons must not be empty.
        Term accumulator;

        if (tokenSource.peek().kind == CONS)
        {
            if (args == null)
            {
                throw new SourceCodeException("Was expecting one of " + BEGIN_TERM_TOKENS + " but got " +
                    tokenImage[nextToken.kind] + ".", null, null, null,
                    new SourceCodePositionImpl(nextToken.beginLine, nextToken.beginColumn, nextToken.endLine,
                        nextToken.endColumn));
            }

            consumeToken(CONS);

            accumulator = term();
        }
        else
        {
            accumulator = new Nil(nilId, null);
        }

        // A list is always terminated with a ']'.
        Token rightDelim = consumeToken(RSQPAREN);

        // Walk down all of the lists arguments joining them together with cons/2 functors.
        if (args != null) // 'args' will contain one or more elements if not null.
        {
            for (int i = args.length - 1; i >= 0; i--)
            {
                Term previousAccumulator = accumulator;

                //accumulator = new Functor(consId.ordinal(), new Term[] { args[i], previousAccumulator });
                accumulator = new Cons(consId, new Term[] { args[i], previousAccumulator });
            }
        }

        // Set the position that the list was parsed from, as being the region between the '[' and ']' brackets.
        SourceCodePosition position =
            new SourceCodePositionImpl(leftDelim.beginLine, leftDelim.beginColumn, rightDelim.endLine,
                rightDelim.endColumn);
        accumulator.setSourceCodePosition(position);

        // The cast must succeed because arglist must return at least one argument, therefore the cons generating
        // loop must have been run at least once. If arglist is not called at all because an empty list was
        // encountered, then the accumulator will contain the 'nil' constant which is a functor of arity zero.
        return (Functor) accumulator;
    }
public Term listFunctor() throws SourceCodeException
    {
        // Get the interned names of the nil and cons functors.
        int nilId = interner.internFunctorName("nil", 0);
        int consId = interner.internFunctorName("cons", 2);

        // A list always starts with a '['.
        Token leftDelim = consumeToken(LSQPAREN);

        // Check if the list contains any arguments and parse them if so.
        Term[] args = null;

        Token nextToken = tokenSource.peek();

        switch (nextToken.kind)
        {
        case LPAREN:
        case LSQPAREN:
        case INTEGER_LITERAL:
        case FLOATING_POINT_LITERAL:
        case STRING_LITERAL:
        case VAR:
        case FUNCTOR:
        case ATOM:
            args = arglist();
            break;

        default:
        }

        // Work out what the terminal element in the list is. It will be 'nil' unless an explicit cons '|' has
        // been used to specify a different terminal element. In the case where cons is used explciitly, the
        // list prior to the cons must not be empty.
        Term accumulator;

        if (tokenSource.peek().kind == CONS)
        {
            if (args == null)
            {
                throw new SourceCodeException("Was expecting one of " + BEGIN_TERM_TOKENS + " but got " +
                    tokenImage[nextToken.kind] + ".", null, null, null,
                    new SourceCodePositionImpl(nextToken.beginLine, nextToken.beginColumn, nextToken.endLine,
                        nextToken.endColumn));
            }

            consumeToken(CONS);

            accumulator = term();
        }
        else
        {
            accumulator = new Nil(nilId, null);
        }

        // A list is always terminated with a ']'.
        Token rightDelim = consumeToken(RSQPAREN);

        // Walk down all of the lists arguments joining them together with cons/2 functors.
        if (args != null) // 'args' will contain one or more elements if not null.
        {
            for (int i = args.length - 1; i >= 0; i--)
            {
                Term previousAccumulator = accumulator;

                //accumulator = new Functor(consId.ordinal(), new Term[] { args[i], previousAccumulator });
                accumulator = new Cons(consId, new Term[] { args[i], previousAccumulator });
            }
        }

        // Set the position that the list was parsed from, as being the region between the '[' and ']' brackets.
        SourceCodePosition position =
            new SourceCodePositionImpl(leftDelim.beginLine, leftDelim.beginColumn, rightDelim.endLine,
                rightDelim.endColumn);
        accumulator.setSourceCodePosition(position);

        // The cast must succeed because arglist must return at least one argument, therefore the cons generating
        // loop must have been run at least once. If arglist is not called at all because an empty list was
        // encountered, then the accumulator will contain the 'nil' constant which is a functor of arity zero.
        return (Functor) accumulator;
    }
Parses a list expressed as a sequence of functors in first order logic. The empty list consists of the atom 'nil'
and a non-empty list consists of the functor 'cons' with arguments the head of the list and the remainder of the
list.

<p/>A list can be empty '[]', contains a sequence of terms seperated by commas '[a,...]', contain a sequence of
terms seperated by commas consed onto another term '[a,...|T]'. In the case where a term is consed onto the end,
if the term is itself a list the whole will form a list with a cons nil terminator, otherwise the term will be
consed onto the end as the list terminal.

@return A list expressed as a sequence of functors in first order.

@throws SourceCodeException If the token sequence does not parse as a valid list.