text:
--/**
-- * <copyright>
-- *
-- * Copyright (c) 2005, 2009 IBM Corporation and others.
-- * All rights reserved.   This program and the accompanying materials
-- * are made available under the terms of the Eclipse Public License v2.0
-- * which accompanies this distribution, and is available at
-- * http://www.eclipse.org/legal/epl-v20.html
-- *
-- * Contributors:
-- *   See (or edit) Notice Declaration below
-- *
-- * </copyright>
-- */
--
-- The EssentialOCL Parser
--

%Define
    -- Redefinition of macros used in the parser template
    --
    $default_repair_count /.getDefaultRepairCount()./
	$super_parser_class /.AbstractOCLParser./
    $prs_stream_class /.DerivedPrsStream./

	-- Definition of new macros used by the grammar file
	-- which may be redefined by extended files.
    $copyright_contributions /.*./

	-- Definition of new macros used by the grammar file
	-- which are not intended to be extended.
	$lpg_ns /.lpg.runtime./ -- package namespace of the LPG Runtime API

	-- Some useful macros
    $NewCase
    /. $Header
                case $rule_number:./

    $EmptyListAction -- Deprecated, code inline with correct generic parameter type
    /. $Header
                case $rule_number:
                    setResult(new BasicEList<Object>());
                    break;./

    -- BeginJava and EndJava need to be reworked in order to be able to properly use $NewCase macro

    -- BeginJava does nothing
	-- block-actions should call BeginCode, instead
    $BeginJava /../

  	-- EndJava does nothing
	-- block-actions should call EndCode, instead
	$EndJava /../

	$BeginCode
	/.$BeginAction
					$symbol_declarations./

	$EndCode /.$EndAction./

%End

%Notice
    /./**
 * Essential OCL Grammar
 * <copyright>
 *
 * Copyright (c) 2005, 2010 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 *   E.D.Willink - Elimination of some shift-reduce conflicts
 *   E.D.Willink - Remove unnecessary warning suppression
 *   E.D.Willink - Bugs 184048, 225493, 243976, 259818, 282882, 287993, 288040, 292112, 295166
 *   Borland - Bug 242880
 *   Adolfo Sanchez-Barbudo Herrera (Open Canarias):
 *        - 242153: LPG v 2.0.17 adoption.
 *        - 299396: Introducing new LPG templates
 *        - 300534: Removing the use of deprecated macros.
 *******************************************************************************/
    ./
%End

%Globals
    /.import org.eclipse.emf.common.util.BasicEList;
	import org.eclipse.emf.common.util.EList;
	import org.eclipse.ocl.cst.BooleanLiteralExpCS;
	import org.eclipse.ocl.cst.CSTNode;
	import org.eclipse.ocl.cst.CallExpCS;
	import org.eclipse.ocl.cst.CollectionLiteralExpCS;
	import org.eclipse.ocl.cst.CollectionLiteralPartCS;
	import org.eclipse.ocl.cst.CollectionTypeCS;
	import org.eclipse.ocl.cst.CollectionTypeIdentifierEnum;
	import org.eclipse.ocl.cst.FeatureCallExpCS;
	import org.eclipse.ocl.cst.IfExpCS;
	import org.eclipse.ocl.cst.IntegerLiteralExpCS;
	import org.eclipse.ocl.cst.InvalidLiteralExpCS;
	import org.eclipse.ocl.cst.IsMarkedPreCS;
	import org.eclipse.ocl.cst.IterateExpCS;
	import org.eclipse.ocl.cst.IteratorExpCS;
	import org.eclipse.ocl.cst.LetExpCS;
	import org.eclipse.ocl.cst.NullLiteralExpCS;
	import org.eclipse.ocl.cst.OCLExpressionCS;
	import org.eclipse.ocl.cst.OperationCallExpCS;
	import org.eclipse.ocl.cst.PathNameCS;
	import org.eclipse.ocl.cst.PrimitiveTypeCS;
	import org.eclipse.ocl.cst.RealLiteralExpCS;
	import org.eclipse.ocl.cst.SimpleNameCS;
	import org.eclipse.ocl.cst.SimpleTypeEnum;
	import org.eclipse.ocl.cst.StringLiteralExpCS;
	import org.eclipse.ocl.cst.TupleLiteralExpCS;
	import org.eclipse.ocl.cst.TupleTypeCS;
	import org.eclipse.ocl.cst.TypeCS;
	import org.eclipse.ocl.cst.UnlimitedNaturalLiteralExpCS;
	import org.eclipse.ocl.cst.VariableCS;
	import org.eclipse.ocl.cst.VariableExpCS;
	import org.eclipse.ocl.lpg.DerivedPrsStream;

	import $lpg_ns.BadParseException;
	import $lpg_ns.BadParseSymFileException;
	import $lpg_ns.DiagnoseParser;
	import $lpg_ns.ErrorToken;
	import $lpg_ns.IToken;
	import $lpg_ns.ILexStream;
	import $lpg_ns.Monitor;
	import $lpg_ns.NullExportedSymbolsException;
	import $lpg_ns.NullTerminalSymbolsException;
	import $lpg_ns.ParseTable;
	import $lpg_ns.RuleAction;
	import $lpg_ns.UndefinedEofSymbolException;
	import $lpg_ns.UnimplementedTerminalsException;
    ./
%End

%KeyWords
-- Reserved keywords
    and implies not or xor
    if then else endif
    let in
    false true
    null invalid
    self

-- Restricted keywords
    Bag Collection OrderedSet Sequence Set
    Tuple
    Boolean Integer Real String UnlimitedNatural
    OclAny OclInvalid OclVoid
%End

-- Terminals
%Identifier
    IDENTIFIER
%End

%Terminals

    QUOTED_IDENTIFIER INTEGER_LITERAL REAL_LITERAL STRING_LITERAL

    PLUS     ::= '+'
    MINUS    ::= '-'
    MULTIPLY ::= '*'
    DIVIDE   ::= '/'

    GREATER       ::= '>'
    LESS          ::= '<'
    EQUAL         ::= '='
    GREATER_EQUAL ::= '>='
    LESS_EQUAL    ::= '<='
    NOT_EQUAL     ::= '<>'

    LPAREN   ::= '('
    RPAREN   ::= ')'
    LBRACE   ::= '{'
    RBRACE   ::= '}'
    LBRACKET ::= '['
    RBRACKET ::= ']'

    ARROW      ::= '->'
    BAR        ::= '|'
    COMMA      ::= ','
    COLON      ::= ':'
    COLONCOLON ::= '::'
    SEMICOLON  ::= ';'
    DOT        ::= '.'
    DOTDOT     ::= '..'
%End

%Headers
	/.

	public $environment_class getOCLEnvironment() {
		return getLexer().getOCLEnvironment();
	}

	@Override
	public $super_lexer_class getLexer() {
		return ($super_lexer_class) super.getLexer();
	}

	// Some methods for backwards compatibility
	/**
	*

	* Before 3.0, this method was used with the now-deprecated  "dollar"getToken macro (which
	* provided token index in the prsStream) to obtain an IToken f a rule given the index of the
	* right hand side token in the said rule. In 3.0 a convenience method has been introduced
	* in order to directly return the IToken, given the index of the right hand side token in the rule.
	*

	*
	*

	* In an action-block of a rule, instead of doing getIToken("dollar"getToken(i))
	* you should do getRhsTokenText(i)
	*

	* @param i the right hand side token index
	* @return the correspondent IToken.
	*
	* @since 3.0
	*/
	@Deprecated
	protected IToken getIToken(int i) {
		return prsStream.getIToken(i);
	}

	/**
	*

	* Before 3.0, this method was used with the now-deprecated "dollar"getToken macro (which
	* provided token index in the prsStream) to obtain an IToken f a rule given the index of the
	* right hand side token in the said rule. In 3.0 a convenience method has been introduced
	* in order to directly return the IToken, given the index of the right hand side token in the rule.
	*

	*
	*

	* In an action-block of a rule, instead of doing getTokenText("dollar"getToken(i))
	* you should do getRhsTokenText(i)
	*

	* @param i the right hand side token index
	* @result the text of the correspondent right hand side IToken.
	*/
	@Deprecated
	protected String getTokenText(int i) {
		return prsStream.getTokenText(i);
	}

	/**
	* A convenience method to obtain the text of a right hand side IToken.
	*
	* @param i the right hand side token index
	* @result the text of the correspondent right hand side IToken.
	*
	* @since 3.0
	*/
	protected String getRhsTokenText(int i) {
		return prsStream.getTokenText(getRhsTokenIndex(i));
	}
	./
%End

%Rules

-----------------------------------------------------------------------
--  Names
-----------------------------------------------------------------------
--  Temporary backward compatibility support for 7.4.8 conceptual usage
    conceptualOperationName -> and
    conceptualOperationName -> implies
    conceptualOperationName -> not
    conceptualOperationName -> or
    conceptualOperationName -> xor
    conceptualOperationName -> '<'
    conceptualOperationName -> '<='
    conceptualOperationName -> '>='
    conceptualOperationName -> '>'
    conceptualOperationName -> '='
    conceptualOperationName -> '<>'
    conceptualOperationName -> '+'
    conceptualOperationName -> '-'
    conceptualOperationName -> '*'
    conceptualOperationName -> '/'
    conceptualOperationNameCS ::= conceptualOperationName
        /.$BeginCode
                    IToken iToken = getRhsIToken(1);
                    SimpleNameCS result = createConceptualOperationNameCS(iToken);
                    setOffsets(result, iToken);
                    setResult(result);
          $EndCode
        ./

    reservedKeyword -> and
    reservedKeyword -> else
    reservedKeyword -> endif
    reservedKeyword -> if
    reservedKeyword -> implies
    reservedKeyword -> in
    reservedKeyword -> let
    reservedKeyword -> not
    reservedKeyword -> or
    reservedKeyword -> then
    reservedKeyword -> xor

    tupleKeywordCS ::= Tuple
        /.$NewCase./
    reservedKeywordCS ::= reservedKeyword
        /.$BeginCode
                    IToken iToken = getRhsIToken(1);
                    SimpleNameCS result = createSimpleNameCS(
                                SimpleTypeEnum.KEYWORD_LITERAL,
                                iToken
                            );
                    setOffsets(result, iToken);
                    setResult(result);
          $EndCode
        ./
    restrictedKeywordCS -> CollectionTypeIdentifierCS
