tom-weatherhead/thaw-grammar

View on GitHub
src/languages/prolog/prolog-grammar.ts

Summary

Maintainability
A
0 mins
Test Coverage
// tom-weatherhead/thaw-grammar/src/languages/prolog/prolog-grammar.ts

// Prolog file extensions: .pl, .pro, .P
// See https://en.wikipedia.org/wiki/Prolog

import {
    GrammarSymbol,
    IToken,
    LanguageSelector,
    LexicalState,
    SemanticStackType
} from 'thaw-interpreter-types';

import { ArgumentException, createProduction } from 'thaw-interpreter-core';

import { GrammarBase, GrammarException } from 'thaw-interpreter-core';

import { createFunctorExpressionFromGoal } from './utilities';

import { PrologClause } from './domain-object-model/prolog-clause';
import { PrologFloatLiteral } from './domain-object-model/prolog-float-literal';
import {
    // isPrologFunctorExpression,
    PrologFunctorExpression
} from './domain-object-model/prolog-functor-expression';
import { PrologGoal } from './domain-object-model/prolog-goal';
import { PrologIntegerLiteral } from './domain-object-model/prolog-integer-literal';
import { createPrologVariable } from './domain-object-model/prolog-variable';

import { IPrologExpression } from './domain-object-model/interfaces/iprolog-expression';

export class PrologGrammar extends GrammarBase {
    constructor() {
        super(GrammarSymbol.nonterminalStart);

        // Terminals:

        this.terminals.push(GrammarSymbol.terminalDot);
        this.terminals.push(GrammarSymbol.terminalComma);
        // this.terminals.push(GrammarSymbol.terminalSemicolon);
        this.terminals.push(GrammarSymbol.terminalLeftBracket);
        this.terminals.push(GrammarSymbol.terminalRightBracket);
        this.terminals.push(GrammarSymbol.terminalLeftSquareBracket);
        this.terminals.push(GrammarSymbol.terminalRightSquareBracket);
        this.terminals.push(GrammarSymbol.terminalNameBeginningWithCapital);
        this.terminals.push(GrammarSymbol.terminalNameNotBeginningWithCapital);
        this.terminals.push(GrammarSymbol.terminalFrom);
        this.terminals.push(GrammarSymbol.terminalInferPred);
        this.terminals.push(GrammarSymbol.terminalIntegerLiteral);
        this.terminals.push(GrammarSymbol.terminalOrBar);
        this.terminals.push(GrammarSymbol.terminalNotSymbol);
        this.terminals.push(GrammarSymbol.terminalIs);
        this.terminals.push(GrammarSymbol.terminalLessThan);
        this.terminals.push(GrammarSymbol.terminalGreaterThan);
        this.terminals.push(GrammarSymbol.terminalEquals);
        this.terminals.push(GrammarSymbol.terminalPlus);
        this.terminals.push(GrammarSymbol.terminalMinus);
        this.terminals.push(GrammarSymbol.terminalMultiply);
        // this.terminals.push(GrammarSymbol.terminalDivide);
        // this.terminals.push(GrammarSymbol.terminalModulus);
        this.terminals.push(GrammarSymbol.terminalLessOrEqual);
        this.terminals.push(GrammarSymbol.terminalGreaterOrEqual);
        this.terminals.push(GrammarSymbol.terminalNotEqual);
        this.terminals.push(GrammarSymbol.terminalArithmeticEqual);
        this.terminals.push(GrammarSymbol.terminalArithmeticNotEqual);
        this.terminals.push(GrammarSymbol.terminalUnifiable);
        this.terminals.push(GrammarSymbol.terminalNotUnifiable);
        this.terminals.push(GrammarSymbol.terminalIfThen);
        this.terminals.push(GrammarSymbol.terminalColon);
        this.terminals.push(GrammarSymbol.terminalDCGArrow);
        this.terminals.push(GrammarSymbol.terminalUniv);
        this.terminals.push(GrammarSymbol.terminalCaret);
        // this.terminals.push(GrammarSymbol.terminal);

        this.terminals.push(GrammarSymbol.terminalEOF);

        // Not yet added: From PrologGrammar2:
        // Symbol.T_Divide, Symbol.T_StringLiteral, Symbol.T_Semicolon, Symbol.T_Mod,
        // Symbol.T_LeftCurlyBrace, Symbol.T_RightCurlyBrace, Symbol.T_FloatLiteral

        this.nonTerminals.push(GrammarSymbol.nonterminalStart);
        this.nonTerminals.push(GrammarSymbol.nonterminalInput);
        this.nonTerminals.push(GrammarSymbol.nonterminalClause);
        this.nonTerminals.push(GrammarSymbol.nonterminalQuery);
        this.nonTerminals.push(GrammarSymbol.nonterminalExpression);
        // this.nonTerminals.push(GrammarSymbol.nonterminalExpressionList);
        this.nonTerminals.push(GrammarSymbol.nonterminalGoal);
        // this.nonTerminals.push(GrammarSymbol.nonterminalLHSGoal);
        this.nonTerminals.push(GrammarSymbol.nonterminalClauseTail);
        // this.nonTerminals.push(GrammarSymbol.nonterminalLHSGoalTail);
        // this.nonTerminals.push(GrammarSymbol.nonterminalFunctor);
        // this.nonTerminals.push(GrammarSymbol.nonterminalFunctorParameters);
        // this.nonTerminals.push(
        //     GrammarSymbol.nonterminalGoalWithPossibleDisjunctiveTail
        // );
        // this.nonTerminals.push(GrammarSymbol.nonterminalGoalList);
        // this.nonTerminals.push(GrammarSymbol.nonterminalPossibleDisjunctiveTail);
        this.nonTerminals.push(GrammarSymbol.nonterminalVariable);
        this.nonTerminals.push(GrammarSymbol.nonterminalList);
        this.nonTerminals.push(GrammarSymbol.nonterminalListContents);
        this.nonTerminals.push(GrammarSymbol.nonterminalListContentsTail);
        this.nonTerminals.push(GrammarSymbol.nonterminalGoalListTail);
        this.nonTerminals.push(GrammarSymbol.nonterminalFunctorExpression);
        this.nonTerminals.push(GrammarSymbol.nonterminalTailOfGoalOrFunctorExpression);
        this.nonTerminals.push(GrammarSymbol.nonterminalExpressionListTail);
        this.nonTerminals.push(GrammarSymbol.nonterminalOptr);
        this.nonTerminals.push(GrammarSymbol.nonterminalArithmeticOperator);
        this.nonTerminals.push(GrammarSymbol.nonterminalArithmeticComparisonOperator);
        this.nonTerminals.push(GrammarSymbol.nonterminalGoalTail1);
        this.nonTerminals.push(GrammarSymbol.nonterminalVariableOrNumericLiteral);
        // this.nonTerminals.push(GrammarSymbol.nonterminal);

        // Non-Terminals:

        // NonTerminals.UnionWith(new HashSet<Symbol>() {
        // Symbol.N_GoalWithPossibleDisjunctiveTail, Symbol.N_PossibleDisjunctiveTail,
        // Symbol.N_NumberOrVariableExpression,
        // Symbol.N_Functor, Symbol.N_Name, Symbol.N_Predicate, Symbol.N_ExpressionTail,
        // Symbol.N_IfThenElseTail, Symbol.N_InfixNonArithmeticPredicateTail, Symbol.N_InfixPredicateTail,
        // Symbol.N_ListContentsTail, Symbol.N_ExpressionPartFollowingAnInteger, Symbol.N_ExpressionPartFollowingAnUpperCaseID,
        // Symbol.N_ExpressionPartFollowingALowerCaseID, Symbol.N_ExpressionPartFollowingALowerCaseIDWithParams,
        // Symbol.N_ExpressionPartFollowingAMinus, Symbol.N_ExpressionPartFollowingMinusLBracketExpr,
        // Symbol.N_OpType_EqualOrUnifiable, Symbol.N_LHSGoal, Symbol.N_LHSGoalTail, //Symbol.N_ComparisonTail,
        // Symbol.N_PrefixArithmeticExpression, Symbol.N_ArithmeticExpression3Minus, Symbol.N_ArithmeticExpression3MinusLBrackArithExpr,
        // // Arithmetic
        // Symbol.N_ArithmeticExpression1, Symbol.N_ArithmeticExpression2, Symbol.N_ArithmeticExpression3, Symbol.N_ArithmeticExpression4,
        // Symbol.N_ArithmeticExpression1Foo, Symbol.N_ArithmeticExpression2Foo, Symbol.N_OpType_Add, Symbol.N_OpType_Multiply,
        // Symbol.N_ModExpression, Symbol.N_PrefixMinusExpression,
        // // Arithmetic comparisons
        // Symbol.N_ComparisonOperator, Symbol.N_ArithmeticAndComparisonTail,
        // //, Symbol.N_GoalBeginningWithArithmeticExpression, Symbol.N_ArithmeticExpressionTail1, Symbol.N_ArithmeticExpressionTail2
        // // Lists
        // Symbol.N_List, Symbol.N_ListContents, Symbol.N_ListTail, Symbol.N_ListContentsTail,
        // // Sequences
        // Symbol.N_Sequence,
        // // Definite Clause Grammar support
        // Symbol.N_DCGRHSGoal, Symbol.N_DCGRHSGoalList,
        // // Caret List (Var1 ^ Var2 ^ ... ^ functorExpression) support
        // Symbol.N_CaretTail, Symbol.N_CaretTail2
        // });

        // Productions:

        // 1: Start -> Input Dot EOF
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalStart,
                [
                    GrammarSymbol.nonterminalInput,
                    GrammarSymbol.terminalDot,
                    GrammarSymbol.terminalEOF
                ],
                1
            )
        );

        // 2: Input -> Clause
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalInput,
                [GrammarSymbol.nonterminalClause, '#createClause'],
                2
            )
        );

        // 3: Input -> Query
        this.productions.push(
            createProduction(GrammarSymbol.nonterminalInput, [GrammarSymbol.nonterminalQuery], 3)
        );

        // 4: Clause -> LHSGoal ClauseTail
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalClause,
                [GrammarSymbol.nonterminalGoal, GrammarSymbol.nonterminalClauseTail],
                4
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalQuery,
                [
                    GrammarSymbol.terminalInferPred,
                    GrammarSymbol.nonterminalGoal,
                    GrammarSymbol.nonterminalGoalListTail,
                    '#consGoalList'
                ],
                5
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalClauseTail,
                [
                    GrammarSymbol.terminalFrom,
                    GrammarSymbol.nonterminalGoal,
                    GrammarSymbol.nonterminalGoalListTail,
                    '#consGoalList'
                ],
                6
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalClauseTail,
                [GrammarSymbol.Lambda, '#createEmptyGoalList'],
                7
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalGoalListTail,
                [
                    GrammarSymbol.terminalComma,
                    GrammarSymbol.nonterminalGoal,
                    GrammarSymbol.nonterminalGoalListTail,
                    '#consGoalList'
                ],
                8
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalGoalListTail,
                [GrammarSymbol.Lambda, '#createEmptyGoalList'],
                9
            )
        );

        // Goal -> NameNotBeginningWithCapital TailOfGoalOrFunctorExpr
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalGoal,
                [
                    GrammarSymbol.terminalNameNotBeginningWithCapital,
                    GrammarSymbol.nonterminalTailOfGoalOrFunctorExpression,
                    '#createGoal'
                ],
                10
            )
        );

        // TailOfGoalOrFunctorExpr -> Lambda
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalTailOfGoalOrFunctorExpression,
                [GrammarSymbol.Lambda, '#createEmptyExpressionList'],
                11
            )
        );

        // TailOfGoalOrFunctorExpr -> ( ExprList )
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalTailOfGoalOrFunctorExpression,
                [
                    GrammarSymbol.terminalLeftBracket,
                    GrammarSymbol.nonterminalExpression,
                    GrammarSymbol.nonterminalExpressionListTail,
                    GrammarSymbol.terminalRightBracket,
                    '#consExpressionList'
                ],
                12
            )
        );

        // ExprListTail -> Lambda
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpressionListTail,
                [GrammarSymbol.Lambda, '#createEmptyExpressionList'],
                15
            )
        );

        // ExprListTail -> , Expr ExprListTail
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpressionListTail,
                [
                    GrammarSymbol.terminalComma,
                    GrammarSymbol.nonterminalExpression,
                    GrammarSymbol.nonterminalExpressionListTail,
                    '#consExpressionList'
                ],
                16
            )
        );

        // Expr -> IntegerLiteral
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpression,
                [GrammarSymbol.terminalIntegerLiteral],
                17
            )
        );

        // Expr -> Variable
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpression,
                [GrammarSymbol.nonterminalVariable],
                18
            )
        );

        // Expr -> FunctorExpr
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpression,
                [GrammarSymbol.nonterminalFunctorExpression],
                19
            )
        );

        // Variable -> NameBeginningWithCapital
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalVariable,
                [GrammarSymbol.terminalNameBeginningWithCapital, '#createVariable'],
                20
            )
        );

        // FunctorExpr -> NameNotBeginningWithCapital TailOfGoalOrFunctorExpr
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalFunctorExpression,
                [
                    GrammarSymbol.terminalNameNotBeginningWithCapital,
                    GrammarSymbol.nonterminalTailOfGoalOrFunctorExpression,
                    '#createFunctorExpression'
                ],
                21
            )
        );

        // Lists.
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalExpression,
                [GrammarSymbol.nonterminalList],
                22
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalList,
                [
                    GrammarSymbol.terminalLeftSquareBracket,
                    GrammarSymbol.nonterminalListContents,
                    GrammarSymbol.terminalRightSquareBracket
                ],
                23
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalListContents,
                [GrammarSymbol.Lambda, '#createNilFunctor'],
                24
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalListContents,
                [
                    GrammarSymbol.nonterminalExpression,
                    GrammarSymbol.nonterminalListContentsTail,
                    '#createConsFunctor'
                ],
                25
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalListContentsTail,
                [GrammarSymbol.Lambda, '#createNilFunctor'],
                26
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalListContentsTail,
                [
                    GrammarSymbol.terminalComma,
                    GrammarSymbol.nonterminalExpression,
                    GrammarSymbol.nonterminalListContentsTail,
                    '#createConsFunctor'
                ],
                27
            )
        );

        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalListContentsTail,
                [GrammarSymbol.terminalOrBar, GrammarSymbol.nonterminalExpression],
                28
            )
        );

        // // Not symbol: \+
        this.productions.push(
            createProduction(
                GrammarSymbol.nonterminalGoal,
                [GrammarSymbol.terminalNotSymbol, GrammarSymbol.nonterminalGoal, '#not'],
                29
            )
        );

        this.addProduction(GrammarSymbol.nonterminalGoal, [
            GrammarSymbol.nonterminalVariableOrNumericLiteral,
            GrammarSymbol.nonterminalGoalTail1
        ]);

        this.addProduction(GrammarSymbol.nonterminalVariableOrNumericLiteral, [
            GrammarSymbol.nonterminalVariable
        ]);

        this.addProduction(GrammarSymbol.nonterminalVariableOrNumericLiteral, [
            GrammarSymbol.terminalIntegerLiteral
        ]);

        this.addProduction(GrammarSymbol.nonterminalGoalTail1, [
            GrammarSymbol.nonterminalArithmeticComparisonOperator,
            GrammarSymbol.nonterminalVariableOrNumericLiteral,
            '#arithmeticComparison'
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalLessThan
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalGreaterThan
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalLessOrEqual
        ]);
        //
        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalGreaterOrEqual
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalArithmeticEqual
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticComparisonOperator, [
            GrammarSymbol.terminalArithmeticNotEqual
        ]);

        this.addProduction(GrammarSymbol.nonterminalGoalTail1, [
            GrammarSymbol.terminalIs,
            GrammarSymbol.nonterminalVariableOrNumericLiteral,
            GrammarSymbol.nonterminalArithmeticOperator,
            GrammarSymbol.nonterminalVariableOrNumericLiteral,
            '#is'
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticOperator, [
            GrammarSymbol.terminalPlus
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticOperator, [
            GrammarSymbol.terminalMinus
        ]);

        this.addProduction(GrammarSymbol.nonterminalArithmeticOperator, [
            GrammarSymbol.terminalMultiply
        ]);

        // this.addProduction(GrammarSymbol.nonterminalArithmeticOperator, [GrammarSymbol.terminalDivide]);
        //
        // this.addProduction(GrammarSymbol.nonterminalArithmeticOperator, [GrammarSymbol.terminalModulus]);

        // Non-arithmetic operators: Unifiable, NotUnifiable, Equals, NotEqual
        this.addProduction(GrammarSymbol.nonterminalGoalTail1, [
            GrammarSymbol.nonterminalOptr,
            GrammarSymbol.nonterminalVariableOrNumericLiteral,
            '#nonArithmeticOperator'
        ]);

        this.addProduction(GrammarSymbol.nonterminalOptr, [GrammarSymbol.terminalUnifiable]);

        this.addProduction(GrammarSymbol.nonterminalOptr, [GrammarSymbol.terminalNotUnifiable]);

        this.addProduction(GrammarSymbol.nonterminalOptr, [GrammarSymbol.terminalEquals]);

        this.addProduction(GrammarSymbol.nonterminalOptr, [GrammarSymbol.terminalNotEqual]);
    }

    // // AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Is });
    // // //AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Not });
    // // AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_ComparisonOperator });
    // // AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_OpType_EqualOrUnifiable });

    // // #if DEAD_CODE
    // // // We cannot add a production that says N_Functor := T_Minus, because of the unary minus operator.
    // // AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Plus });
    // // AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_OpType_Multiply });
    // // //AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Mod });
    // // #endif

    // // AddProduction(Symbol.N_Expression, new List<object>() {
    // // Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_IfThenElseTail, Symbol.T_RightBracket, Symbol.N_ArithmeticAndComparisonTail });
    // // AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_IntegerLiteral, Symbol.N_ExpressionPartFollowingAnInteger });
    // // AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_FloatLiteral, Symbol.N_ExpressionPartFollowingAnInteger });
    // // AddProduction(Symbol.N_Expression, new List<object>() {
    // // Symbol.T_NameBeginningWithCapital, Symbol.N_ExpressionPartFollowingAnUpperCaseID });
    // // AddProduction(Symbol.N_Expression, new List<object>() {
    // // Symbol.N_Functor, Symbol.N_ExpressionPartFollowingALowerCaseID });
    // // AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_Minus, Symbol.N_ExpressionPartFollowingAMinus });
    // // AddProduction(Symbol.N_ModExpression, new List<object>() {
    // // Symbol.T_Mod, Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket,
    // // "#arithExpr_Prefix" });
    // // AddProduction(Symbol.N_IfThenElseTail, new List<object>() { Symbol.N_Sequence }); // This can produce Lambda.
    // // AddProduction(Symbol.N_IfThenElseTail, new List<object>() {
    // // Symbol.T_IfThen, Symbol.N_Goal, Symbol.T_Colon, Symbol.N_Goal, "#ifThenElse" });
    // // AddProduction(Symbol.N_IfThenElseTail, new List<object>() {

    // // // Sequences.

    // // ...

    public get languageName(): string {
        return 'Prolog';
    }

    // public override get defaultParser(): ParserSelector {
    //     return ParserSelector.SLR1;
    // }

    public executeSemanticAction(semanticStack: SemanticStackType, action: string): void {
        const gs = LanguageSelector.Prolog2;

        let str: string;
        let goal: PrologGoal;
        let goalList: PrologGoal[];
        let expr: IPrologExpression;
        let expr2: IPrologExpression;
        let expr3: IPrologExpression;
        let exprList: IPrologExpression[];
        // let functor: PrologFunctor;
        // let variable: PrologVariable;
        // let variableList: PrologVariable[];
        let functorExpr: PrologFunctorExpression;
        // let functorExpr2: PrologFunctorExpression;
        // // let functorExpr3: PrologFunctorExpression;
        // let clause: PrologClause;

        switch (action) {
            case '#createClause':
                goalList = semanticStack.pop() as PrologGoal[];
                goal = semanticStack.pop() as PrologGoal;
                semanticStack.push(new PrologClause(goal, goalList));
                break;

            case '#consGoalList':
                goalList = semanticStack.pop() as PrologGoal[];
                goal = semanticStack.pop() as PrologGoal;
                goalList.unshift(goal);
                semanticStack.push(goalList);
                break;

            case '#createEmptyGoalList':
                goalList = [];
                semanticStack.push(goalList);
                break;

            case '#createGoal':
                exprList = semanticStack.pop() as IPrologExpression[];
                str = semanticStack.pop() as string;
                // console.log('#createGoal: Goal name is', str);
                semanticStack.push(new PrologGoal(gs, str, exprList));
                break;

            case '#createEmptyExpressionList':
                exprList = [];
                semanticStack.push(exprList);
                break;

            case '#consExpressionList':
                exprList = semanticStack.pop() as IPrologExpression[];
                expr = semanticStack.pop() as IPrologExpression;
                exprList.unshift(expr);
                semanticStack.push(exprList);
                break;

            case '#createVariable':
                str = semanticStack.pop() as string;
                semanticStack.push(createPrologVariable(str));
                break;

            case '#createFunctorExpression':
                exprList = semanticStack.pop() as IPrologExpression[];
                str = semanticStack.pop() as string;
                semanticStack.push(new PrologFunctorExpression(gs, str, exprList));
                break;

            // **** BEGIN - For lists

            case '#createNilFunctor':
                semanticStack.push(new PrologFunctorExpression(gs, '[]', []));
                break;

            case '#createConsFunctor':
                expr2 = semanticStack.pop() as IPrologExpression;
                expr = semanticStack.pop() as IPrologExpression;
                semanticStack.push(new PrologFunctorExpression(gs, '.', [expr, expr2]));
                break;

            // **** END - For lists

            case '#not': // #metaPredicateWithGoal
                goal = semanticStack.pop() as PrologGoal;
                functorExpr = createFunctorExpressionFromGoal(goal);
                semanticStack.push(new PrologFunctorExpression(gs, 'not', [functorExpr]));
                break;

            case '#arithmeticComparison':
                expr2 = semanticStack.pop() as IPrologExpression;
                str = semanticStack.pop() as string; // Infix comparison operator: < > ==
                expr = semanticStack.pop() as IPrologExpression;
                semanticStack.push(new PrologGoal(gs, str, [expr, expr2]));
                break;

            case '#is':
                expr3 = semanticStack.pop() as IPrologExpression;
                str = semanticStack.pop() as string; // Infix operator: +, -, *, etc.
                expr2 = semanticStack.pop() as IPrologExpression;
                expr = semanticStack.pop() as IPrologExpression;
                // semanticStack.push(new PrologGoal(gs, str, [expr, expr2, expr3]));
                semanticStack.push(new PrologGoal(gs, str, [expr2, expr3, expr]));
                break;

            case '#nonArithmeticOperator': // Identical to '#arithmeticComparison'
                expr2 = semanticStack.pop() as IPrologExpression;
                str = semanticStack.pop() as string;
                expr = semanticStack.pop() as IPrologExpression;
                semanticStack.push(new PrologGoal(gs, str, [expr, expr2]));
                break;

            // // case "#arithExpr_Prefix":   // The same as #infix, except for the order of the items on the stack.
            // // expr2 = (IPrologExpression)semanticStack.Pop();
            // // expr = (IPrologExpression)semanticStack.Pop();
            // // str = (string)semanticStack.Pop();
            // // functor = new PrologFunctor(str);
            // // exprList = new List<IPrologExpression>() { expr, expr2 };
            // // semanticStack.Push(new PrologFunctorExpression(gs, functor, exprList));
            // // break;

            // // case "#unaryMinus":
            // // expr2 = (IPrologExpression)semanticStack.Pop();
            // // str = (string)semanticStack.Pop(); // Remove the - from the stack.
            // // expr = new PrologIntegerLiteral(0);
            // // exprList = new List<IPrologExpression>() { expr, expr2 };
            // // functor = new PrologFunctor(str);
            // // semanticStack.Push(new PrologFunctorExpression(gs, functor, exprList));
            // // break;

            // // case "#consSeq":
            // // expr2 = (IPrologExpression)semanticStack.Pop();
            // // expr = (IPrologExpression)semanticStack.Pop();
            // // functor = new PrologFunctor("consSeq");
            // // semanticStack.Push(new PrologFunctorExpression(gs, functor, new List<IPrologExpression>() { expr, expr2 }));
            // // break;

            // // case "#goalDisjunction":
            // // functorExpr2 = (PrologFunctorExpression)semanticStack.Pop();
            // // functorExpr = (PrologFunctorExpression)semanticStack.Pop();
            // // functor = new PrologFunctor("goal_disjunction");
            // // semanticStack.Push(new PrologFunctorExpression(gs, functor, new List<IPrologExpression>() { functorExpr, functorExpr2 }));
            // // break;

            // // case "#ifThenElse":
            // // functorExpr3 = (PrologFunctorExpression)semanticStack.Pop();
            // // functorExpr2 = (PrologFunctorExpression)semanticStack.Pop();
            // // functorExpr = PopAndConvertToFunctorExpression(semanticStack, action);
            // // functor = new PrologFunctor("if_then_else");
            // // semanticStack.Push(new PrologFunctorExpression(gs, functor,
            // // new List<IPrologExpression>() { functorExpr, functorExpr2, functorExpr3 }));
            // // break;

            // // case "#DCGClause":
            // // // The #DCGClause semantic action will add the extra arguments to the goals in order to support the difference list mechanism.
            // // // It also converts lists into "unifiable" predicates.
            // // exprList = (List<IPrologExpression>)semanticStack.Pop();
            // // functorExpr = (PrologFunctorExpression)semanticStack.Pop(); // The LHS of the clause.
            // // semanticStack.Push(GenerateDCGClause(functorExpr, exprList));
            // // break;

            // // case "#DCGEmptyObjectList":
            // // semanticStack.Push(new List<IPrologExpression>());
            // // break;

            // // case "#DCGObjectList":
            // // exprList = (List<IPrologExpression>)semanticStack.Pop();
            // // expr = (IPrologExpression)semanticStack.Pop();
            // // exprList.Insert(0, expr);
            // // semanticStack.Push(exprList);
            // // break;

            // // case "#markGoalAsNonDCG":
            // // functorExpr = (PrologFunctorExpression)semanticStack.Peek();
            // // functorExpr.DCGDoNotAddExtraArguments = true;
            // // break;

            // // case "#createCaretList":
            // // functorExpr = (PrologFunctorExpression)semanticStack.Pop();
            // // variableList = (List<PrologVariable>)semanticStack.Pop();
            // // semanticStack.Push(new CaretList(variableList, functorExpr));
            // // break;

            default:
                throw new ArgumentException(`Unrecognized semantic action: '${action}'`, 'action');
        }
    }

    public override tokenToSymbol(token: IToken): GrammarSymbol {
        const tokenValueAsString: string = token.tokenValue as string;

        switch (token.tokenType) {
            case LexicalState.tokenEOF:
                return GrammarSymbol.terminalEOF;
            case LexicalState.tokenIdent:
            case LexicalState.tokenExclamation: // The cut.
                switch (tokenValueAsString) {
                    case '?-':
                        return GrammarSymbol.terminalInferPred;
                    case ':-':
                        return GrammarSymbol.terminalFrom;
                    case 'is':
                        return GrammarSymbol.terminalIs;
                    case '+':
                        return GrammarSymbol.terminalPlus;
                    case '-':
                        return GrammarSymbol.terminalMinus;
                    case '*':
                        return GrammarSymbol.terminalMultiply;
                    case '/':
                        return GrammarSymbol.terminalDivide;
                    // case 'mod':
                    //     return GrammarSymbol.terminalMod;
                    case '<':
                        return GrammarSymbol.terminalLessThan;
                    case '>':
                        return GrammarSymbol.terminalGreaterThan;
                    case '=<':
                        return GrammarSymbol.terminalLessOrEqual; // Not <=.  See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21
                    case '>=':
                        return GrammarSymbol.terminalGreaterOrEqual;
                    case '\\+':
                        return GrammarSymbol.terminalNotSymbol;
                    case '->':
                        return GrammarSymbol.terminalIfThen;
                    case ':':
                        return GrammarSymbol.terminalColon;
                    case '=':
                        return GrammarSymbol.terminalUnifiable;
                    case '\\=':
                        return GrammarSymbol.terminalNotUnifiable;

                    case '==':
                        return GrammarSymbol.terminalEquals;
                    case '\\==':
                        return GrammarSymbol.terminalNotEqual;
                    case '=:=':
                        return GrammarSymbol.terminalArithmeticEqual; // See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21
                    case '=\\=':
                        return GrammarSymbol.terminalArithmeticNotEqual;

                    case '-->':
                        return GrammarSymbol.terminalDCGArrow;
                    case '=..':
                        return GrammarSymbol.terminalUniv;
                    case '^':
                        return GrammarSymbol.terminalCaret;
                    default:
                        break;
                }

                const firstChar = tokenValueAsString.substring(0, 1);

                // The following supports non-binding variables such as _ and _Foo .
                // See http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_3.html
                // TODO: Should we require the second character (if it exists) to be a capital letter if the first is an underscore?

                if (firstChar.toLowerCase() === firstChar && !tokenValueAsString.startsWith('_')) {
                    // This case includes non-binding variables (i.e. variable names that start with _)
                    // as well as tokenExclamation (the cut).
                    return GrammarSymbol.terminalNameNotBeginningWithCapital;
                } else {
                    return GrammarSymbol.terminalNameBeginningWithCapital;
                }

            case LexicalState.tokenIntLit:
                return GrammarSymbol.terminalIntegerLiteral;

            // HACK version 2 : ThAW 2020-01-06 : The value in an IntegerLiteral can be int or float.
            // In the future, we will need to properly support FloatLiterals
            // and distinguish them from IntegerLiterals.
            // case LexicalState.tokenFltLit: return Symbol.terminalFloatLiteral;
            case LexicalState.tokenFltLit:
                return GrammarSymbol.terminalIntegerLiteral;

            case LexicalState.tokenStrLit:
                return GrammarSymbol.terminalStringLiteral;
            // case LexicalState.tokenIdent: return Symbol.terminalID;
            case LexicalState.tokenLeftBracket:
                return GrammarSymbol.terminalLeftBracket;
            case LexicalState.tokenRightBracket:
                return GrammarSymbol.terminalRightBracket;
            case LexicalState.tokenLeftSquareBracket:
                return GrammarSymbol.terminalLeftSquareBracket;
            case LexicalState.tokenRightSquareBracket:
                return GrammarSymbol.terminalRightSquareBracket;
            case LexicalState.tokenComma:
                return GrammarSymbol.terminalComma;
            case LexicalState.tokenDot:
                return GrammarSymbol.terminalDot;
            case LexicalState.tokenSemicolon:
                return GrammarSymbol.terminalSemicolon;
            case LexicalState.tokenOrBar:
                return GrammarSymbol.terminalOrBar;
            case LexicalState.tokenBackslashPlus:
                return GrammarSymbol.terminalNotSymbol;

            // case LexicalState.tokenStrLit2: return Symbol.T_NameNotBeginningWithCapital; // The contents of a single-quoted string.
            // case LexicalState.tokenLeftCurlyBrace: return Symbol.T_LeftCurlyBrace;
            // case LexicalState.tokenRightCurlyBrace: return Symbol.T_RightCurlyBrace;
            // case LexicalState.tokenColon: return Symbol.T_Colon;
            // case LexicalState.tokenLess: return Symbol.T_LessThan;
            case LexicalState.tokenLess:
                return GrammarSymbol.terminalLessThan;
            // case LexicalState.tokenEqualLessThan: return Symbol.T_LessEqual;
            case LexicalState.tokenGreater:
                return GrammarSymbol.terminalGreaterThan;
            case LexicalState.tokenGreaterEqual:
                return GrammarSymbol.terminalGreaterOrEqual;
            // case LexicalState.tokenBackslashEqual: return Symbol.T_NotUnifiable;
            // case LexicalState.tokenEqualEqual: return Symbol.T_Equals;
            // case LexicalState.tokenEqualEqual:
            //     return GrammarSymbol.terminalEquals;
            // case LexicalState.tokenBackslashEqualEqual: return Symbol.T_NotEqual;
            // case LexicalState.tokenEqualColonEqual: return Symbol.T_ArithmeticEquals;
            case LexicalState.tokenEqualColonEqual:
                return GrammarSymbol.terminalEquals;
            // case LexicalState.tokenEqualBackslashEqual: return Symbol.T_ArithmeticNotEquals;
            // case LexicalState.tokenEqualBackslashEqual:
            //     return GrammarSymbol.terminalNotEqual;
            // case LexicalState.tokenMinusMinusGreaterThan: return Symbol.T_DCGArrow;
            // case LexicalState.tokenEqualDotDot: return Symbol.T_Univ;
            case LexicalState.tokenPlus:
                return GrammarSymbol.terminalPlus;
            case LexicalState.tokenMinus:
                return GrammarSymbol.terminalMinus;
            case LexicalState.tokenMult:
                return GrammarSymbol.terminalMultiply;
            // case LexicalState.tokenDiv: return Symbol.T_Divide;
            case LexicalState.tokenEqual:
                return GrammarSymbol.terminalUnifiable; // Unifiable
            // case LexicalState.tokenArrow: return Symbol.T_IfThen;
            // case LexicalState.tokenCaret: return Symbol.T_Caret;
            default:
                break;
        }

        throw new GrammarException(
            `No grammar symbol matches token ${token.tokenType} ${
                LexicalState[token.tokenType]
            } (value '${token.tokenValue}')`,
            token.line,
            token.column
        );
    }

    public override pushTokenOntoSemanticStack(
        semanticStack: SemanticStackType,
        tokenAsSymbol: GrammarSymbol,
        token: IToken
    ): void {
        const value = token.tokenValue;

        switch (tokenAsSymbol) {
            case GrammarSymbol.terminalIntegerLiteral:
                // semanticStack.push(new PrologIntegerLiteral(value as number));
                semanticStack.push(new PrologIntegerLiteral(token.getValueAsNumber()));
                break;

            case GrammarSymbol.terminalFloatLiteral:
                // semanticStack.push(new PrologFloatLiteral(value as number));
                semanticStack.push(new PrologFloatLiteral(token.getValueAsNumber()));
                break;

            case GrammarSymbol.terminalNameBeginningWithCapital:
            case GrammarSymbol.terminalNameNotBeginningWithCapital:
            // case GrammarSymbol.terminalIs:
            case GrammarSymbol.terminalPlus:
            case GrammarSymbol.terminalMinus:
            case GrammarSymbol.terminalMultiply:
            case GrammarSymbol.terminalLessThan:
            case GrammarSymbol.terminalGreaterThan:
            case GrammarSymbol.terminalLessOrEqual:
            case GrammarSymbol.terminalGreaterOrEqual:
            case GrammarSymbol.terminalArithmeticEqual:
            case GrammarSymbol.terminalArithmeticNotEqual:
                if (typeof value !== 'string') {
                    throw new Error('Oh bugger.');
                }

                semanticStack.push(value as string); // value is really a string; it must be converted to a Prolog domain model type later.
                break;

            // case Symbol.terminalStringLiteral:
            //     // semanticStack.push(PrologGlobalInfo.CSharpStringToPrologCodeList((string)value));
            //     semanticStack.push(value);
            //     break;

            // case Symbol.T_Plus:
            // case Symbol.T_Divide:
            // case Symbol.T_Mod:
            // case Symbol.T_LessThan:
            // case Symbol.T_GreaterThan:
            // case Symbol.T_LessEqual:
            // case Symbol.T_GreaterEqual:
            // case Symbol.T_ArithmeticEquals:
            // case Symbol.T_ArithmeticNotEquals:
            // case Symbol.T_Assign:   // Unifiable
            // case Symbol.T_Equals:
            // case Symbol.T_NotEqual:
            // case Symbol.T_NotUnifiable:
            // case Symbol.T_Univ:
            // semanticStack.push(value);
            // break;

            default:
                break;
        }
    }
}