--  restrictedKeywordCS -> BooleanLiteralExpCS
--  restrictedKeywordCS -> InvalidLiteralExpCS
--  restrictedKeywordCS -> NullLiteralExpCS
--  restrictedKeywordCS -> selfKeywordCS
    restrictedKeywordCS -> primitiveTypeCS
    restrictedKeywordCS -> tupleKeywordCS

    selfKeywordCS ::= self
        /.$BeginCode
                    IToken iToken = getRhsIToken(1);
                    SimpleNameCS result = createSimpleNameCS(
                            SimpleTypeEnum.SELF_LITERAL,
                            iToken
                        );
                    setOffsets(result, iToken);
                    setResult(result);
          $EndCode
        ./

    simpleNameCS ::= IDENTIFIER
        /.$BeginCode
                    IToken iToken = getRhsIToken(1);
                    SimpleNameCS result = createSimpleNameCS(
                            SimpleTypeEnum.IDENTIFIER_LITERAL,
                            iToken
                        );
                    setOffsets(result, iToken);
                    setResult(result);
          $EndCode
        ./
    simpleNameCS -> QuotedSimpleNameCS
    QuotedSimpleNameCS ::= QUOTED_IDENTIFIER
        /.$BeginCode
                    IToken iToken = getRhsIToken(1);
                    SimpleNameCS result = createQuotedSimpleNameCS(
                            SimpleTypeEnum.IDENTIFIER_LITERAL,
                            iToken
                        );
                    setOffsets(result, iToken);
                    setResult(result);
          $EndCode
        ./
    QuotedSimpleNameCS ::= QuotedSimpleNameCS STRING_LITERAL
        /.$BeginCode
                    SimpleNameCS string = (SimpleNameCS)getRhsSym(1);
                    IToken literalToken = getRhsIToken(2);
                    SimpleNameCS result = extendQuotedSimpleNameCS(string, literalToken);
                    setOffsets(result, string, literalToken);
                    setResult(result);
          $EndCode
        ./

    unreservedSimpleNameCS -> simpleNameCS
    unreservedSimpleNameCS -> restrictedKeywordCS

    pathNameCS ::= simpleNameCS
        /.$BeginCode
                    SimpleNameCS simpleName = (SimpleNameCS)getRhsSym(1);
                    PathNameCS result = createPathNameCS(simpleName);
                    setOffsets(result, simpleName);
                    setResult(result);
          $EndCode
        ./
    pathNameCS ::= pathNameCS '::' unreservedSimpleNameCS
        /.$BeginCode
                    PathNameCS result = (PathNameCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    result = extendPathNameCS(result, simpleNameCS);
                    setOffsets(result, result, simpleNameCS);
                    setResult(result);
          $EndCode
        ./

-----------------------------------------------------------------------
--  Types
-----------------------------------------------------------------------
    primitiveTypeCS ::= Boolean
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.BOOLEAN_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= Integer
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.INTEGER_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= Real
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.REAL_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= String
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.STRING_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= UnlimitedNatural
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.UNLIMITED_NATURAL_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    primitiveTypeCS ::= OclAny
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.OCL_ANY_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= OclInvalid
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.OCL_INVALID_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    primitiveTypeCS ::= OclVoid
        /.$BeginCode
                    PrimitiveTypeCS result = createPrimitiveTypeCS(
                            SimpleTypeEnum.OCL_VOID_LITERAL,
                            getRhsTokenText(1)
                        );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    CollectionTypeIdentifierCS ::= Set
        /.$BeginCode
                    SimpleNameCS result = createCollectionTypeCS(
                                CollectionTypeIdentifierEnum.SET_LITERAL,
                                getRhsTokenText(1)
                            );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    CollectionTypeIdentifierCS ::= Bag
        /.$BeginCode
                    SimpleNameCS result = createCollectionTypeCS(
                                CollectionTypeIdentifierEnum.BAG_LITERAL,
                                getRhsTokenText(1)
                            );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    CollectionTypeIdentifierCS ::= Sequence
        /.$BeginCode
                    SimpleNameCS result = createCollectionTypeCS(
                                CollectionTypeIdentifierEnum.SEQUENCE_LITERAL,
                                getRhsTokenText(1)
                            );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    CollectionTypeIdentifierCS ::= Collection
        /.$BeginCode
                    SimpleNameCS result = createCollectionTypeCS(
                                CollectionTypeIdentifierEnum.COLLECTION_LITERAL,
                                getRhsTokenText(1)
                            );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    CollectionTypeIdentifierCS ::= OrderedSet
        /.$BeginCode
                    SimpleNameCS result = createCollectionTypeCS(
                                CollectionTypeIdentifierEnum.ORDERED_SET_LITERAL,
                                getRhsTokenText(1)
                            );
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    typeCS -> primitiveTypeCS
    typeCS -> pathNameCS
    typeCS -> collectionTypeCS
    typeCS -> tupleTypeCS

    collectionTypeCS ::= CollectionTypeIdentifierCS '(' typeCS ')'
        /.$BeginCode
                    CollectionTypeCS result = (CollectionTypeCS)getRhsSym(1);
                    result.setTypeCS((TypeCS)getRhsSym(3));
                    setOffsets(result, result, getRhsIToken(4));
                    setResult(result);
          $EndCode
        ./

    tupleTypeCS ::= Tuple '(' tupleTypePartsCSopt ')'
        /.$BeginCode
                     TupleTypeCS result = createTupleTypeCS((EList<VariableCS>)getRhsSym(3));
                    setOffsets(result, getRhsIToken(1), getRhsIToken(4));
                    setResult(result);
          $EndCode
        ./

    tupleTypePartsCSopt ::= %empty
        /.$BeginCode
                    setResult(new BasicEList<VariableCS>());
          $EndCode
        ./
    tupleTypePartsCSopt -> tupleTypePartsCS

    tupleTypePartsCS ::= typedUninitializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = new BasicEList<VariableCS>();
                    result.add((VariableCS)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./
    tupleTypePartsCS ::= tupleTypePartsCS ',' typedUninitializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = (EList<VariableCS>)getRhsSym(1);
                    result.add((VariableCS)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./

-----------------------------------------------------------------------
--  Declarations
-----------------------------------------------------------------------
    untypedUninitializedVariableCS ::= simpleNameCS
        /.$BeginCode
                    SimpleNameCS name = (SimpleNameCS)getRhsSym(1);
                    VariableCS result = createVariableCS(name, null, null);
                    setOffsets(result, name);
                    setResult(result);
          $EndCode
        ./

    typedUninitializedVariableCS ::= simpleNameCS ':' typeCS
        /.$BeginCode
                    SimpleNameCS name = (SimpleNameCS)getRhsSym(1);
                    TypeCS type = (TypeCS)getRhsSym(3);
                    VariableCS result = createVariableCS(name, type, null);
                    setOffsets(result, name, type);
                    setResult(result);
          $EndCode
        ./

    untypedInitializedVariableCS ::= simpleNameCS '=' OclExpressionCS
        /.$BeginCode
                    SimpleNameCS name = (SimpleNameCS)getRhsSym(1);
                    OCLExpressionCS initExpression = (OCLExpressionCS)getRhsSym(3);
                    VariableCS result = createVariableCS(name, null, initExpression);
                    setOffsets(result, name, initExpression);
                    setResult(result);
          $EndCode
        ./

    typedInitializedVariableCS ::= simpleNameCS ':' typeCS '=' OclExpressionCS
        /.$BeginCode
                    SimpleNameCS name = (SimpleNameCS)getRhsSym(1);
                    TypeCS type = (TypeCS)getRhsSym(3);
                    OCLExpressionCS initExpression = (OCLExpressionCS)getRhsSym(5);
                    VariableCS result = createVariableCS(name, type, initExpression);
                    setOffsets(result, name, initExpression);
                    setResult(result);
          $EndCode
        ./

    initializedVariableCS -> untypedInitializedVariableCS
    initializedVariableCS -> typedInitializedVariableCS

    uninitializedVariableCS -> untypedUninitializedVariableCS
    uninitializedVariableCS -> typedUninitializedVariableCS

    VariableDeclarationCS -> untypedUninitializedVariableCS
    VariableDeclarationCS -> untypedInitializedVariableCS
    VariableDeclarationCS -> typedUninitializedVariableCS
    VariableDeclarationCS -> typedInitializedVariableCS

-----------------------------------------------------------------------
--  Literals
-----------------------------------------------------------------------
-- EnumLiteralExpCS is parsed as a PropertyCallExpCS[C]
--  LiteralExpCS -> EnumLiteralExpCS
    LiteralExpCS -> CollectionLiteralExpCS
    LiteralExpCS -> TupleLiteralExpCS
    LiteralExpCS -> PrimitiveLiteralExpCS
    LiteralExpCS -> TypeLiteralExpCS

    CollectionLiteralExpCS ::= CollectionTypeIdentifierCS
       '{' CollectionLiteralPartsCSopt '}'
        /.$BeginCode
                    CollectionTypeCS typeCS = (CollectionTypeCS)getRhsSym(1);
                    CollectionLiteralExpCS result = createCollectionLiteralExpCS(
                            typeCS,
                            (EList<CollectionLiteralPartCS>)getRhsSym(3)
                        );
                    setOffsets(result, typeCS, getRhsIToken(4));
                    setResult(result);
          $EndCode
        ./
    CollectionLiteralExpCS ::= collectionTypeCS '{' CollectionLiteralPartsCSopt '}'
        /.$BeginCode
                    CollectionTypeCS typeCS = (CollectionTypeCS)getRhsSym(1);
                    CollectionLiteralExpCS result = createCollectionLiteralExpCS(
                            typeCS,
                            (EList<CollectionLiteralPartCS>)getRhsSym(3)
                        );
                    setOffsets(result, typeCS, getRhsIToken(4));
                    setResult(result);
          $EndCode
        ./

    CollectionLiteralPartsCSopt ::= %empty
        /.$BeginCode
                    setResult(new BasicEList<CollectionLiteralPartCS>());
          $EndCode
        ./
    CollectionLiteralPartsCSopt -> CollectionLiteralPartsCS

    CollectionLiteralPartsCS ::= CollectionLiteralPartCS
        /.$BeginCode
                    EList<CollectionLiteralPartCS> result = new BasicEList<CollectionLiteralPartCS>();
                    result.add((CollectionLiteralPartCS)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./
    CollectionLiteralPartsCS ::= CollectionLiteralPartsCS ',' CollectionLiteralPartCS
        /.$BeginCode
                    EList<CollectionLiteralPartCS> result = (EList<CollectionLiteralPartCS>)getRhsSym(1);
                    result.add((CollectionLiteralPartCS)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./

    CollectionLiteralPartCS -> CollectionRangeCS
    CollectionLiteralPartCS ::= OclExpressionCS
        /.$BeginCode
                    CollectionLiteralPartCS result = createCollectionLiteralPartCS(
                            (OCLExpressionCS)getRhsSym(1)
                        );
                    setOffsets(result, (CSTNode)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./

    CollectionRangeCS ::= OclExpressionCS '..' OclExpressionCS
        /.$BeginCode
                    CollectionLiteralPartCS result = createCollectionRangeCS(
                            (OCLExpressionCS)getRhsSym(1),
                            (OCLExpressionCS)getRhsSym(3)
                        );
                    setOffsets(result, (CSTNode)getRhsSym(1), (CSTNode)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./

    PrimitiveLiteralExpCS -> IntegerLiteralExpCS
    PrimitiveLiteralExpCS -> RealLiteralExpCS
    PrimitiveLiteralExpCS -> StringLiteralExpCS
    PrimitiveLiteralExpCS -> BooleanLiteralExpCS
    PrimitiveLiteralExpCS -> UnlimitedNaturalLiteralExpCS
    PrimitiveLiteralExpCS -> InvalidLiteralExpCS
    PrimitiveLiteralExpCS -> NullLiteralExpCS

    TupleLiteralExpCS ::= Tuple '{' TupleLiteralPartsCS '}'
        /.$BeginCode
                    TupleLiteralExpCS result = createTupleLiteralExpCS((EList<VariableCS>)getRhsSym(3));
                    setOffsets(result, getRhsIToken(1), getRhsIToken(4));
                    setResult(result);
          $EndCode
        ./

    TupleLiteralPartsCS ::= initializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = new BasicEList<VariableCS>();
                    result.add((VariableCS)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./
    TupleLiteralPartsCS ::= TupleLiteralPartsCS ',' initializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = (EList<VariableCS>)getRhsSym(1);
                    result.add((VariableCS)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./

    IntegerLiteralExpCS ::= INTEGER_LITERAL
        /.$BeginCode
                    IntegerLiteralExpCS result = createIntegerLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    RealLiteralExpCS ::= REAL_LITERAL
        /.$BeginCode
                    RealLiteralExpCS result = createRealLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    StringLiteralExpCS ::= STRING_LITERAL
        /.$BeginCode
                    IToken literalToken = getRhsIToken(1);
                    StringLiteralExpCS result = createStringLiteralExpCS(literalToken);
                    setOffsets(result, literalToken);
                    setResult(result);
          $EndCode
        ./
    StringLiteralExpCS ::= StringLiteralExpCS STRING_LITERAL
        /.$BeginCode
                    StringLiteralExpCS string = (StringLiteralExpCS)getRhsSym(1);
                    IToken literalToken = getRhsIToken(2);
                    StringLiteralExpCS result = extendStringLiteralExpCS(string, literalToken);
                    setOffsets(result, string, literalToken);
                    setResult(result);
          $EndCode
        ./

    BooleanLiteralExpCS ::= true
        /.$BeginCode
                    BooleanLiteralExpCS result = createBooleanLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./
    BooleanLiteralExpCS ::= false
        /.$BeginCode
                    BooleanLiteralExpCS result = createBooleanLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    UnlimitedNaturalLiteralExpCS ::= '*'
        /.$BeginCode
                    UnlimitedNaturalLiteralExpCS result = createUnlimitedNaturalLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    InvalidLiteralExpCS ::= invalid
        /.$BeginCode
                    InvalidLiteralExpCS result = createInvalidLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    NullLiteralExpCS ::= null
        /.$BeginCode
                    NullLiteralExpCS result = createNullLiteralExpCS(getRhsTokenText(1));
                    setOffsets(result, getRhsIToken(1));
                    setResult(result);
          $EndCode
        ./

    -- unqualified pathNameCS is parsed as SimpleNameExpCS
    -- qualified pathNameCS is parsed as PropertyCallExpCS[C]
    TypeLiteralExpCS ::= primitiveTypeCS
        /.$NewCase./
    TypeLiteralExpCS ::= collectionTypeCS
        /.$NewCase./
    TypeLiteralExpCS ::= tupleTypeCS
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(1);
                    VariableExpCS result = createVariableExpCS(
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            null
                        );
                    setOffsets(result, simpleNameCS);
                    setResult(result);
          $EndCode
        ./

-----------------------------------------------------------------------
--  Calls
-----------------------------------------------------------------------
    CallExpCS -> FeatureCallExpCS
    CallExpCS -> LoopExpCS

    LoopExpCS -> IteratorExpCS
    LoopExpCS -> IterateExpCS

--  IteratorExpCS[A.1] is parsed as OperationCallExpCS[B]
    IteratorExpCS ::=                          -- [A.2]
        primaryExpCS '->' simpleNameCS
        '(' uninitializedVariableCS '|' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IteratorExpCS result = createIteratorExpCS(
                            source,
                            simpleNameCS,
                            (VariableCS)getRhsSym(5),
                            null,
                            (OCLExpressionCS)getRhsSym(7)
                        );
                    setOffsets(result, source, getRhsIToken(8));
                    setResult(result);
          $EndCode
        ./
    IteratorExpCS ::=                          -- [A.3.1]
        primaryExpCS '->' simpleNameCS
        '(' simpleNameCS ',' uninitializedVariableCS '|' OclExpressionCS ')'
        /.$BeginCode
                    SimpleNameCS name = (SimpleNameCS)getRhsSym(5);
                    VariableCS variableCS = createVariableCS(name, null, null);
                    setOffsets(variableCS, name);
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IteratorExpCS result = createIteratorExpCS(
                            source,
                            simpleNameCS,
                            variableCS,
                            (VariableCS)getRhsSym(7),
                            (OCLExpressionCS)getRhsSym(9)
                        );
                    setOffsets(result, source, getRhsIToken(10));
                    setResult(result);
          $EndCode
        ./
    IteratorExpCS ::=                          -- [A.3.2]
        primaryExpCS '->' simpleNameCS '(' typedUninitializedVariableCS ','
        uninitializedVariableCS '|' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IteratorExpCS result = createIteratorExpCS(
                            source,
                            simpleNameCS,
                            (VariableCS)getRhsSym(5),
                            (VariableCS)getRhsSym(7),
                            (OCLExpressionCS)getRhsSym(9)
                        );
                    setOffsets(result, source, getRhsIToken(10));
                    setResult(result);
          $EndCode
        ./
--  IteratorExpCS[B] is parsed as OperationCallExpCS[C]
--  IteratorExpCS[C] is parsed as AssociationClassCallExpCS[A.1]
--  IteratorExpCS[D] is parsed as AssociationClassCallExpCS[A]
--  IteratorExpCS[E] is parsed as AssociationClassCallExpCS[A]

    IterateExpCS ::= primaryExpCS '->' simpleNameCS
        '(' typedInitializedVariableCS '|' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IterateExpCS result = createIterateExpCS(
                            source,
                            simpleNameCS,
                            (VariableCS)getRhsSym(5),
                            null,
                            (OCLExpressionCS)getRhsSym(7)
                        );
                    setOffsets(result, source, getRhsIToken(8));
                    setResult(result);
          $EndCode
        ./
    IterateExpCS ::= primaryExpCS '->' simpleNameCS
        '(' uninitializedVariableCS ';' typedInitializedVariableCS '|' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IterateExpCS result = createIterateExpCS(
                            source,
                            simpleNameCS,
                            (VariableCS)getRhsSym(5),
                            (VariableCS)getRhsSym(7),
                            (OCLExpressionCS)getRhsSym(9)
                        );
                    setOffsets(result, source, getRhsIToken(10));
                    setResult(result);
          $EndCode
        ./

    FeatureCallExpCS -> OperationCallExpCS
    FeatureCallExpCS -> PropertyCallExpCS
    FeatureCallExpCS -> NavigationCallExpCS

--  OperationCallExpCS[A] is realized by the infix OclExpressionCS productions
    OperationCallExpCS ::= -- [B.1]
        primaryExpCS '->' simpleNameCS '(' ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    OperationCallExpCS result = createArrowOperationCallExpCS(
                            source,
                            (SimpleNameCS)getRhsSym(3),
                            null,
                            new BasicEList<OCLExpressionCS>()
                        );
                    setOffsets(result, source, getRhsIToken(5));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::= -- [B.2],IteratorExpCS[A.1]
        primaryExpCS '->' simpleNameCS '(' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    OCLExpressionCS arg = (OCLExpressionCS)getRhsSym(5);
                    OCLExpressionCS result;
                    if (isIterator(simpleNameCS.getValue())) {
                        result = createIteratorExpCS(
                                source,
                                simpleNameCS,
                                null,
                                null,
                                arg
                            );
                    }
                    else {
                        EList<OCLExpressionCS> args = new BasicEList<OCLExpressionCS>();
                        args.add(arg);
                        result = createArrowOperationCallExpCS(
                                source,
                                simpleNameCS,
                                null,
                                args
                            );
                    }
                    setOffsets(result, source, getRhsIToken(6));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::= -- [B.3.1]
        primaryExpCS '->' simpleNameCS '(' notNameExpressionCS ',' argumentsCS ')'
        /.$BeginCode
                    EList<OCLExpressionCS> args = (EList<OCLExpressionCS>)getRhsSym(7);
                    args.add(0, (OCLExpressionCS)getRhsSym(5));
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    OperationCallExpCS result = createArrowOperationCallExpCS(
                            source,
                            (SimpleNameCS)getRhsSym(3),
                            null,
                            args
                        );
                    setOffsets(result, source, getRhsIToken(8));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::= -- [B.3.2]
        primaryExpCS '->' simpleNameCS '(' simpleNameCS ',' argumentsCS ')'
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(5);
                    OCLExpressionCS variableExpCS = createVariableExpCS(
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            null
                        );
                    setOffsets(variableExpCS, simpleNameCS);
                    EList<OCLExpressionCS> args = (EList<OCLExpressionCS>)getRhsSym(7);
                    args.add(0, variableExpCS);
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    OperationCallExpCS result = createArrowOperationCallExpCS(
                            source,
                            (SimpleNameCS)getRhsSym(3),
                            null,
                            args
                        );
                    setOffsets(result, source, getRhsIToken(8));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::=
        primaryExpCS '.' conceptualOperationNameCS isMarkedPreCSopt '(' argumentsCSopt ')'
        /.$NewCase./
    OperationCallExpCS ::= -- [C],[E],IteratorExpCS[B]
        primaryExpCS '.' simpleNameCS isMarkedPreCSopt '(' argumentsCSopt ')'
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    CallExpCS result = createDotOperationCallExpCS(
                            source,
                            null,
                            simpleNameCS,
                            (IsMarkedPreCS)getRhsSym(4),
                            (EList<OCLExpressionCS>)getRhsSym(6)
                        );
                    setOffsets(result, source, getRhsIToken(7));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::= -- [D],[F],[G.1]
        simpleNameCS isMarkedPreCSopt '(' argumentsCSopt ')'
        /.$BeginCode
                    OperationCallExpCS result = createDotOperationCallExpCS(
                            null,
                            null,
                            (SimpleNameCS)getRhsSym(1),
                            (IsMarkedPreCS)getRhsSym(2),
                            (EList<OCLExpressionCS>)getRhsSym(4)
                        );
                    setOffsets(result, getRhsIToken(1), getRhsIToken(5));
                    setResult(result);
          $EndCode
        ./
    OperationCallExpCS ::= -- [G.2]
        pathNameCS '::' unreservedSimpleNameCS '(' argumentsCSopt ')'
        /.$BeginCode
                    PathNameCS pathNameCS = (PathNameCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    OperationCallExpCS result = createDotOperationCallExpCS(
                            null,
                            pathNameCS,
                            simpleNameCS,
                            null,
                            (EList<OCLExpressionCS>)getRhsSym(5)
                        );
                    setOffsets(result, pathNameCS, getRhsIToken(6));
                    setResult(result);
          $EndCode
        ./
--  OperationCallExpCS[H] is realized by the prefix OclExpressionCS productions
    OperationCallExpCS ::= -- [I],[J]
        primaryExpCS '.' pathNameCS '::' unreservedSimpleNameCS isMarkedPreCSopt
        '(' argumentsCSopt ')'
        /.$BeginCode
                    PathNameCS pathNameCS = (PathNameCS)getRhsSym(3);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(5);
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    CallExpCS result = createDotOperationCallExpCS(
                            source,
                            pathNameCS,
                            simpleNameCS,
                            (IsMarkedPreCS)getRhsSym(6),
                            (EList<OCLExpressionCS>)getRhsSym(8)
                        );
                    setOffsets(result, source, getRhsIToken(9));
                    setResult(result);
          $EndCode
        ./

--  NavigationCallExpCS -> PropertyCallExpCS -- parsed as FeatureCallExpCS
    NavigationCallExpCS -> AssociationClassCallExpCS

--  PropertyCallExpCS[A] is parsed as AssociationClassCallExpCS[A.1]
--  PropertyCallExpCS[B.1] is parsed as a SimpleNameExpCS
--  PropertyCallExpCS[B.2] is parsed as a AssociationClassCallExpCS[B.1]
    PropertyCallExpCS ::= -- [C] excluding [B]
        pathNameCS '::' unreservedSimpleNameCS isMarkedPreCSopt
        /.$BeginCode
                    PathNameCS pathNameCS = (PathNameCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IsMarkedPreCS isMarkedPreCS = (IsMarkedPreCS)getRhsSym(4);
                    FeatureCallExpCS result = createFeatureCallExpCS(
                            null,
                            pathNameCS,
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            isMarkedPreCS
                        );
                    if (isMarkedPreCS != null) {
                        setOffsets(result, pathNameCS, isMarkedPreCS);
                    } else {
                        setOffsets(result, pathNameCS, simpleNameCS);
                    }
                    setResult(result);
          $EndCode
        ./
    PropertyCallExpCS ::= -- [D]
        primaryExpCS '.' pathNameCS '::' unreservedSimpleNameCS isMarkedPreCSopt
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    PathNameCS pathNameCS = (PathNameCS)getRhsSym(3);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(5);
                    IsMarkedPreCS isMarkedPreCS = (IsMarkedPreCS)getRhsSym(6);
                    FeatureCallExpCS result = createFeatureCallExpCS(
                            source,
                            pathNameCS,
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            isMarkedPreCS
                        );
                    if (isMarkedPreCS != null) {
                        setOffsets(result, source, isMarkedPreCS);
                    } else {
                        setOffsets(result, source, simpleNameCS);
                    }
                    setResult(result);
          $EndCode
        ./

    AssociationClassCallExpCS ::= -- [A.1],PropertyCallExpCS[A],IteratorExpCS[C,D,E]
        primaryExpCS '.' simpleNameCS isMarkedPreCSopt
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IsMarkedPreCS isMarkedPreCS = (IsMarkedPreCS)getRhsSym(4);
                    FeatureCallExpCS result = createFeatureCallExpCS(
                            source,
                            null,
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            isMarkedPreCS
                        );
                    if (isMarkedPreCS != null) {
                        setOffsets(result, source, isMarkedPreCS);
                    } else {
                        setOffsets(result, source, simpleNameCS);
                    }
                    setResult(result);
          $EndCode
        ./
    AssociationClassCallExpCS ::= -- [A.2],IteratorExpCS[D,E]
        primaryExpCS '.' simpleNameCS '[' argumentsCS ']' isMarkedPreCSopt
        /.$BeginCode
                    OCLExpressionCS source = (OCLExpressionCS)getRhsSym(1);
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(3);
                    IsMarkedPreCS isMarkedPreCS = (IsMarkedPreCS)getRhsSym(7);
                    FeatureCallExpCS result = createFeatureCallExpCS(
                            source,
                            null,
                            simpleNameCS,
                            (EList<OCLExpressionCS>)getRhsSym(5),
                            isMarkedPreCS
                        );
                    if (isMarkedPreCS != null) {
                        setOffsets(result, source, isMarkedPreCS);
                    } else {
                        setOffsets(result, source, getRhsIToken(6));
                    }
                    setResult(result);
          $EndCode
        ./
--  AssociationClassCallExpCS[B.1.1] parsed as SimpleNameExpCS
--  AssociationClassCallExpCS[B.1.2] is added by Complete OCL
    AssociationClassCallExpCS ::=  -- [B.2]
        simpleNameCS '[' argumentsCS ']' isMarkedPreCSopt
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(1);
                    IsMarkedPreCS isMarkedPreCS = (IsMarkedPreCS)getRhsSym(5);
                    VariableExpCS result = createVariableExpCS(
                            simpleNameCS,
                            (EList<OCLExpressionCS>)getRhsSym(3),
                            isMarkedPreCS
                        );
                    if (isMarkedPreCS != null) {
                        setOffsets(result, simpleNameCS, isMarkedPreCS);
                    } else {
                        setOffsets(result, simpleNameCS, getRhsIToken(4));
                    }
                    setResult(result);
          $EndCode
        ./

    isMarkedPreCSopt ::= %empty
        /.$BeginCode
                    setResult(null);
          $EndCode
        ./

    argumentsCSopt ::= %empty
        /.$BeginCode
                    setResult(new BasicEList<OCLExpressionCS>());
          $EndCode
        ./
    argumentsCSopt -> argumentsCS

    argumentsCS ::= OclExpressionCS
        /.$BeginCode
                    EList<OCLExpressionCS> result = new BasicEList<OCLExpressionCS>();
                    result.add((OCLExpressionCS)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./
    argumentsCS ::= argumentsCS ',' OclExpressionCS
        /.$BeginCode
                    EList<OCLExpressionCS> result = (EList<OCLExpressionCS>)getRhsSym(1);
                    result.add((OCLExpressionCS)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./

-----------------------------------------------------------------------
--  Expressions
-----------------------------------------------------------------------
    -- An OclExpressionCS comprising just a SimpleNameCS is kept separate as
    --  SimpleNameExpCS to avoid ambiguity when parsing "a->b(c,d" until the next
    --  letter resolves the usage as a two iterator  or as a two or more argument
    --  OperationCallExpCS.
    -- An OclExpressionCS comprising one or more LetExpCS is kept separate to ensure
    --  that let is right associative, whereas infix operators are left associative.
    --   a = 64 / 16 / let b : Integer in 8 / let c : Integer in 4
    -- is
    --   a = (64 / 16) / (let b : Integer in 8 / (let c : Integer in 4 ))
    OclExpressionCS -> notNameExpressionCS
    OclExpressionCS -> SimpleNameExpCS

--  VariableExpCS[.1] simpleNameCS parsed as SimpleNameExpCS
    VariableExpCS ::= -- [.2]
        selfKeywordCS
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(1);
                    VariableExpCS result = createVariableExpCS(
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            null
                        );
                    setOffsets(result, simpleNameCS);
                    setResult(result);
          $EndCode
        ./

    SimpleNameExpCS ::= -- AssociationClassCallExpCS[B.1.1],
                        -- PropertyCallExpCS[B],VariableExpCS[.1]
        simpleNameCS
        /.$BeginCode
                    SimpleNameCS simpleNameCS = (SimpleNameCS)getRhsSym(1);
                    VariableExpCS result = createVariableExpCS(
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>(),
                            null
                        );
                    setOffsets(result, simpleNameCS);
                    setResult(result);
          $EndCode
        ./

    notNameExpressionCS -> impliesNotNameNotLetCS
    notNameExpressionCS -> impliesWithLetCS

    impliesNotLetCS -> impliesNotNameNotLetCS
    impliesNotLetCS -> SimpleNameExpCS
    impliesNotNameNotLetCS -> xorNotNameNotLetCS
    impliesNotNameNotLetCS ::= impliesNotLetCS implies xorNotLetCS
        /.$NewCase./
    impliesWithLetCS -> xorWithLetCS
    impliesWithLetCS ::= impliesNotLetCS implies xorWithLetCS
        /.$NewCase./

    xorNotLetCS -> xorNotNameNotLetCS
    xorNotLetCS -> SimpleNameExpCS
    xorNotNameNotLetCS -> orNotNameNotLetCS
    xorNotNameNotLetCS ::= xorNotLetCS xor orNotLetCS
        /.$NewCase./
    xorWithLetCS -> orWithLetCS
    xorWithLetCS ::= xorNotLetCS xor orWithLetCS
        /.$NewCase./

    orNotLetCS -> orNotNameNotLetCS
    orNotLetCS -> SimpleNameExpCS
    orNotNameNotLetCS -> andNotNameNotLetCS
    orNotNameNotLetCS ::= orNotLetCS or andNotLetCS
        /.$NewCase./
    orWithLetCS -> andWithLetCS
    orWithLetCS ::= orNotLetCS or andWithLetCS
        /.$NewCase./

    andNotLetCS -> andNotNameNotLetCS
    andNotLetCS -> SimpleNameExpCS
    andNotNameNotLetCS -> equalityNotNameNotLetCS
    andNotNameNotLetCS ::= andNotLetCS and equalityNotLetCS
        /.$NewCase./
    andWithLetCS -> equalityWithLetCS
    andWithLetCS ::= andNotLetCS and equalityWithLetCS
        /.$NewCase./

    equalityNotLetCS -> equalityNotNameNotLetCS
    equalityNotLetCS -> SimpleNameExpCS
    equalityNotNameNotLetCS -> relationalNotNameNotLetCS
    equalityNotNameNotLetCS ::= equalityNotLetCS '=' relationalNotLetCS
        /.$NewCase./
    equalityNotNameNotLetCS ::= equalityNotLetCS '<>' relationalNotLetCS
        /.$NewCase./
    equalityWithLetCS -> relationalWithLetCS
    equalityWithLetCS ::= equalityNotLetCS '=' relationalWithLetCS
        /.$NewCase./
    equalityWithLetCS ::= equalityNotLetCS '<>' relationalWithLetCS
        /.$NewCase./

    relationalNotLetCS -> relationalNotNameNotLetCS
    relationalNotLetCS -> SimpleNameExpCS
    relationalNotNameNotLetCS -> additiveNotNameNotLetCS
    relationalNotNameNotLetCS ::= relationalNotLetCS '>' additiveNotLetCS
        /.$NewCase./
    relationalNotNameNotLetCS ::= relationalNotLetCS '<' additiveNotLetCS
        /.$NewCase./
    relationalNotNameNotLetCS ::= relationalNotLetCS '>=' additiveNotLetCS
        /.$NewCase./
    relationalNotNameNotLetCS ::= relationalNotLetCS '<=' additiveNotLetCS
        /.$NewCase./
    relationalWithLetCS -> additiveWithLetCS
    relationalWithLetCS ::= relationalNotLetCS '>' additiveWithLetCS
        /.$NewCase./
    relationalWithLetCS ::= relationalNotLetCS '<' additiveWithLetCS
        /.$NewCase./
    relationalWithLetCS ::= relationalNotLetCS '>=' additiveWithLetCS
        /.$NewCase./
    relationalWithLetCS ::= relationalNotLetCS '<=' additiveWithLetCS
        /.$NewCase./

    additiveNotLetCS -> additiveNotNameNotLetCS
    additiveNotLetCS -> SimpleNameExpCS
    additiveNotNameNotLetCS -> multiplicativeNotNameNotLetCS
    additiveNotNameNotLetCS ::= additiveNotLetCS '+' multiplicativeNotLetCS
        /.$NewCase./
    additiveNotNameNotLetCS ::= additiveNotLetCS '-' multiplicativeNotLetCS
        /.$NewCase./
    additiveWithLetCS -> multiplicativeWithLetCS
    additiveWithLetCS ::= additiveNotLetCS '+' multiplicativeWithLetCS
        /.$NewCase./
    additiveWithLetCS ::= additiveNotLetCS '-' multiplicativeWithLetCS
        /.$NewCase./

    multiplicativeNotLetCS -> multiplicativeNotNameNotLetCS
    multiplicativeNotLetCS -> SimpleNameExpCS
    multiplicativeNotNameNotLetCS -> unaryNotNameNotLetCS
    multiplicativeNotNameNotLetCS ::= multiplicativeNotLetCS '*' unaryNotLetCS
        /.$NewCase./
    multiplicativeNotNameNotLetCS ::= multiplicativeNotLetCS '/' unaryNotLetCS
        /.$NewCase./
    multiplicativeWithLetCS -> unaryWithLetCS
    multiplicativeWithLetCS ::= multiplicativeNotLetCS '*' unaryWithLetCS
        /.$NewCase./
    multiplicativeWithLetCS ::= multiplicativeNotLetCS '/' unaryWithLetCS
        /.$BeginCode
                    SimpleNameCS simpleNameCS = createSimpleNameCS(
                                SimpleTypeEnum.KEYWORD_LITERAL,
                                getRhsIToken(2)
                            );
                    setOffsets(simpleNameCS, getRhsIToken(2));
                    OCLExpressionCS left = (OCLExpressionCS)getRhsSym(1);
                    OCLExpressionCS right = (OCLExpressionCS)getRhsSym(3);
                    EList<OCLExpressionCS> args = new BasicEList<OCLExpressionCS>();
                    args.add(right);
                    OperationCallExpCS result = createOperationCallExpCS(
                            left,
                            simpleNameCS,
                            args
                        );
                    setOffsets(result, left, right);
                    setResult(result);
          $EndCode
        ./

    unaryNotLetCS -> unaryNotNameNotLetCS
    unaryNotLetCS -> SimpleNameExpCS
    unaryNotNameNotLetCS -> primaryNotNameCS
    unaryNotNameNotLetCS ::= '-' unaryNotLetCS
        /.$NewCase./
    unaryNotNameNotLetCS ::= not unaryNotLetCS
        /.$NewCase./
    unaryWithLetCS -> LetExpCS             -- OclExpressionCS[D]
    unaryWithLetCS ::= '-' unaryWithLetCS
        /.$NewCase./
    unaryWithLetCS ::= not unaryWithLetCS
        /.$BeginCode
                    SimpleNameCS simpleNameCS = createSimpleNameCS(
                                SimpleTypeEnum.KEYWORD_LITERAL,
                                getRhsIToken(1)
                            );
                    setOffsets(simpleNameCS, getRhsIToken(1));
                    OCLExpressionCS expr = (OCLExpressionCS)getRhsSym(2);
                    OperationCallExpCS result = createOperationCallExpCS(
                            expr,
                            simpleNameCS,
                            new BasicEList<OCLExpressionCS>()
                        );
                    setOffsets(result, simpleNameCS, expr);
                    setResult(result);
          $EndCode
        ./

    primaryExpCS -> primaryNotNameCS
    primaryExpCS -> SimpleNameExpCS

    primaryNotNameCS -> CallExpCS       -- OclExpressionCS[A]
    primaryNotNameCS -> VariableExpCS   -- OclExpressionCS[B]
    primaryNotNameCS -> LiteralExpCS    -- OclExpressionCS[C]
--  primaryNotNameCS -> OclMessageExpCS -- OclExpressionCS[E] is added by Complete OCL
    primaryNotNameCS -> IfExpCS         -- OclExpressionCS[F]
    primaryNotNameCS ::= '(' OclExpressionCS ')'
        /.$BeginCode
                    OCLExpressionCS result = (OCLExpressionCS)getRhsSym(2);
                    if (result instanceof OperationCallExpCS) {
                        ((OperationCallExpCS)result).setIsAtomic(true);
                    }
                    setOffsets(result, getRhsIToken(1), getRhsIToken(3));
                    setResult(result);
          $EndCode
        ./

    IfExpCS ::= if OclExpressionCS then OclExpressionCS else OclExpressionCS endif
        /.$BeginCode
                    IfExpCS result = createIfExpCS(
                            (OCLExpressionCS)getRhsSym(2),
                            (OCLExpressionCS)getRhsSym(4),
                            (OCLExpressionCS)getRhsSym(6)
                        );
                    setOffsets(result, getRhsIToken(1), getRhsIToken(7));
                    setResult(result);
          $EndCode
        ./

    LetExpCS ::= let letVariablesCS in OclExpressionCS
        /.$BeginCode
                    OCLExpressionCS expr = (OCLExpressionCS)getRhsSym(4);
                    LetExpCS result = createLetExpCS(
                            (EList<VariableCS>)getRhsSym(2),
                            expr
                        );
                    setOffsets(result, getRhsIToken(1), expr);
                    setResult(result);
          $EndCode
        ./

    letVariablesCS ::= typedInitializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = new BasicEList<VariableCS>();
                    result.add((VariableCS)getRhsSym(1));
                    setResult(result);
          $EndCode
        ./
    letVariablesCS ::= letVariablesCS ',' typedInitializedVariableCS
        /.$BeginCode
                    EList<VariableCS> result = (EList<VariableCS>)getRhsSym(1);
                    result.add((VariableCS)getRhsSym(3));
                    setResult(result);
          $EndCode
        ./
%End


text:
# We keep only primitive pythagorean triples
pyth := n ->
  Filtered(Cartesian([1 .. n], [1 .. n], [1 .. n]),
  u -> u[3]^2 = u[1]^2 + u[2]^2 and u[1] < u[2]
  and GcdInt(u[1], u[2]) = 1);

pyth(100);
# [ [ 3, 4, 5 ], [ 5, 12, 13 ], [ 7, 24, 25 ], [ 8, 15, 17 ], [ 9, 40, 41 ], [ 11, 60, 61 ], [ 12, 35, 37 ],
#   [ 13, 84, 85 ], [ 16, 63, 65 ], [ 20, 21, 29 ], [ 28, 45, 53 ], [ 33, 56, 65 ], [ 36, 77, 85 ], [ 39, 80, 89 ],
#   [ 48, 55, 73 ], [ 65, 72, 97 ] ]

ext: gap

max_issues_repo_name: seanwallawalla-forks/RosettaCodeData

max_forks_repo_name: seanwallawalla-forks/RosettaCodeData


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

# Don't forget to Import(platforms.cellSPU)

#F _svctSizes(N, p, v). Uptil N, multiples of p, vectorsize=v
#F Eg: spu_4x32f_medium uses _svctSizes(1024, 16, 4);
_svctSizes := (N, p, v) -> Filtered([1..N], i->ForAll(Factors(i), j->j<=p) and IsInt(i/v^2));

#F _svctSizes(N, p, v, from). Uptil N, multiples of p, vectorsize=v, beginning with from
#F Eg: spu_4x32f_medium uses _svctSizes(1024, 16, 4, 96);
_svctSizesFrom := (N, p, v, low) -> Filtered([low..N], i->ForAll(Factors(i), j->j<=p) and IsInt(i/v^2));

_defaultSizes := (func, default) -> ((arg) -> When(Length(arg) = 1, func(When(IsList(arg[1]), arg[1], [arg[1]])), func(default)));

Class(cellopts, rec(
#    ic := rec(oddSizes := false, svct := true, tsplRader:=false, tsplBluestein:=false,
#              splitL := false, pushTag := true, flipIxA := false,
#              stdTTensor := true, tsplPFA := false, interleavedComplex := true),
#
#    sc := rec(oddSizes := false, svct := true, tsplRader:=false, tsplBluestein:=false,
#              splitL := false, pushTag := true, flipIxA := false,
#              stdTTensor := true, tsplPFA := false, interleavedComplex := false)
sc := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := false),
ic := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := true),
));

Class(cellOpts, rec(
            2x64f := rec(
                dft_sc := rec(
                    small :=  rec(verify:=true, tsplBluestein:=false, interleavedComplex := false, PRDFT:=true, URDFT:= true, cplxVect := true, stdTTensor := false, globalUnrolling:=10000),
                    medium := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := false),
                ),
                dft_ic := rec(
                    small := rec(verify:=true, tsplBluestein:=false, interleavedComplex := true, PRDFT:=true, URDFT:= true, cplxVect := true, stdTTensor := false, globalUnrolling:=10000),
                    medium := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := true),
                )
            ),
            4x32f := rec(
                dft_sc := rec(
                    small := rec(verify:=true, interleavedComplex := false, stdTTensor := false, globalUnrolling:=10000),
                    medium := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := false),
                ),
                dft_ic := rec(
                    small := rec(verify:=true, interleavedComplex := true, stdTTensor := false, globalUnrolling:=10000),
                    medium := rec(tsplRader:=false, tsplBluestein:=false, tsplPFA:=false, oddSizes:=false, interleavedComplex := true),
                )
            )
));

benchSPU := function()
    if LocalConfig.cpuinfo.SIMD().hasSPU() then
        return rec(
            2x64f := rec(
                1d := rec(
                    dft_sc := rec(
                        small := _defaultSizes(s->doSimdDft(s, spu_2x64f, cellOpts.2x64f.split.small), [ 2..32 ]),
                        medium := _defaultSizes(s->doSimdDft(s, spu_2x64f, cellOpts.2x64f.split.medium), _svctSizes(1024, 16, 2)),
#                        medium := spiral.libgen.doParSimdDft(spu_2x64f, 1, _svctSizes(1024, 16, 4), false, true, false, false),
#                        large := spiral.libgen.doParSimdDft(spu_2x64f, 1, List([4..20], i->2^i), false, true, false, false)

                    ),
                    dft_ic := rec(
                        small := _defaultSizes(s->doSimdDft(s, spu_2x64f,  cellOpts.2x64f.dft_ic.small), [2..32]),
                        medium := _defaultSizes(s->doSimdDft(s, spu_2x64f, cellOpts.2x64f.dft_ic.medium), _svctSizes(1024, 16, 2)),
#                        medium := spiral.libgen.doParSimdDft(spu_2x64f, 1, _svctSizes(1024, 16, 4), false, true, false, true),
#                        large := spiral.libgen.doParSimdDft(spu_2x64f, 1, List([4..20], i->2^i), false, true, false, true)
                    ),
                    rdft := _defaultSizes(s->doSimdSymDFT(TRDFT, s, spu_2x64f, rec(verify :=true)), 32*[1..12]),
                    dht  := _defaultSizes(s->doSimdSymDFT(TDHT,  s, spu_2x64f, rec(verify :=true)), 8*[1..12]),
                    dct2 := _defaultSizes(s->doSimdSymDFT(TDCT2, s, spu_2x64f, rec(verify :=true)), 32*[1..12]),
                    dct3 := _defaultSizes(s->doSimdSymDFT(TDCT3, s, spu_2x64f, rec(verify :=true)), 32*[1..12]),
                    dct4 := _defaultSizes(s->doSimdSymDFT(TDCT4, s, spu_2x64f, rec(verify :=true)), 32*[1..12]),
                    dst2 := _defaultSizes(s->doSimdSymDFT(TDST2, s, spu_2x64f, rec(verify :=true)), 8*[1..12]),
                    dst3 := _defaultSizes(s->doSimdSymDFT(TDST3, s, spu_2x64f, rec(verify :=true)), 8*[1..12]),
                    dst4 := _defaultSizes(s->doSimdSymDFT(TDST4, s, spu_2x64f, rec(verify :=true)), 8*[1..12])
                ),
                2d := rec(
                    dft_ic := rec(
                        medium := _defaultSizes(s->doSimdMddft(s, spu_2x64f, rec(interleavedComplex := true,
                                    oddSizes := false, svct := true, splitL := false, pushTag := true, flipIxA := false, stdTTensor := true, tsplPFA := false)),
                                    4*List([1..16], i->[i,i])),
                        small := _defaultSizes(s->doSimdMddft(s, spu_2x64f, rec(verify:=true, interleavedComplex := true, globalUnrolling:=10000,
                                    tsplPFA := false, pushTag:= false, oddSizes := true, svct := true, splitL := false)),
                                    List([2..16], i->[i,i]))
                    ),
                    dft_sc := rec(
                        medium := _defaultSizes(s->doSimdMddft(s, spu_2x64f, rec(interleavedComplex := false,
                                    oddSizes := false, svct := true, splitL := false, pushTag := true, flipIxA := false, stdTTensor := true, tsplPFA := false)),
                                    4*List([1..16], i->[i,i])),
                        small := _defaultSizes(s->doSimdMddft(s, spu_2x64f, rec(verify:=true, interleavedComplex := false, globalUnrolling:=10000,
                                    tsplPFA := false, pushTag:= false, oddSizes := true, svct := true, splitL := false)),
                                    List([2..16], i->[i,i]))
                    ),
                    dct2 := _defaultSizes(s->doSimdSymMDDFT(DCT2, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16]),
                    dct3 := _defaultSizes(s->doSimdSymMDDFT(DCT3, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16]),
                    dct4 := _defaultSizes(s->doSimdSymMDDFT(DCT4, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16]),
                    dst2 := _defaultSizes(s->doSimdSymMDDFT(DST2, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16]),
                    dst3 := _defaultSizes(s->doSimdSymMDDFT(DST3, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16]),
                    dst4 := _defaultSizes(s->doSimdSymMDDFT(DST4, s, spu_2x64f, rec(verify := true)), [4, 8, 12, 16])
                ),
            ),
            4x32f := rec(
                1d := rec(
                    dft_sc := rec(
                        small := _defaultSizes(s->doSimdDft(s, spu_4x32f, cellOpts.4x32f.dft_sc.small), [ 2..64 ]),
                        medium := _defaultSizes(s->doSimdDft(s, spu_4x32f, cellOpts.4x32f.dft_sc.medium), _svctSizes(1024, 16, 4)),
#                        medium := spiral.libgen.doParSimdDft(spu_4x32f, 1, _svctSizes(1024, 16, 4), false, true, false, false),
#                        large := spiral.libgen.doParSimdDft(spu_4x32f, 1, List([4..20], i->2^i), false, true, false, false)

                    ),
                    dft_ic := rec(
                        small := _defaultSizes(s->doSimdDft(s, spu_4x32f, cellOpts.4x32f.dft_ic.small), [ 2..64 ]),
                        medium := _defaultSizes(s->doSimdDft(s, spu_4x32f, cellOpts.4x32f.dft_ic.medium), _svctSizes(1024, 16, 4))
#                        medium := spiral.libgen.doParSimdDft(spu_4x32f, 1, _svctSizes(1024, 16, 4), false, true, false, true),
#                        large := spiral.libgen.doParSimdDft(spu_4x32f, 1, List([4..20], i->2^i), false, true, false, true)
                    ),
                    rdft := _defaultSizes(s->doSimdSymDFT(TRDFT, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dht  := _defaultSizes(s->doSimdSymDFT(TDHT,  s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dct2 := _defaultSizes(s->doSimdSymDFT(TDCT2, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dct3 := _defaultSizes(s->doSimdSymDFT(TDCT3, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dct4 := _defaultSizes(s->doSimdSymDFT(TDCT4, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dst2 := _defaultSizes(s->doSimdSymDFT(TDST2, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dst3 := _defaultSizes(s->doSimdSymDFT(TDST3, s, spu_4x32f, rec(verify :=true)), 32*[1..12]),
                    dst4 := _defaultSizes(s->doSimdSymDFT(TDST4, s, spu_4x32f, rec(verify :=true)), 32*[1..12])
                ),

                2d := rec(
                    dft_ic := rec(
                        medium := _defaultSizes(s->doSimdMddft(s, spu_4x32f, rec(interleavedComplex := true,
                                    oddSizes := false, svct := true, splitL := false, pushTag := true, flipIxA := false, stdTTensor := true, tsplPFA := false)),
                                    16*List([1..5], i->[i,i])),
                        small := _defaultSizes(s->doSimdMddft(s, spu_4x32f, rec(verify:=true, interleavedComplex := true, globalUnrolling:=10000,
                                    tsplPFA := false, pushTag:= false, oddSizes := true, svct := true, splitL := false)),
                                    List([2..16], i->[i,i]))
                    ),
                    dft_sc := rec(
                        medium := _defaultSizes(s->doSimdMddft(s, spu_4x32f, rec(interleavedComplex := false,
                                    oddSizes := false, svct := true, splitL := false, pushTag := true, flipIxA := false, stdTTensor := true, tsplPFA := false)),
                                    16*List([1..5], i->[i,i])),
                        medium128 := _defaultSizes(s->doSimdMddft(s, spu_4x32f, rec(interleavedComplex := false,
                                    oddSizes := false, svct := true, splitL := false, pushTag := true, flipIxA := false, stdTTensor := true, tsplPFA := false)),
                                    16*List([4], i->[8,i])),
                        small := _defaultSizes(s->doSimdMddft(s, spu_4x32f, rec(verify:=true, interleavedComplex := false, globalUnrolling:=10000,
                                    tsplPFA := false, pushTag:= false, oddSizes := true, svct := true, splitL := false)),
                                    List([2..16], i->[i,i]))
                    ),
                    dct2 := _defaultSizes(s->doSimdSymMDDFT(DCT2, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16]),
                    dct3 := _defaultSizes(s->doSimdSymMDDFT(DCT3, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16]),
                    dct4 := _defaultSizes(s->doSimdSymMDDFT(DCT4, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16]),
                    dst2 := _defaultSizes(s->doSimdSymMDDFT(DST2, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16]),
                    dst3 := _defaultSizes(s->doSimdSymMDDFT(DST3, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16]),
                    dst4 := _defaultSizes(s->doSimdSymMDDFT(DST4, s, spu_4x32f, rec(verify := true)), [4, 8, 12, 16])
                )
            ),
        );
    else
        return false;
    fi;
end;

ext: gi


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

Class(DWT, NonTerminal, DataNonTerminalMixin, rec(
    abbrevs := [
       (n,w) -> Checked(IsPosInt(n), IsEvenInt(n), n>=2, IsList(w), Length(w)=2,
	   [n, toFiltFunc(w[1]), toFiltFunc(w[2])]),
       (n,g,h) -> Checked(IsPosInt(n), IsEvenInt(n), n>=2,
	   [n, toFiltFunc(g), toFiltFunc(h)]),
    ],
    isReal := self >> true,

    setData := meth(self, gdata, hdata)
       self.params[2][1] := gdata; self.params[3][1] := hdata; return self;
    end,

    dims := self >> let(n:=self.params[1], k:=self.params[2][1].domain(),
                        [n, n + k - 2]),

    terminate := self >> let(
	n := self.params[1],
	g := self.params[2],
	h := self.params[3],
	VStack(Filt(n/2,g[1],g[2],2).terminate(), Filt(n/2,h[1],h[2],2).terminate())),

    HashId := self >> [ self.params[1], self.params[2][1].domain() ]
));

KnownCoeffs := filtfunc -> ObjId(filtfunc[1])=FList or
                           (ObjId(filtfunc[1])=FData and IsBound(filtfunc[1].var.value));

RulesFor(DWT, rec(
    #F DWT_Base: (base case)
    #F
    #F Computes DWT by definition
    #F
    DWT_Filt := rec(
	forTransposition := true,
	limit            := -1, # means no limit
	isApplicable     := (self, P) >> When(self.limit < 0, true,
	    P[1] <= self.limit or P[2][1].domain() <= self.limit),

	allChildren := P -> let(n := P[1], g := P[2], h := P[3],
	    [[ Filt(n/2,g[1],g[2],2), Filt(n/2,h[1],h[2],2) ]]),

	rule := (P, C) -> VStack(C[1], C[2])
    ),

    DWT_Base2 := rec(
	isApplicable := P -> true,
	rule := (P, C) -> let(n := P[1], g := P[2][1].tolist(), h := P[3][1].tolist(),
	    diff := Length(h) - Length(g),
	    gg := Cond(diff <= 0, g, Concatenation(g, Replicate(diff,0))),
	    hh := Cond(diff >= 0, h, Concatenation(h, Replicate(-diff,0))),
	    k := Maximum(Length(g), Length(h)),
	    When(n=1, Mat([gg,hh]), L(n,2)*RowTensor(n/2,k-2,Mat([gg,hh]))))
    ),

    DWT_Base4 := rec(
	isApplicable := P -> P[1] mod 4 = 0,
	rule := (P, C) -> let(n := P[1], g := P[2][1].tolist(), h := P[3][1].tolist(),
	    diff := Length(h) - Length(g),
	    gg := Cond(diff <= 0, g, Concatenation(g, Replicate(diff,0))),
	    hh := Cond(diff >= 0, h, Concatenation(h, Replicate(-diff,0))),
	    k := Maximum(Length(g), Length(h)),
	    When(n=1, Mat([gg,hh]), L(n,2)*RowTensor(n/4,k-2,BB(RowTensor(2,k-2,Mat([gg,hh]))))))
    ),
    DWT_Base8 := rec(
	isApplicable := P -> P[1] mod 8 = 0,
	rule := (P, C) -> let(n := P[1], g := P[2][1].tolist(), h := P[3][1].tolist(),
	    diff := Length(h) - Length(g),
	    gg := Cond(diff <= 0, g, Concatenation(g, Replicate(diff,0))),
	    hh := Cond(diff >= 0, h, Concatenation(h, Replicate(-diff,0))),
	    k := Maximum(Length(g), Length(h)),
	    When(n=1, Mat([gg,hh]), L(n,2)*RowTensor(n/8,k-2,BB(RowTensor(4,k-2,Mat([gg,hh]))))))
    ),

    #F DWT_Lifting: lifting steps, does not work yet
    #F
    DWT_Lifting := rec(
        info             := "DWT(n,g,h) -> Lifting steps",
        forTransposition := false,
        isApplicable     := P -> P[1]>2 and P[1] mod 2 =0 and KnownCoeffs(P[2]),
	switch := false,
        allChildren := function ( P )
            local n,g,h,vg,vh, lift_schemes,children,scheme,step,filts,pol;
            n       := P[1];
	    [g, h]  := [List(P[2][1].tolist(), EvalScalar), List(P[3][1].tolist(), EvalScalar)];
	    [vg,vh] := [P[2][2], P[3][2]];

            lift_schemes := Copy(HashLookupWav(HashTableWavelets, [[g,h],[vg,vh]]));
	    children := [];

            for scheme in lift_schemes do
	        filts := [];
	        for step in Drop(scheme,1) do
		    pol := FillZeros(ListPoly(step));
		    Add(filts, Filt(n/2, pol[1], pol[2]));
		od;
                # attach the indicator of the type of the first liftings step
		filts[1].lift := scheme[1];
		Add(children, filts);
            od;
            return children;
        end,

        rule := function ( P, C, Nonterms )
            local n, i, ind, b, l, M, ind0, ind1, lstep;
            n := P[1];
            b := Nonterms[1].lift;
            l:=Length(C);

	    ind0 := fTensor(fBase(2,0), fId(Rows(C[3])));
	    ind1 := fTensor(fBase(2,1), fId(Rows(C[3])));
	    lstep := (f,b) -> When(b=0,
		LStep(Scat(ind0) * f * Gath(ind1)),
		LStep(Scat(ind1) * f * Gath(ind0)));

            M := When(b < 0,
		SUM(Scat(ind0)*C[2]*Gath(ind1), Scat(ind1)*C[1]*Gath(ind0)),
		SUM(Scat(ind0)*C[2]*Gath(ind0), Scat(ind1)*C[1]*Gath(ind1)));

	    b := (b+2) mod 2; # make b positive
	    for i in [1 .. l-2] do
	        M := M * lstep(C[i+2], b);
		b := (b+1) mod 2;
            od;

	    return M.child(1) * Inplace(Compose(Drop(M.children(),1))) * L(n,2);
       end
    )
));


text:
# Copyright (c) 2018-2020, Carnegie Mellon University
# See LICENSE for details
#
# n-qubit Y transforms
#

#F qYT( n ) - Y Gate non-terminal
#F Definition: (2^n x 2^n)-matrix  that applies an n-point Y Transform to the target qubits
#F Note:       qYT(1) denotes the matrix[[0, -i], [i, 0]],
#F             qYT(_) is not symmetric.
#F
#F qYT( n ) -> an n-qubit Y transform
Class(qYT, TaggedNonTerminal, rec(
  abbrevs   := [ n -> Checked(IsPosInt(n), [n]) ],
  dims      := self >> let(size := 2^self.params[1], [size, size]),
  terminate := self >> Tensor(Replicate(self.params[1], qX())),
  isReal    := self >> true,
  groups    := self >> [Replicate(self.params[1], 1)],
  rChildren := self >> self.params,
  from_rChildren := (self, rch) >> self.__bases__[1](rch[1]),
  recursive_def := (self, arch) >> self.__bases__[1](self.params[1]),
  connected := self >> true,
  SmallRandom := () -> Random([2..5]),
  LargeRandom := () -> Random([6..15]),
  normalizedArithCost := self >> Error("ArithCost not implemented"),
  TType := T_Complex(64),
));

NewRulesFor(qYT, rec(

    # qYT_BinSplit rule
    # qYT_BinSplit qYT_(k) -> (qYT_(k1) tensor I) (I tensor qYT_(k2))
    # k1 + k2 = k
    qYT_BinSplit := rec (
        forTransposition := false,
        minSize          := 2,
        applicable       := (self, nt) >> nt.params[1] > 1,
        children         := nt -> List( [1..nt.params[1] - 1],  i -> [ Tensor(qYT(i), qYT(nt.params[1]-i)).withTags(nt.getTags()) ]  ),
        apply            := (nt, c, cnt) -> c[1],
        switch := true,
    ),

    #F qYT_Base: qYT(1) = qY() SPL object
    #F Directly represent as an implementable gate
    qYT_Base := rec(
        info             := "qYT_(1) -> qY()",
        forTransposition := false,
        applicable       := (self, nt) >> nt.params[1]=1,
        apply            := (nt, c, cnt) -> qY(),
    )

));

max_stars_repo_name: spiral-software/spiral-package-quantum

max_issues_repo_name: spiral-software/spiral-package-quantum

max_forks_repo_name: spiral-software/spiral-package-quantum


text:
#
#
#

Read("~/Workspace/Chevalley.gap/init.gi");

Read(Filename(home_dir,"lib/rsys.gd"));
Read(Filename(home_dir,"lib/rsys.gi"));

Read(Filename(home_dir,"lib/chvadj.gd"));
Read(Filename(home_dir,"lib/chvadj.gi"));


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

_printattr := x->When((x=[] and TYPE(x)="string") or (x<>[] and IsString(x)), Print("\"", x, "\""), Print(x));

attrTakeA  := (to, from) -> When(IsRec(to) and IsBound(to.takeAobj), to.takeAobj(from), to);

Class(AttrMixin, rec(
    a := rec(),

    setA := meth(arg)
        local self, i, a, f, val;
        a := rec();
        self := arg[1];
        for i in [2..Length(arg)] do
            if IsVarMap(arg[i]) then
                f := NameOf(arg[i][1]);
                val := Eval(arg[i][2]);
                a.(f) := val;
            elif IsList(arg[i]) and Length(arg[i]) in [0,2] then
                if Length(arg[i])>0 then
                    [f, val] := arg[i];
                    a.(f) := val;
                fi;
            else return Error("arg[i] must be a list or varmap");
            fi;
        od;
        return CopyFields(self, rec(a:=a));
    end,

    withA := meth(arg)
        local self, res, set;
        self := arg[1];
        set := self.setA;
        res := ApplyFunc(set, arg);
        res.a := CopyFields(self.a, res.a);
        return res;
    end,

    hasA := (self, attr) >> Cond(IsBound(self.a.(attr)), true, false),

    # getA(<attr>, <def> = false) - returns attribute value.
    #   Optional <def> parameter is value to return when attribute is not found.

    getA := (arg) >> let( self := arg[1], attr := arg[2],
                        def := When(Length(arg)>2, arg[3], false),
                        Cond(IsBound(self.a.(attr)), self.a.(attr), def)),

    printA := self >> let(flds := UserRecFields(self.a),
        Cond(flds=[], Print(""),
             Print(".setA(",
                 DoForAllButLast(flds, x->Print(x, " => ", _printattr(self.a.(x)), ", ")),
                 Last(flds), " => ", _printattr(self.a.(Last(flds))), ")"))),

    takeA   := meth(self, a) self.a := CopyFields(a); return self; end,

    appendA := meth(self, a) self.a := CopyFields(self.a, a); return self; end,

    takeAobj   := meth(self, obj) self.a := CopyFields(obj.a); return self; end,

    appendAobj   := meth(self, obj) self.a := CopyFields(self.a, obj.a); return self; end,

    attrs := ~.takeAobj,

    # testA( attr, v = true ) returns true if object has attribute <attr> with value equal to <v>

    testA := (arg) >> let( self := arg[1], attr := arg[2],
        v := When(IsBound(arg[3]), arg[3], true),
        self.hasA(attr) and self.getA(attr) = v),

    dropA := meth(arg)
        local obj, d, s;
        obj := ShallowCopy(arg[1]);
        d   := Drop(arg, 1);
        if Length(arg)=1 then
            Unbind(obj.a);
        elif ForAll(d, IsString) then
            obj.a := ShallowCopy(obj.a);
            for s in d do Unbind(obj.a.(s)); od;
        else
            Error("Usage: dropA([ <attr_name_string>[, <attr_name_string>[, ...]] ])");
        fi;
        return obj;
    end,

    # listA() returns list of attribute names and values in [[name, value],...] form.

    listA := (self) >> List(Sort(UserRecFields(self.a)), e -> [e, self.a.(e)]),
));


text:
#
# Interprets GAP MathInTheMiddle OpenMath into GAP functions
#

# Make records indicating success or failure
InstallGlobalFunction(MitM_Error,
function(str...)
    return rec(success := false, error := Concatenation(str));
end);

InstallGlobalFunction(MitM_Result,
function(obj)
    return rec(success := true, result := obj);
end);

InstallMethod(MitM_OMRecToGAP, [MitM_OMRecRep],
function(r)
    local val, res;
    val := MitM_IsValidOMRec(r);
    if val <> true then
        return MitM_Error(val);
    fi;
    res := MitM_OMRecToGAPNC(r);
    if res.success <> true then
        return res;
    fi;
    return MitM_Result(EvalString(res.result));
end);

InstallGlobalFunction(MitM_OMRecToGAPNC,
function(r)
    return MitM_EvalToFunction.(MitM_Tag(r))(r);
end);

# Primitives for GAP
BindGlobal("MitM_GAP_PrimitivesFunc", rec(
     ListConstr := "({args...} -> args)",
     RecConstr := "(function(args...) local r,i; r := rec(); for i in [1,3..Length(args)-1] do r.(args[i]) := args[i+1]; od; return r; end)",
     PermConstr := "({args...} -> PermList(args))",
     # TODO: PermBytesConstr
     BoolConstr := "({args...} -> EvalString(args[1]))",
     CharConstr := "({args...} -> args[1][1])",
     FFEConstr := "({args...} -> Sum([0..args[2]-1], i -> args[i+3] * Z(args[1], args[2]) ^ i))",
) );

MitM_Evaluate := function(node)
    return node;
end;

MitM_get_allowed_heads := function()
    return OMA( OMS( "scscp1", "symbol_set" )
              , OMS( "scscp_transient_1", "MitM_Evaluate" )
              , OMS( "scscp_transient_1", "MitM_Quit" )
              , OMS( MitM_cdbase, "lib", "MitM_Evaluate" ) );
end;

BindGlobal("MitM_CDDirectory",
rec( ( "default" ) := function(node)
       if MitM_CD(node) = "scscp2" then
           if MitM_Name(node) = "get_allowed_heads" then
               return MitM_Result( "MitM_get_allowed_heads" );
           else
               return MitM_Error("name \"", MitM_Name(node), "\" not supported");
           fi;
       elif MitM_CD(node) = "scscp_transient_1" then
           if MitM_Name(node) = "MitM_Evaluate" then
               return MitM_Result("MitM_Evaluate");
           elif MitM_Name(node) = "MitM_Quit" then
               QUIT_GAP(0);
           fi;
       else
           return MitM_Error("cd \"", MitM_CD(node), "\" not supported");
       fi;
     end,
     ( MitM_cdbase ) := function(node)
         local name;
         name := MitM_Attributes(node).name;
         if MitM_CD(node) = "prim" then
             if not name in RecNames(MitM_GAP_PrimitivesFunc) then
                 return MitM_Error("OMS name \"", name,
                                   "\" not a GAP primitive function");
             fi;
             return MitM_Result(MitM_GAP_PrimitivesFunc.(name));
         elif MitM_CD(node) = "lib" then
             if not IsBoundGlobal(name) then
                 return MitM_Error("OMS name \"", name,
                                   "\" not a GAP library function");
             fi;
             return MitM_Result(name);
         else
             return MitM_Error("cd \"", MitM_CD(node)
                               , "\" not supported");
         fi;
     end,
) );

# Evaluators for OpenMath objects
InstallValue(MitM_EvalToFunction, rec(
     OMOBJ := function(node)
         return MitM_OMRecToGAPNC(MitM_Content(node)[1]);
     end,

     OMS := function(node)
         local name, sym;

         if MitM_CDBase(node) = fail then
             return MitM_CDDirectory.("default")(node);
         elif IsBound(MitM_CDDirectory.(MitM_CDBase(node))) then
             return MitM_CDDirectory.(MitM_CDBase(node))(node);
         else
             return MitM_Error("cdbase \"", MitM_CDBase(node)
                               , "\" is not supported");
         fi;
     end,

     OMV := node -> MitM_Result(StringFormatted("{}",
                                                MitM_Name(node))),
     OMI := function(node)
         local v;
         v := ShallowCopy(MitM_Content(node)[1]);
         RemoveCharacters(v, WHITESPACE);
         if Position(MitM_Content(node)[1], 'x') <> fail then
             RemoveCharacters(v, "x");
             return MitM_Result(String(IntHexString(v)));
         else
             return MitM_Result(v);
         fi;
     end,

     OMB := node -> MitM_Result(StringFormatted("\"{}\"", MitM_Content(node)[1])),

     OMSTR := function(node)
         local str;
         if IsEmpty(MitM_Content(node)) then
             str := "";
         else
             str := MitM_Content(node)[1];
         fi;
         return MitM_Result(StringFormatted("({} -> \"{}\")()", "{}", str));
     end,

     OMF := function(node)
         if IsBound(MitM_Attributes(node).dec) then
             return MitM_Result(String(Float(MitM_Attributes(node).dec)));
         else
             return MitM_Error("OMF: hex encoding not supported");
         fi;
     end,

     OMA := function(node)
         local sym, args, item, r;

         sym := MitM_OMRecToGAPNC(MitM_Content(node)[1]);
         if sym.success <> true then
             return MitM_Error("OMA contents: ", sym.error);
         fi;
         args := [];
         for item in MitM_Content(node){[2..Length(MitM_Content(node))]} do
             r := MitM_OMRecToGAPNC(item);
             if r.success <> true then
                 return MitM_Error("OMA contents: ", r.error);
             elif MitM_Name(item) = "OMV" then
                 # Interpret string as variable
                 Add(args, EvalString(r.result));
             else
                 Add(args, r.result);
             fi;
         od;
         return MitM_Result(Concatenation(sym.result, "(",
                                          JoinStringsWithSeparator(args, ","),
                                          ")"));
     end,

     OMBIND := function(node)
         local list, val;

         if not (MitM_CD(MitM_Content(node)[1]) = "prim" and
                 MitM_Name(MitM_Content(node)[1]) = "lambda") then
             return MitM_Error("only the lambda binding is implemented");
         fi;
         list := List(MitM_Content(MitM_Content(node)[2]), MitM_Name);
         val := MitM_OMRecToGAPNC(MitM_Content(node)[3]);
         if val.success <> true then
             return MitM_Error("OMBIND contents: ", val.error);
         fi;
         return MitM_Result(Concatenation( "function(",
                                           JoinStringsWithSeparator(list, ","),
                                           ") return ",
                                           val.result,
                                           ";  end" ));
     end,

     OMATTR := function(node)
         return MitM_OMRecToGAPNC(MitM_Content(node)[2]);
     end,

     OME := function(node)
         # TODO: Error handling?
         Print("Error: ", List(MitM_Content(node){[2..Length(MitM_Content(node))]},
                               MitM_OMRecToGAPNC), "\n");
     end,

#     OMR := function(node)
#     end,
    ) );

max_stars_repo_name: markuspf/MathsInTheMiddle

max_issues_repo_name: markuspf/MathsInTheMiddle

max_forks_repo_name: markuspf/MathsInTheMiddle


text:
#
# walrus: Computational Methods for Finitely Generated Monoids and Groups
#

InstallGlobalFunction(NewPregroupWord,
function(pg, word)
    local maxk, rel;
    maxk := MaxPowerK(word);
    return Objectify(IsPregroupRelatorType,
                     rec( pregroup := pg
                        , base := maxk[1]
                        , exponent := maxk[2]
                        , baselen := Length(maxk[1]) ) );
end);

InstallGlobalFunction(NewPregroupRelator,
function(pres, word, id)
    local maxk, rel;
    maxk := MaxPowerK(word);
    rel := Objectify(IsPregroupRelatorType,
                     rec( pres := pres
                        , base := maxk[1]
                        , exponent := maxk[2]
                        , baselen := Length(maxk[1])
                        , __ID := id)
                    );
    return rel;
end);

InstallMethod(Base, "for a pregroup relator",
              [IsPregroupRelator and IsPregroupRelatorRep ],
              r -> r!.base);

InstallMethod(Exponent, "for a pregroup relator",
              [IsPregroupRelator and IsPregroupRelatorRep ],
              r -> r!.exponent);

InstallMethod(Inverse, "for a pregroup relator",
              [ IsPregroupRelator and IsPregroupRelatorRep ],
              r -> Objectify(IsPregroupRelatorType,
                             rec( pres := r!.pres
                                , base := List(Reversed(r!.base), PregroupInverse)
                                , exponent := r!.exponent
                                , baselen := r!.baselen
                                , __ID := -r!.__ID)
                            ));
InstallMethod(PregroupPresentationOf,
              "for pregroup relators",
              [IsPregroupRelator],
              r -> r!.pres);

InstallMethod(Locations, "for a pregroup relator",
              [IsPregroupRelator],
function(r)
    return List([1..r!.baselen], i -> NewLocation(r, i));
end);

InstallMethod(\[\], "for a pregroup relator",
              [IsPregroupRelator and IsPregroupRelatorRep, IsInt],
function(r, p)
    local i, l;
    i := RemInt(p - 1, r!.baselen);
    if i < 0 then
        i := i + r!.baselen;
    fi;
    return r!.base[i + 1];
end);

InstallMethod(Length, "for a pregroup relator",
    [ IsPregroupRelator and IsPregroupRelatorRep ],
function(r)
    return r!.baselen * r!.exponent;
end);

# we could possibly store this on creation
# But this is run at most once anyway
InstallMethod(Places, "for a pregroup relator",
              [ IsPregroupRelator and IsPregroupRelatorRep ],
function(r)
    local P, res;

    res := [];

    for P in Places(PregroupPresentationOf(r)) do
        if Relator(P) = r then
            Add(res, P);
        fi;
    od;
    return res;
end);

InstallMethod(ViewString, "for a pregroup relator",
    [IsPregroupRelator],
function(r)
    if Exponent(r) > 1 then
        return STRINGIFY("<pregroup relator ("
                        , List(r!.base, ViewString)
                        , ")^", r!.exponent, ">");
    else
        return STRINGIFY("<pregroup relator "
                        , List(r!.base, ViewString)
                        , ">");
    fi;
end);

InstallMethod(IsBound\[\], "for a pregroup relator, and an position",
              [IsPregroupRelator, IsInt], ReturnTrue );

InstallMethod(\=, "for a pregroup relator, and a pregroup relator",
              [IsPregroupRelator, IsPregroupRelator],
function(l,r)
    # id is uniqe wrt pregroup presentation. We should probably
    # make a family of relators for each presentation etc
    return l!.__ID = r!.__ID;
    return (l!.exponent = r!.exponent)
           and (l!.base = r!.base);
end);

InstallMethod(\in, "for a generator and a pregroup relator",
              [ IsElementOfPregroup, IsPregroupRelator and IsPregroupRelatorRep],
function(e,r)
    return e in r!.base;
end);

#T redo and move to pregroup files
InstallGlobalFunction(ReduceUPregroupWord,
function(word)
    local rw, rw2, i, j, one;

    if Length(word) = 0 then
        return [];
    fi;

    one := PregroupOf(word[1])[1];
    rw := ShallowCopy(word);

    for i in [2..Length(rw)] do
        if rw[i-1] * rw[i] <> fail then
            rw[i] := rw[i-1] * rw[i];
            rw[i-1] := one;
        fi;
    od;

    i := 1; j := 1;
    rw2 := [];
    while i <= Length(rw) do
        if rw[i] <> one then
            rw2[j] := rw[i];
            j := j + 1;
        fi;
        i := i + 1;
    od;

    return rw2;
end);

max_stars_repo_name: RussWoodroofe/walrus

max_issues_repo_name: RussWoodroofe/walrus

max_forks_repo_name: RussWoodroofe/walrus


text:
# Copyright (c) 2018-2021, Carnegie Mellon University
# See LICENSE for details

BlocksInt := (n, min, max) ->
    List(Filtered([0..Log2Int(max)+1], i -> min <= (2^i) and (2^i) <= max and (2^i) < n), i->2^i);

# ---------
Class(divisorsIntNonTriv, AutoFoldExp, rec(
    ev := self >> DivisorsIntNonTriv(self.args[1].ev()),
    computeType := self >> TList(TInt)
));

Class(oddDivisorsIntNonTriv, AutoFoldExp, rec(
    ev := self >> Filtered(DivisorsIntNonTriv(self.args[1].ev()), IsOddInt),
    computeType := self >> TList(TInt)
));

Class(isPrime, AutoFoldExp, rec(
    ev := self >> let(a:=self.args[1].ev(), IsInt(a) and IsPrime(a)),
    computeType := self >> TBool
));

Class(hasOddDivisors, AutoFoldExp, rec(
    ev := self >> Filtered(DivisorsIntNonTriv(self.args[1].ev()), IsOddInt) <> [],
    computeType := self >> TBool
));

Class(divisorsIntNonSelf, AutoFoldExp, rec(
    ev := self >> [1] :: DivisorsIntNonTriv(self.args[1].ev()),
    computeType := self >> TList(TInt)
));

#F integersBetween(<min>, <max>)
#F    returns a list min..max, as a code object
#F
Class(integersBetween, AutoFoldExp, rec(
    ev := self >> [self.args[1].ev() .. self.args[2].ev()],
    computeType := self >> TList(TInt)
));

#F blocksInt(<n>, <min>, <max>)
#F    returns a list of possible block sizes min..max, as a code object
#F    block sizes is really any integers in the interval, that is less than <n>
#F    it should be defined in autolib .c files separately, depending on strategy, etc
#F    In Spiral, evaluation will use BlocksInt which will try 2-power sized blocks.
#F    This does not need to be consistent with autolib.c implementation.
#F
Class(blocksInt, AutoFoldExp, rec(
    ev := self >> BlocksInt(self.args[1].ev(), self.args[2].ev(), self.args[3].ev()),
    computeType := self >> TList(TInt)
));

# ---------------
# YSV NOTE: Refactor below as above
#
Class(rpDivisorsIntNonTriv, Exp, rec(computeType := self>> TPtr(TInt)));
Class(hasCoprimeFactors, Exp, rec(computeType := self >> TBool));

# ---------------
#DivisorsIntNonTrivSym := n ->
#    Cond(IsSymbolic(n), divisorsIntNonTriv(n), # inert form
#                        DivisorsIntNonTriv(EvalScalar(n))); # computes divisors

#DivisorsIntNonSelfSym := n ->
#    Cond(IsSymbolic(n), divisorsIntNonSelf(n), # inert form
#                        Concatenation([1],DivisorsIntNonTriv(EvalScalar(n)))); # computes divisors

RPDivisorsIntNonTrivSym := n ->
    Cond(IsSymbolic(n), rpDivisorsIntNonTriv(n), # inert form
                        RPDivisorsIntNonTriv(EvalScalar(n))); # computes divisors


text:
# All of this is built-in
Derangements([1 .. 4]);
# [ [ 2, 1, 4, 3 ], [ 2, 3, 4, 1 ], [ 2, 4, 1, 3 ], [ 3, 1, 4, 2 ], [ 3, 4, 1, 2 ], [ 3, 4, 2, 1 ],
#   [ 4, 1, 2, 3 ], [ 4, 3, 1, 2 ], [ 4, 3, 2, 1 ] ]
Size(last);
# 9

NrDerangements([1 .. 4]);
# 9

# An implementation using formula D(n + 1) = n*(D(n) + D(n - 1))
NrDerangementsAlt_memo := [1, 0];
NrDerangementsAlt := function(n)
	if not IsBound(NrDerangementsAlt_memo[n + 1]) then
		NrDerangementsAlt_memo[n + 1] := (n - 1)*(NrDerangementsAlt(n - 1) + NrDerangementsAlt(n - 2));
	fi;
	return NrDerangementsAlt_memo[n + 1];
end;

L := List([0 .. 9]);

PrintArray(TransposedMat([L,
	List(L, n -> Size(Derangements([1 .. n]))),
	List(L, n -> NrDerangements([1 .. n])),
	List(L, NrDerangementsAlt)]));
# [ [       0,       1,       1,       1 ],
#   [       1,       0,       0,       0 ],
#   [       2,       1,       1,       1 ],
#   [       3,       2,       2,       2 ],
#   [       4,       9,       9,       9 ],
#   [       5,      44,      44,      44 ],
#   [       6,     265,     265,     265 ],
#   [       7,    1854,    1854,    1854 ],
#   [       8,   14833,   14833,   14833 ],
#   [       9,  133496,  133496,  133496 ] ]