// namespace Inference.Interpreter.Prolog
// {
// public class PrologGrammar2_LL1 : GrammarBase
// {
// private readonly GrammarSelector gs = GrammarSelector.Prolog2;

// public PrologGrammar2_LL1()
// : base(Symbol.N_Start)
// {
// Terminals.UnionWith(new HashSet<Symbol>() { ... });

// NonTerminals.UnionWith(new HashSet<Symbol>() { ... });

// AddProduction(Symbol.N_Clause, new List<object>() { Symbol.N_LHSGoal, Symbol.N_ClauseTail });
// AddProduction(Symbol.N_LHSGoal, new List<object>() { Symbol.T_NameBeginningWithCapital, Symbol.N_LHSGoalTail });
// AddProduction(Symbol.N_LHSGoal, new List<object>() { Symbol.N_Functor, Symbol.N_LHSGoalTail });
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_NameNotBeginningWithCapital });
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Is });
// //AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Not });
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_ComparisonOperator });
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_OpType_EqualOrUnifiable });
// #if DEAD_CODE
// // We cannot add a production that says N_Functor := T_Minus, because of the unary minus operator.
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Plus });
// AddProduction(Symbol.N_Functor, new List<object>() { Symbol.N_OpType_Multiply });
// //AddProduction(Symbol.N_Functor, new List<object>() { Symbol.T_Mod });
// #endif
// AddProduction(Symbol.N_LHSGoalTail, new List<object>() { Symbol.Lambda, "#functorExpressionNoArgs" });
// AddProduction(Symbol.N_LHSGoalTail, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_ExpressionList, Symbol.T_RightBracket, "#functorExpression2" });
// AddProduction(Symbol.N_ExpressionList, new List<object>() { Symbol.Lambda, "#emptyExprList" });
// AddProduction(Symbol.N_ExpressionList, new List<object>() {
// Symbol.T_Comma, Symbol.N_Expression, Symbol.N_ExpressionList, "#exprList" });

// AddProduction(Symbol.N_ClauseTail, new List<object>() {
// Symbol.T_From, Symbol.N_GoalWithPossibleDisjunctiveTail, Symbol.N_GoalList, "#cons", "#clauseAsFunctor" });
// AddProduction(Symbol.N_ClauseTail, new List<object>() { Symbol.Lambda, "#nil", "#clauseAsFunctor" });
// AddProduction(Symbol.N_GoalList, new List<object>() {
// Symbol.T_Comma, Symbol.N_GoalWithPossibleDisjunctiveTail, Symbol.N_GoalList, "#cons" });
// AddProduction(Symbol.N_GoalList, new List<object>() { Symbol.Lambda, "#nil" });
// AddProduction(Symbol.N_Query, new List<object>() {
// Symbol.T_InferPred, Symbol.N_GoalWithPossibleDisjunctiveTail, Symbol.N_GoalList, "#cons" });
// AddProduction(Symbol.N_GoalWithPossibleDisjunctiveTail, new List<object>() {
// Symbol.N_Goal, Symbol.N_PossibleDisjunctiveTail });
// AddProduction(Symbol.N_PossibleDisjunctiveTail, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_PossibleDisjunctiveTail, new List<object>() {
// Symbol.T_Semicolon, Symbol.N_Goal, Symbol.N_PossibleDisjunctiveTail, "#goalDisjunction" });

// // ThAW 2014/03/18 : This is where the fun begins.
// AddProduction(Symbol.N_Goal, new List<object>() { Symbol.N_Expression, "#convertExpressionToFunctorExpression" });

// AddProduction(Symbol.N_Expression, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_IfThenElseTail, Symbol.T_RightBracket, Symbol.N_ArithmeticAndComparisonTail });
// AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_IntegerLiteral, Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_FloatLiteral, Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_Expression, new List<object>() {
// Symbol.T_NameBeginningWithCapital, Symbol.N_ExpressionPartFollowingAnUpperCaseID });
// AddProduction(Symbol.N_Expression, new List<object>() {
// Symbol.N_Functor, Symbol.N_ExpressionPartFollowingALowerCaseID });
// AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_Minus, Symbol.N_ExpressionPartFollowingAMinus });
// AddProduction(Symbol.N_ModExpression, new List<object>() {
// Symbol.T_Mod, Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket,
// "#arithExpr_Prefix" });
// AddProduction(Symbol.N_IfThenElseTail, new List<object>() { Symbol.N_Sequence }); // This can produce Lambda.
// AddProduction(Symbol.N_IfThenElseTail, new List<object>() {
// Symbol.T_IfThen, Symbol.N_Goal, Symbol.T_Colon, Symbol.N_Goal, "#ifThenElse" });
// AddProduction(Symbol.N_IfThenElseTail, new List<object>() {
// Symbol.T_From, Symbol.N_GoalWithPossibleDisjunctiveTail, Symbol.N_GoalList, "#cons", "#clauseAsFunctor" });

// // Sequences.
// AddProduction(Symbol.N_Sequence, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_Sequence, new List<object>() { Symbol.T_Comma, Symbol.N_Expression, Symbol.N_Sequence, "#consSeq" });

// AddProduction(Symbol.N_InfixNonArithmeticPredicateTail, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_InfixNonArithmeticPredicateTail, new List<object>() {
// Symbol.N_OpType_EqualOrUnifiable, Symbol.N_Expression, "#infix" });

// AddProduction(Symbol.N_InfixPredicateTail, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_InfixPredicateTail, new List<object>() {
// Symbol.N_OpType_EqualOrUnifiable, Symbol.N_Expression, "#infix" });
// AddProduction(Symbol.N_InfixPredicateTail, new List<object>() {
// Symbol.N_ComparisonOperator, Symbol.N_Expression, "#infix" }); // N_Expression here may be e.g. +(2, 2)

// AddProduction(Symbol.N_ArithmeticAndComparisonTail, new List<object>() { Symbol.N_InfixPredicateTail });
// AddProduction(Symbol.N_ArithmeticAndComparisonTail, new List<object>() {
// Symbol.N_OpType_Add, Symbol.N_ArithmeticExpression2, "#infix", Symbol.N_ArithmeticExpression1Foo, Symbol.N_InfixPredicateTail });
// AddProduction(Symbol.N_ArithmeticAndComparisonTail, new List<object>() {
// Symbol.N_OpType_Multiply, Symbol.N_ArithmeticExpression3, "#infix", Symbol.N_ArithmeticExpression2Foo, Symbol.N_ArithmeticExpression1Foo,
// Symbol.N_InfixPredicateTail });

// // Lists.
// ...
// AddProduction(Symbol.N_ListTail, new List<object>() {
// Symbol.N_OpType_EqualOrUnifiable, Symbol.N_Expression, "#infix" });
// AddProduction(Symbol.N_Expression, new List<object>() {
// Symbol.T_Dot, Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.T_Comma, Symbol.N_Expression, Symbol.T_RightBracket, "#cons",
// Symbol.N_InfixNonArithmeticPredicateTail });

// AddProduction(Symbol.N_ExpressionPartFollowingAnInteger, new List<object>() { Symbol.N_ArithmeticAndComparisonTail });
// AddProduction(Symbol.N_ExpressionPartFollowingAnInteger, new List<object>() {
// Symbol.T_Is, Symbol.N_Expression, "#infix" /* "#is" */ });

// AddProduction(Symbol.N_ExpressionPartFollowingAnUpperCaseID, new List<object>() {
// "#variable", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAnUpperCaseID , new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_ExpressionList, Symbol.T_RightBracket, "#functorExpression2" });
// AddProduction(Symbol.N_ExpressionPartFollowingALowerCaseID, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_ExpressionList, Symbol.T_RightBracket,
// "#functorExpression2", // This functor may be converted to a goal later.
// Symbol.N_ExpressionPartFollowingALowerCaseIDWithParams });
// AddProduction(Symbol.N_ExpressionPartFollowingALowerCaseID, new List<object>() {
// "#functorExpressionNoArgs", Symbol.N_ExpressionPartFollowingALowerCaseIDWithParams });
// AddProduction(Symbol.N_ExpressionPartFollowingALowerCaseIDWithParams, new List<object>() { Symbol.Lambda });

// AddProduction(Symbol.N_ExpressionPartFollowingALowerCaseIDWithParams, new List<object>() {
// Symbol.N_OpType_EqualOrUnifiable, Symbol.N_Expression, "#infix" });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.T_IntegerLiteral, "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.T_FloatLiteral, "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.T_NameBeginningWithCapital, "#variable", "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.N_PrefixArithmeticExpression, "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.N_PrefixMinusExpression, "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });
// AddProduction(Symbol.N_ExpressionPartFollowingAMinus, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.N_ExpressionPartFollowingMinusLBracketExpr });
// AddProduction(Symbol.N_ExpressionPartFollowingMinusLBracketExpr, new List<object>() {
// Symbol.T_RightBracket, "#unaryMinus", Symbol.N_ExpressionPartFollowingAnInteger });

// // Handle + and -
// // Remember that for LL(1) grammars, semantic actions don't have to be placed at the end of the production (unlike with *LR(1) grammars).
// // See Fischer & LeBlanc page 239 for the Micro grammar with semantic action symbols.
// AddProduction(Symbol.N_ArithmeticExpression1, new List<object>() {
// Symbol.N_ArithmeticExpression2, Symbol.N_ArithmeticExpression1Foo });
// AddProduction(Symbol.N_ArithmeticExpression1Foo, new List<object>() {
// Symbol.N_OpType_Add, Symbol.N_ArithmeticExpression2, "#infix", Symbol.N_ArithmeticExpression1Foo });
// AddProduction(Symbol.N_ArithmeticExpression1Foo, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_OpType_Add, new List<object>() { Symbol.T_Plus });
// AddProduction(Symbol.N_OpType_Add, new List<object>() { Symbol.T_Minus });
// // Handle * and /
// AddProduction(Symbol.N_ArithmeticExpression2, new List<object>() {
// Symbol.N_ArithmeticExpression3, Symbol.N_ArithmeticExpression2Foo });
// AddProduction(Symbol.N_ArithmeticExpression2Foo, new List<object>() {
// Symbol.N_OpType_Multiply, Symbol.N_ArithmeticExpression3, "#infix", Symbol.N_ArithmeticExpression2Foo });
// AddProduction(Symbol.N_ArithmeticExpression2Foo, new List<object>() { Symbol.Lambda });
// AddProduction(Symbol.N_OpType_Multiply, new List<object>() { Symbol.T_Multiply });
// AddProduction(Symbol.N_OpType_Multiply, new List<object>() { Symbol.T_Divide });
// AddProduction(Symbol.N_ArithmeticExpression3, new List<object>() { Symbol.N_ArithmeticExpression4 });
// AddProduction(Symbol.N_ArithmeticExpression3, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket });
// AddProduction(Symbol.N_ArithmeticExpression3, new List<object>() {
// Symbol.T_Minus, Symbol.N_ArithmeticExpression3Minus });
// AddProduction(Symbol.N_PrefixMinusExpression, new List<object>() {
// Symbol.T_Minus, Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket,
// "#arithExpr_Prefix" });
// AddProduction(Symbol.N_ArithmeticExpression3Minus, new List<object>() {
// Symbol.N_PrefixMinusExpression, "#unaryMinus" });
// AddProduction(Symbol.N_ArithmeticExpression3Minus, new List<object>() { Symbol.N_ArithmeticExpression4, "#unaryMinus" });
// AddProduction(Symbol.N_ArithmeticExpression3Minus, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.N_ArithmeticExpression3MinusLBrackArithExpr });
// AddProduction(Symbol.N_ArithmeticExpression3MinusLBrackArithExpr, new List<object>() {
// Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket, "#arithExpr_Prefix" });
// AddProduction(Symbol.N_ArithmeticExpression3MinusLBrackArithExpr, new List<object>() {
// Symbol.T_RightBracket, "#unaryMinus" });
// // Expressions represented by N_ArithmeticExpression4 do not rely on order of operations to be evaluated
// // (except possibly for the arguments to the prefix-operator expressions).
// AddProduction(Symbol.N_ArithmeticExpression4, new List<object>() { Symbol.N_PrefixArithmeticExpression });
// AddProduction(Symbol.N_ArithmeticExpression4, new List<object>() { Symbol.N_NumberOrVariableExpression });
// AddProduction(Symbol.N_NumberOrVariableExpression, new List<object>() { Symbol.T_IntegerLiteral });
// AddProduction(Symbol.N_NumberOrVariableExpression, new List<object>() { Symbol.T_FloatLiteral });
// DONE: AddProduction(Symbol.N_NumberOrVariableExpression, new List<object>() { Symbol.T_NameBeginningWithCapital, "#variable" });

// // Prefix usages of operators that are usually infix: "is", arithmetic operators, and arithmetic comparison operators.
// // is :
// //AddProduction(Symbol.N_Expression, new List<object>() {
// //    Symbol.T_Is, Symbol.T_LeftBracket, Symbol.N_NumberOrVariableExpression, Symbol.T_Comma, Symbol.N_ArithmeticExpression1,
// //    Symbol.T_RightBracket, "#is" });
// // Arithmetic operators:
// AddProduction(Symbol.N_Expression, new List<object>() { Symbol.N_PrefixArithmeticExpression, Symbol.N_ArithmeticAndComparisonTail });
// #if !DEAD_CODE
// AddProduction(Symbol.N_PrefixArithmeticExpression, new List<object>() {
// Symbol.T_Plus, Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket,
// "#arithExpr_Prefix" });
// AddProduction(Symbol.N_PrefixArithmeticExpression, new List<object>() {
// Symbol.N_OpType_Multiply, Symbol.T_LeftBracket, Symbol.N_ArithmeticExpression1, Symbol.T_Comma, Symbol.N_ArithmeticExpression1,
// Symbol.T_RightBracket, "#arithExpr_Prefix" });
// #endif
// AddProduction(Symbol.N_PrefixArithmeticExpression, new List<object>() { Symbol.N_ModExpression });
// AddProduction(Symbol.N_ExpressionPartFollowingMinusLBracketExpr, new List<object>() {
// Symbol.T_Comma, Symbol.N_ArithmeticExpression1, Symbol.T_RightBracket, "#arithExpr_Prefix", Symbol.N_ArithmeticAndComparisonTail });

// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_LessThan });
// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_GreaterThan });
// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_LessEqual });
// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_GreaterEqual });
// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_ArithmeticEquals });
// AddProduction(Symbol.N_ComparisonOperator, new List<object>() { Symbol.T_ArithmeticNotEquals });

// AddProduction(Symbol.N_OpType_EqualOrUnifiable, new List<object>() { Symbol.T_Assign });        // = (unification)
// AddProduction(Symbol.N_OpType_EqualOrUnifiable, new List<object>() { Symbol.T_NotUnifiable });  // \=
// AddProduction(Symbol.N_OpType_EqualOrUnifiable, new List<object>() { Symbol.T_Equals });        // ==
// AddProduction(Symbol.N_OpType_EqualOrUnifiable, new List<object>() { Symbol.T_NotEqual });      // \==
// AddProduction(Symbol.N_OpType_EqualOrUnifiable, new List<object>() { Symbol.T_Univ });          // =..

// // String literals.
// AddProduction(Symbol.N_Expression, new List<object>() { Symbol.T_StringLiteral });

// // Definite Clause Grammar support.
// // See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlch7
// // See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlch8
// // The #DCGClause semantic action will add the extra arguments to the goals in order to support the difference list mechanism.
// // It also converts lists into "unifies-with" predicates.
// AddProduction(Symbol.N_ClauseTail, new List<object>() {
// Symbol.T_DCGArrow, Symbol.N_DCGRHSGoal, Symbol.N_DCGRHSGoalList, "#DCGObjectList", "#DCGClause" });
// AddProduction(Symbol.N_DCGRHSGoalList, new List<object>() { Symbol.Lambda, "#DCGEmptyObjectList" });
// AddProduction(Symbol.N_DCGRHSGoalList, new List<object>() {
// Symbol.T_Comma, Symbol.N_DCGRHSGoal, Symbol.N_DCGRHSGoalList, "#DCGObjectList" });
// AddProduction(Symbol.N_DCGRHSGoal, new List<object>() { Symbol.N_LHSGoal });
// AddProduction(Symbol.N_DCGRHSGoal, new List<object>() { Symbol.N_List });
// AddProduction(Symbol.N_DCGRHSGoal, new List<object>() {
// Symbol.T_LeftCurlyBrace, Symbol.N_Goal, Symbol.T_RightCurlyBrace, "#markGoalAsNonDCG" });

// // Caret list support for bagof/3 and setof/3:
// AddProduction(Symbol.N_ExpressionPartFollowingAnUpperCaseID, new List<object>() { Symbol.T_Caret, "#createVariableList", Symbol.N_CaretTail });
// AddProduction(Symbol.N_CaretTail, new List<object>() { Symbol.N_Functor,
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_ExpressionList, Symbol.T_RightBracket, "#functorExpression2", "#createCaretList" });
// AddProduction(Symbol.N_CaretTail, new List<object>() { Symbol.T_NameBeginningWithCapital, Symbol.N_CaretTail2 });
// // Note: Functors aren't supposed to begin with a capital letter, but this functor will be converted to a goal.
// AddProduction(Symbol.N_CaretTail2, new List<object>() {
// Symbol.T_LeftBracket, Symbol.N_Expression, Symbol.N_ExpressionList, Symbol.T_RightBracket, "#functorExpression2", "#createCaretList" });
// AddProduction(Symbol.N_CaretTail2, new List<object>() { Symbol.T_Caret, "#appendToVariableList", Symbol.N_CaretTail });
// }

// private static PrologVariable GenerateNewVariable()
// {
// return new PrologVariable(string.Format("Var{0}", Guid.NewGuid()));
// }

// public static PrologFunctorExpression GenerateDCGClause(PrologFunctorExpression lhsGoal, List<IPrologExpression> rhsExprList)
// {
// var rhsGoalList = new List<IPrologExpression>();

// // We need a way to generate new variables that do not already occur in lhsGoal or objList.
// var variable1 = GenerateNewVariable();
// var variable2 = variable1;

// for each (var rhsExpr in rhsExprList)
// {
// var variable3 = GenerateNewVariable();

// var rhsGoal = rhsExpr as PrologFunctorExpression;

// if (rhsGoal == null)
// {
// throw new Exception("GenerateDCGClause() : obj is not a functor expression.");
// }
// else if (rhsGoal.Name == "." || rhsGoal.Name == "[]")
// {
// // Assume that obj is a list.
// var objAsList = rhsGoal; // (PrologFunctorExpression)obj;
// var rhsGoalParam1 = variable2;
// IPrologExpression rhsGoalParam2 = objAsList;
// PrologFunctorExpression parentConsCell = null;

// for (; ; )
// {

// if (objAsList.Name == "[]" && objAsList.ExpressionList.Count == 0)
// {

// if (parentConsCell != null)
// {
// parentConsCell.ExpressionList[1] = variable3;
// }
// else
// {
// rhsGoalParam2 = variable3;
// }

// break;
// }
// else if (objAsList.Name == "." && objAsList.ExpressionList.Count == 2)
// {
// parentConsCell = objAsList;
// objAsList = (PrologFunctorExpression)objAsList.ExpressionList[1];
// }
// else
// {
// throw new Exception("GenerateDCGClause() : Non-list found where list expected.");
// }
// }

// //rhsGoal = new PrologGoal(gs, new PrologPredicate("unifiable"), new List<IPrologExpression>() { rhsGoalParam1, rhsGoalParam2 });
// rhsGoal = new PrologFunctorExpression(GrammarSelector.Prolog2, new PrologFunctor("="),
// new List<IPrologExpression>() { rhsGoalParam1, rhsGoalParam2 });
// variable2 = variable3;
// }
// else if (!rhsGoal.DCGDoNotAddExtraArguments)
// {
// rhsGoal.ExpressionList.Add(variable2);
// rhsGoal.ExpressionList.Add(variable3);
// variable2 = variable3;
// }

// rhsGoalList.Add(rhsGoal);
// }

// lhsGoal.ExpressionList.Add(variable1);
// lhsGoal.ExpressionList.Add(variable2);

// //return new PrologClause(lhsGoal, rhsGoalList);
// var rhsGoalListAsPrologList = PrologGlobalInfo.CSharpListToPrologList(rhsGoalList);

// //return new PrologFunctorExpression(gs, new PrologFunctor("clause"), new List<IPrologExpression>() { lhsGoal, rhsGoalListAsPrologList });
// return PrologGlobalInfo.CreateClauseAsFunctorExpression(lhsGoal, rhsGoalListAsPrologList);
// }

// public override void ExecuteSemanticAction(Stack<object> semanticStack, string action)
// {
// string str;
// List<PrologGoal> goalList;
// IPrologExpression expr;
// IPrologExpression expr2;
// List<IPrologExpression> exprList;
// PrologFunctor functor;
// PrologVariable variable;
// List<PrologVariable> variableList;
// PrologFunctorExpression functorExpr;
// PrologFunctorExpression functorExpr2;
// PrologFunctorExpression functorExpr3;
// PrologClause clause;

// switch (action)
// {
// case "#createClause":
// clause = PrologGlobalInfo.CreateClause((IPrologExpression)semanticStack.Pop());

// if (clause == null)
// {
// throw new Exception("Semantic action #createClause failed.");
// }

// semanticStack.Push(clause);
// break;

// case "#createCSharpGoalList":
// goalList = PrologGlobalInfo.PrologListToGoalList((IPrologExpression)semanticStack.Pop());

// if (goalList == null)
// {
// throw new Exception("Semantic action #createCSharpGoalList failed.");
// }

// semanticStack.Push(goalList);
// break;

// case "#convertExpressionToFunctorExpression":
// semanticStack.Push(PopAndConvertToFunctorExpression(semanticStack, action));
// break;

// case "#clauseAsFunctor":
// functorExpr2 = (PrologFunctorExpression)semanticStack.Pop();
// //functorExpr = (PrologFunctorExpression)semanticStack.Pop();
// functorExpr = PopAndConvertToFunctorExpression(semanticStack, action);
// //functor = new PrologFunctor("clause");
// //semanticStack.Push(new PrologFunctorExpression(gs, functor, new List<IPrologExpression>() { functorExpr, functorExpr2 }));
// semanticStack.Push(PrologGlobalInfo.CreateClauseAsFunctorExpression(functorExpr, functorExpr2));
// break;

// case "#infix": // Infix binary (dyadic) operator.
// expr2 = (IPrologExpression)semanticStack.Pop();
// str = (string)semanticStack.Pop();
// expr = (IPrologExpression)semanticStack.Pop();
// functor = new PrologFunctor(str);
// exprList = new List<IPrologExpression>() { expr, expr2 };
// semanticStack.Push(new PrologFunctorExpression(gs, functor, exprList));
// break;

// case "#arithExpr_Prefix":   // The same as #infix, except for the order of the items on the stack.
// expr2 = (IPrologExpression)semanticStack.Pop();
// expr = (IPrologExpression)semanticStack.Pop();
// str = (string)semanticStack.Pop();
// functor = new PrologFunctor(str);
// exprList = new List<IPrologExpression>() { expr, expr2 };
// semanticStack.Push(new PrologFunctorExpression(gs, functor, exprList));
// break;

// case "#unaryMinus":
// expr2 = (IPrologExpression)semanticStack.Pop();
// str = (string)semanticStack.Pop(); // Remove the - from the stack.
// expr = new PrologIntegerLiteral(0);
// exprList = new List<IPrologExpression>() { expr, expr2 };
// functor = new PrologFunctor(str);
// semanticStack.Push(new PrologFunctorExpression(gs, functor, exprList));
// break;

// case "#consSeq":
// expr2 = (IPrologExpression)semanticStack.Pop();
// expr = (IPrologExpression)semanticStack.Pop();
// functor = new PrologFunctor("consSeq");
// semanticStack.Push(new PrologFunctorExpression(gs, functor, new List<IPrologExpression>() { expr, expr2 }));
// break;

// case "#goalDisjunction":
// functorExpr2 = (PrologFunctorExpression)semanticStack.Pop();
// functorExpr = (PrologFunctorExpression)semanticStack.Pop();
// functor = new PrologFunctor("goal_disjunction");
// semanticStack.Push(new PrologFunctorExpression(gs, functor, new List<IPrologExpression>() { functorExpr, functorExpr2 }));
// break;

// case "#ifThenElse":
// functorExpr3 = (PrologFunctorExpression)semanticStack.Pop();
// functorExpr2 = (PrologFunctorExpression)semanticStack.Pop();
// functorExpr = PopAndConvertToFunctorExpression(semanticStack, action);
// functor = new PrologFunctor("if_then_else");
// semanticStack.Push(new PrologFunctorExpression(gs, functor,
// new List<IPrologExpression>() { functorExpr, functorExpr2, functorExpr3 }));
// break;

// case "#DCGClause":
// // The #DCGClause semantic action will add the extra arguments to the goals in order to support the difference list mechanism.
// // It also converts lists into "unifiable" predicates.
// exprList = (List<IPrologExpression>)semanticStack.Pop();
// functorExpr = (PrologFunctorExpression)semanticStack.Pop(); // The LHS of the clause.
// semanticStack.Push(GenerateDCGClause(functorExpr, exprList));
// break;

// case "#DCGEmptyObjectList":
// semanticStack.Push(new List<IPrologExpression>());
// break;

// case "#DCGObjectList":
// exprList = (List<IPrologExpression>)semanticStack.Pop();
// expr = (IPrologExpression)semanticStack.Pop();
// exprList.Insert(0, expr);
// semanticStack.Push(exprList);
// break;

// case "#markGoalAsNonDCG":
// functorExpr = (PrologFunctorExpression)semanticStack.Peek();
// functorExpr.DCGDoNotAddExtraArguments = true;
// break;

// case "#createVariableList":
// str = (string)semanticStack.Pop();
// variable = new PrologVariable(str);
// semanticStack.Push(new List<PrologVariable>() { variable });
// break;

// case "#appendToVariableList":
// str = (string)semanticStack.Pop();
// variableList = (List<PrologVariable>)semanticStack.Peek();
// variable = new PrologVariable(str);
// variableList.Add(variable);
// break;

// case "#createCaretList":
// functorExpr = (PrologFunctorExpression)semanticStack.Pop();
// variableList = (List<PrologVariable>)semanticStack.Pop();
// semanticStack.Push(new CaretList(variableList, functorExpr));
// break;

// default:
// throw new ArgumentException(string.Format("Unrecognized semantic action: {0}", action), "action");
// }
// }

// public override Symbol TokenToSymbol(Token token)
// {
// string tokenValueAsString = token.TokenValue.ToString();

// switch (token.TokenType)
// {
// case TokenType.T_Ident:
// case TokenType.T_Exclamation:   // The cut.

// switch (tokenValueAsString)
// {
// case "?-": return Symbol.T_InferPred;
// case ":-": return Symbol.T_From;
// case "is": return Symbol.T_Is;
// case "+": return Symbol.T_Plus;
// case "-": return Symbol.T_Minus;
// case "*": return Symbol.T_Multiply;
// case "/": return Symbol.T_Divide;
// case "mod": return Symbol.T_Mod;
// case "<": return Symbol.T_LessThan;
// case ">": return Symbol.T_GreaterThan;
// case "=<": return Symbol.T_LessEqual; // Not <=.  See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21
// case ">=": return Symbol.T_GreaterEqual;
// case @"\+": return Symbol.T_NotSymbol;
// case "->": return Symbol.T_IfThen;
// case ":": return Symbol.T_Colon;
// case "=": return Symbol.T_Assign;   // Unifiable
// case @"\=": return Symbol.T_NotUnifiable;
// case "==": return Symbol.T_Equals;
// case @"\==": return Symbol.T_NotEqual;
// case "=:=": return Symbol.T_ArithmeticEquals; // See http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse21
// case @"=\=": return Symbol.T_ArithmeticNotEquals;
// case "-->": return Symbol.T_DCGArrow;
// case "=..": return Symbol.T_Univ;
// case "^": return Symbol.T_Caret;
// default: break;
// }

// if (char.IsUpper(tokenValueAsString, 0)
// // The following supports non-binding variables such as _ and _Foo .
// // See http://www.csupomona.edu/~jrfisher/www/prolog_tutorial/2_3.html
// // TODO: Should we require the second character (if it exists) to be a capital letter if the first is an underscore?
// || tokenValueAsString.StartsWith("_"))
// {
// return Symbol.T_NameBeginningWithCapital;
// }
// else
// {
// return Symbol.T_NameNotBeginningWithCapital;
// }

// case TokenType.T_StrLit: return Symbol.T_StringLiteral;
// case TokenType.T_StrLit2: return Symbol.T_NameNotBeginningWithCapital; // The contents of a single-quoted string.
// case TokenType.T_Comma: return Symbol.T_Comma;
// case TokenType.T_Dot: return Symbol.T_Dot;
// case TokenType.T_LeftSquareBracket: return Symbol.T_LeftSquareBracket;
// case TokenType.T_RightSquareBracket: return Symbol.T_RightSquareBracket;
// case TokenType.T_OrBar: return Symbol.T_OrBar;
// case TokenType.T_Semicolon: return Symbol.T_Semicolon;
// case TokenType.T_LeftCurlyBrace: return Symbol.T_LeftCurlyBrace;
// case TokenType.T_RightCurlyBrace: return Symbol.T_RightCurlyBrace;
// case TokenType.T_Colon: return Symbol.T_Colon;
// case TokenType.T_QuestionMinus: return Symbol.T_InferPred;
// case TokenType.T_ColonMinus: return Symbol.T_From;
// case TokenType.T_Less: return Symbol.T_LessThan;
// case TokenType.T_EqualLessThan: return Symbol.T_LessEqual;
// case TokenType.T_Greater: return Symbol.T_GreaterThan;
// case TokenType.T_GreaterEqual: return Symbol.T_GreaterEqual;
// case TokenType.T_BackslashPlus: return Symbol.T_NotSymbol;
// case TokenType.T_BackslashEqual: return Symbol.T_NotUnifiable;
// case TokenType.T_EqualEqual: return Symbol.T_Equals;
// case TokenType.T_BackslashEqualEqual: return Symbol.T_NotEqual;
// case TokenType.T_EqualColonEqual: return Symbol.T_ArithmeticEquals;
// case TokenType.T_EqualBackslashEqual: return Symbol.T_ArithmeticNotEquals;
// case TokenType.T_MinusMinusGreaterThan: return Symbol.T_DCGArrow;
// case TokenType.T_EqualDotDot: return Symbol.T_Univ;
// case TokenType.T_Plus: return Symbol.T_Plus;
// case TokenType.T_Minus: return Symbol.T_Minus;
// case TokenType.T_Mult: return Symbol.T_Multiply;
// case TokenType.T_Div: return Symbol.T_Divide;
// case TokenType.T_Equal: return Symbol.T_Assign;   // Unifiable
// case TokenType.T_Arrow: return Symbol.T_IfThen;
// case TokenType.T_FltLit: return Symbol.T_FloatLiteral;
// case TokenType.T_Caret: return Symbol.T_Caret;
// default: break;
// }

// return base.TokenToSymbol(token);
// }

// public override void PushTokenOntoSemanticStack(Stack<object> semanticStack, Symbol tokenAsSymbol, Token token)
// {
// var value = token.TokenValue;

// switch (tokenAsSymbol)
// {
// case Symbol.T_IntegerLiteral:
// semanticStack.Push(new PrologIntegerLiteral((int)value));
// break;

// case Symbol.T_FloatLiteral:
// semanticStack.Push(new PrologFloatLiteral((double)value));
// break;

// case Symbol.T_NameBeginningWithCapital:
// case Symbol.T_NameNotBeginningWithCapital:
// semanticStack.Push(value);  // value is really a string; it must be converted to a Prolog domain model type later.
// break;

// case Symbol.T_StringLiteral:
// semanticStack.Push(PrologGlobalInfo.CSharpStringToPrologCodeList((string)value));
// break;

// case Symbol.T_Plus:
// case Symbol.T_Minus:
// case Symbol.T_Multiply:
// case Symbol.T_Divide:
// case Symbol.T_Mod:
// case Symbol.T_LessThan:
// case Symbol.T_GreaterThan:
// case Symbol.T_LessEqual:
// case Symbol.T_GreaterEqual:
// case Symbol.T_ArithmeticEquals:
// case Symbol.T_ArithmeticNotEquals:
// case Symbol.T_Assign:   // Unifiable
// case Symbol.T_Equals:
// case Symbol.T_NotEqual:
// case Symbol.T_NotUnifiable:
// case Symbol.T_Univ:
// case Symbol.T_Is:
// semanticStack.Push(value);
// break;

// default:
// break;
// }
// }
// }
// }