CASTVisitorPlanBundle.java

  1. /*
  2.  * @cond LICENSE
  3.  * ######################################################################################
  4.  * # LGPL License                                                                       #
  5.  * #                                                                                    #
  6.  * # This file is part of the LightJason AgentSpeak(L++)                                #
  7.  * # Copyright (c) 2015-19, LightJason (info@lightjason.org)                            #
  8.  * # This program is free software: you can redistribute it and/or modify               #
  9.  * # it under the terms of the GNU Lesser General Public License as                     #
  10.  * # published by the Free Software Foundation, either version 3 of the                 #
  11.  * # License, or (at your option) any later version.                                    #
  12.  * #                                                                                    #
  13.  * # This program is distributed in the hope that it will be useful,                    #
  14.  * # but WITHOUT ANY WARRANTY; without even the implied warranty of                     #
  15.  * # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                      #
  16.  * # GNU Lesser General Public License for more details.                                #
  17.  * #                                                                                    #
  18.  * # You should have received a copy of the GNU Lesser General Public License           #
  19.  * # along with this program. If not, see http://www.gnu.org/licenses/                  #
  20.  * ######################################################################################
  21.  * @endcond
  22.  */

  23. package org.lightjason.agentspeak.grammar;

  24. import com.google.common.collect.LinkedHashMultimap;
  25. import com.google.common.collect.Multimap;
  26. import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
  27. import org.apache.commons.lang3.tuple.ImmutablePair;
  28. import org.apache.commons.lang3.tuple.Pair;
  29. import org.lightjason.agentspeak.action.IAction;
  30. import org.lightjason.agentspeak.common.CCommon;
  31. import org.lightjason.agentspeak.common.CPath;
  32. import org.lightjason.agentspeak.common.IPath;
  33. import org.lightjason.agentspeak.error.CIllegalArgumentException;
  34. import org.lightjason.agentspeak.error.CSyntaxErrorException;
  35. import org.lightjason.agentspeak.language.CLiteral;
  36. import org.lightjason.agentspeak.language.CRawTerm;
  37. import org.lightjason.agentspeak.language.ILiteral;
  38. import org.lightjason.agentspeak.language.ITerm;
  39. import org.lightjason.agentspeak.language.execution.IExecution;
  40. import org.lightjason.agentspeak.language.execution.action.CBeliefAction;
  41. import org.lightjason.agentspeak.language.execution.action.CDeconstruct;
  42. import org.lightjason.agentspeak.language.execution.action.CLambdaExpression;
  43. import org.lightjason.agentspeak.language.execution.action.CMultiAssignment;
  44. import org.lightjason.agentspeak.language.execution.action.CProxyAction;
  45. import org.lightjason.agentspeak.language.execution.action.CRawAction;
  46. import org.lightjason.agentspeak.language.execution.action.CRepair;
  47. import org.lightjason.agentspeak.language.execution.action.CSingleAssignment;
  48. import org.lightjason.agentspeak.language.execution.action.CTernaryOperation;
  49. import org.lightjason.agentspeak.language.execution.action.achievement_test.CAchievementGoalLiteral;
  50. import org.lightjason.agentspeak.language.execution.action.achievement_test.CAchievementGoalVariable;
  51. import org.lightjason.agentspeak.language.execution.action.achievement_test.CAchievementRuleLiteral;
  52. import org.lightjason.agentspeak.language.execution.action.achievement_test.CAchievementRuleVariable;
  53. import org.lightjason.agentspeak.language.execution.action.achievement_test.CTestGoal;
  54. import org.lightjason.agentspeak.language.execution.action.achievement_test.CTestRule;
  55. import org.lightjason.agentspeak.language.execution.action.unify.CDefaultUnify;
  56. import org.lightjason.agentspeak.language.execution.action.unify.CExpressionUnify;
  57. import org.lightjason.agentspeak.language.execution.action.unify.CVariableUnify;
  58. import org.lightjason.agentspeak.language.execution.expression.CAtom;
  59. import org.lightjason.agentspeak.language.execution.expression.CProxyReturnExpression;
  60. import org.lightjason.agentspeak.language.execution.expression.EOperator;
  61. import org.lightjason.agentspeak.language.execution.expression.IExpression;
  62. import org.lightjason.agentspeak.language.execution.expression.logical.CUnary;
  63. import org.lightjason.agentspeak.language.execution.expression.numerical.CAdditive;
  64. import org.lightjason.agentspeak.language.execution.expression.numerical.CComparable;
  65. import org.lightjason.agentspeak.language.execution.expression.numerical.CMultiplicative;
  66. import org.lightjason.agentspeak.language.execution.expression.numerical.CPower;
  67. import org.lightjason.agentspeak.language.execution.expression.numerical.CRelational;
  68. import org.lightjason.agentspeak.language.execution.expressionbinary.COperatorAssign;
  69. import org.lightjason.agentspeak.language.execution.expressionunary.CDecrement;
  70. import org.lightjason.agentspeak.language.execution.expressionunary.CIncrement;
  71. import org.lightjason.agentspeak.language.instantiable.plan.CPlan;
  72. import org.lightjason.agentspeak.language.instantiable.plan.IPlan;
  73. import org.lightjason.agentspeak.language.instantiable.plan.annotation.CAtomAnnotation;
  74. import org.lightjason.agentspeak.language.instantiable.plan.annotation.CValueAnnotation;
  75. import org.lightjason.agentspeak.language.instantiable.plan.annotation.IAnnotation;
  76. import org.lightjason.agentspeak.language.instantiable.plan.trigger.CTrigger;
  77. import org.lightjason.agentspeak.language.instantiable.plan.trigger.ITrigger;
  78. import org.lightjason.agentspeak.language.instantiable.rule.CRule;
  79. import org.lightjason.agentspeak.language.instantiable.rule.CRulePlaceholder;
  80. import org.lightjason.agentspeak.language.instantiable.rule.IRule;
  81. import org.lightjason.agentspeak.language.variable.CMutexVariable;
  82. import org.lightjason.agentspeak.language.variable.CVariable;
  83. import org.lightjason.agentspeak.language.variable.CVariableEvaluate;
  84. import org.lightjason.agentspeak.language.variable.IVariable;
  85. import org.lightjason.agentspeak.language.variable.IVariableEvaluate;

  86. import javax.annotation.Nonnull;
  87. import java.text.MessageFormat;
  88. import java.util.Collection;
  89. import java.util.Collections;
  90. import java.util.HashSet;
  91. import java.util.LinkedHashSet;
  92. import java.util.LinkedList;
  93. import java.util.List;
  94. import java.util.Map;
  95. import java.util.Objects;
  96. import java.util.Set;
  97. import java.util.logging.Logger;
  98. import java.util.stream.Collectors;


  99. /**
  100.  * default abstract-syntax-tree (AST) visitor for plan-bundles scripts
  101.  *
  102.  * @note methods are implemented twice agent and plan-bundle, because both use equal
  103.  * AgentSpeak(L) grammer, but AntLR visitor does not support inheritance by the grammar definition
  104.  */
  105. @SuppressWarnings( {"all", "warnings", "unchecked", "unused", "cast"} )
  106. public final class CASTVisitorPlanBundle extends AbstractParseTreeVisitor<Object> implements IASTVisitorPlanBundle
  107. {
  108.     /**
  109.      * logger
  110.      */
  111.     private static final Logger LOGGER = CCommon.logger( IASTVisitorAgent.class );
  112.     /**
  113.      * set with initial beliefs
  114.      */
  115.     private final Set<ILiteral> m_initialbeliefs = new LinkedHashSet<>();
  116.     /**
  117.      * map with plans
  118.      */
  119.     private final Set<IPlan> m_plans = new HashSet<>();
  120.     /**
  121.      * map with logical rules
  122.      */
  123.     private final Multimap<IPath, IRule> m_rules = LinkedHashMultimap.create();
  124.     /**
  125.      * map with action definition
  126.      */
  127.     private final Map<IPath, IAction> m_actions;

  128.     /**
  129.      * ctor
  130.      *
  131.      * @param p_actions set with actions
  132.      */
  133.     public CASTVisitorPlanBundle( @Nonnull final Set<IAction> p_actions )
  134.     {
  135.         m_actions = p_actions.stream().collect( Collectors.toMap( i -> i.name(), i -> i ) );
  136.         LOGGER.info( MessageFormat.format( "create parser with actions & rules : {0} / {1}", m_actions.keySet(), m_rules.keySet() ) );
  137.     }


  138.     // --- plan bundle rules -----------------------------------------------------------------------------------------------------------------------------------

  139.     @Override
  140.     public final Object visitPlanbundle( final PlanBundleParser.PlanbundleContext p_context )
  141.     {
  142.         return this.visitChildren( p_context );
  143.     }

  144.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------

  145.     // --- AgentSpeak(L) rules ---------------------------------------------------------------------------------------------------------------------------------

  146.     @Override
  147.     public final Object visitBelief( final PlanBundleParser.BeliefContext p_context )
  148.     {
  149.         if ( Objects.isNull( p_context.literal() ) )
  150.             return null;

  151.         m_initialbeliefs.add( (ILiteral) this.visitLiteral( p_context.literal() ) );
  152.         return null;
  153.     }

  154.     @Override
  155.     public final Object visitPlans( final PlanBundleParser.PlansContext p_context )
  156.     {
  157.         if ( Objects.isNull( p_context.plan() ) )
  158.             return null;

  159.         p_context.plan().stream().forEach( i -> ( (List<IPlan>) this.visitPlan( i ) ).stream().forEach( j -> m_plans.add( j ) ) );
  160.         LOGGER.info( MessageFormat.format( "parsed plans: {0}", m_plans ) );
  161.         return null;
  162.     }

  163.     @Override
  164.     public final Object visitLogicrules( final PlanBundleParser.LogicrulesContext p_context )
  165.     {
  166.         // create placeholder objects first and run parsing again to build full-qualified rule objects
  167.         p_context.logicrule().stream()
  168.                  .map( i -> (IRule) this.visitLogicrulePlaceHolder( i ) )
  169.                  .forEach( i -> m_rules.put( i.identifier().fqnfunctor(), i ) );

  170.         final Multimap<IPath, IRule> l_rules = LinkedHashMultimap.create();
  171.         p_context.logicrule().stream()
  172.                  .flatMap( i -> ( (List<IRule>) this.visitLogicrule( i ) ).stream() )
  173.                  .forEach( i -> l_rules.put( i.identifier().fqnfunctor(), i ) );

  174.         // clear rule list and replace placeholder objects
  175.         m_rules.clear();
  176.         l_rules.values().stream()
  177.                .map( i -> i.replaceplaceholder( l_rules ) )
  178.                .forEach( i -> m_rules.put( i.identifier().fqnfunctor(), i ) );

  179.         LOGGER.info( MessageFormat.format( "parsed rules: {0}", m_rules.values() ) );
  180.         return null;
  181.     }

  182.     @Override
  183.     public final Object visitLogicrule( final PlanBundleParser.LogicruleContext p_context )
  184.     {
  185.         final ILiteral l_literal = (ILiteral) this.visitLiteral( p_context.literal() );
  186.         return p_context.logicalruledefinition().stream()
  187.                         .map( i -> new CRule( (ILiteral) l_literal.deepcopy(), (List<IExecution>) this.visitLogicalruledefinition( i ) ) )
  188.                         .collect( Collectors.toList() );
  189.     }

  190.     @Override
  191.     public final Object visitLogicalruledefinition( final PlanBundleParser.LogicalruledefinitionContext p_context )
  192.     {
  193.         return this.visitBody( p_context.body() );
  194.     }

  195.     @Override
  196.     public final Object visitPlan( final PlanBundleParser.PlanContext p_context )
  197.     {
  198.         final Set<IAnnotation<?>> l_annotation = (Set<IAnnotation<?>>) this.visitAnnotations( p_context.annotations() );
  199.         final CTrigger l_trigger = new CTrigger(
  200.             (ITrigger.EType) this.visitPlan_trigger( p_context.plan_trigger() ),
  201.             (ILiteral) this.visitLiteral( p_context.literal() )
  202.         );

  203.         return p_context.plandefinition()
  204.                         .stream()
  205.                         .map( i ->
  206.                         {
  207.                             final Pair<IExpression, List<IExecution>> l_content = (Pair<IExpression, List<IExecution>>) this.visitPlandefinition( i );
  208.                             return new CPlan( l_trigger, l_content.getLeft(), l_content.getRight(), l_annotation );
  209.                         } )
  210.                         .collect( Collectors.toList() );
  211.     }

  212.     @Override
  213.     public final Object visitPlandefinition( final PlanBundleParser.PlandefinitionContext p_context )
  214.     {
  215.         return new ImmutablePair<IExpression, List<IExecution>>(
  216.             Objects.isNull( p_context.expression() ) ? IExpression.EMPTY
  217.                                            : (IExpression) this.visitExpression( p_context.expression() ),
  218.             (List<IExecution>) this.visitBody( p_context.body() )
  219.         );
  220.     }

  221.     @Override
  222.     public final Object visitAnnotations( final PlanBundleParser.AnnotationsContext p_context )
  223.     {
  224.         if ( ( Objects.isNull( p_context ) ) || ( p_context.isEmpty() ) )
  225.             return Collections.emptySet();


  226.         final Set<IAnnotation<?>> l_annotation = new HashSet<>();

  227.         if ( Objects.nonNull( p_context.annotation_atom() ) )
  228.             p_context.annotation_atom().stream().map( i -> (IAnnotation<?>) this.visitAnnotation_atom( i ) ).forEach( l_annotation::add );

  229.         if ( Objects.nonNull( p_context.annotation_literal() ) )
  230.             p_context.annotation_literal().stream().map( i -> (IAnnotation<?>) this.visitAnnotation_literal( i ) ).forEach( l_annotation::add );

  231.         return l_annotation.isEmpty() ? Collections.emptySet() : l_annotation;
  232.     }

  233.     @Override
  234.     public final Object visitAnnotation_atom( final PlanBundleParser.Annotation_atomContext p_context )
  235.     {
  236.         if ( Objects.nonNull( p_context.ATOMIC() ) )
  237.             return new CAtomAnnotation<>( IAnnotation.EType.ATOMIC );

  238.         if ( Objects.nonNull( p_context.PARALLEL() ) )
  239.             return new CAtomAnnotation<>( IAnnotation.EType.PARALLEL );

  240.         throw new CIllegalArgumentException( CCommon.languagestring( this, "atomannotation", p_context.getText() ) );
  241.     }

  242.     @Override
  243.     public final Object visitAnnotation_literal( final PlanBundleParser.Annotation_literalContext p_context )
  244.     {
  245.         return this.visitChildren( p_context );
  246.     }

  247.     @Override
  248.     public Object visitAnnotation_value_literal( final PlanBundleParser.Annotation_value_literalContext p_context )
  249.     {
  250.         if ( Objects.nonNull( p_context.number() ) )
  251.             return new CValueAnnotation<>(
  252.                 IAnnotation.EType.CONSTANT,
  253.                 (String) this.visitVariableatom( p_context.variableatom() ),
  254.                 ( (Number) this.visitNumber( p_context.number() ) ).doubleValue()
  255.             );

  256.         if ( Objects.nonNull( p_context.STRING() ) )
  257.             return new CValueAnnotation<>(
  258.                 IAnnotation.EType.CONSTANT,
  259.                 (String) this.visitVariableatom( p_context.variableatom() ),
  260.                 stringvalue( p_context.STRING().getText() )
  261.             );

  262.         throw new CIllegalArgumentException( CCommon.languagestring( this, "valueannotation", p_context.getText() ) );
  263.     }

  264.     @Override
  265.     public final Object visitPlan_trigger( final PlanBundleParser.Plan_triggerContext p_context )
  266.     {
  267.         return this.visitChildren( p_context );
  268.     }

  269.     @Override
  270.     public final Object visitPlan_goal_trigger( final PlanBundleParser.Plan_goal_triggerContext p_context )
  271.     {
  272.         if ( ITrigger.EType.ADDGOAL.sequence().equals( p_context.getText() ) )
  273.             return ITrigger.EType.ADDGOAL;

  274.         if ( ITrigger.EType.DELETEGOAL.sequence().equals( p_context.getText() ) )
  275.             return ITrigger.EType.DELETEGOAL;

  276.         throw new CIllegalArgumentException( CCommon.languagestring( this, "goaltrigger", p_context.getText() ) );
  277.     }

  278.     @Override
  279.     public final Object visitPlan_belief_trigger( final PlanBundleParser.Plan_belief_triggerContext p_context )
  280.     {
  281.         if ( ITrigger.EType.ADDBELIEF.sequence().equals( p_context.getText() ) )
  282.             return ITrigger.EType.ADDBELIEF;

  283.         if ( ITrigger.EType.DELETEBELIEF.sequence().equals( p_context.getText() ) )
  284.             return ITrigger.EType.DELETEBELIEF;

  285.         throw new CIllegalArgumentException( CCommon.languagestring( this, "belieftrigger", p_context.getText() ) );
  286.     }

  287.     @Override
  288.     public final Object visitBody( final PlanBundleParser.BodyContext p_context )
  289.     {
  290.         // filter null values of the body formular, because blank lines adds a null value, body-formula rule return an executable call everytime
  291.         return p_context.body_formula().stream()
  292.                         .filter( i -> Objects.nonNull( i ) )
  293.                         .map( i -> this.visitBody_formula( i ) )
  294.                         .filter( i -> i instanceof IExecution )
  295.                         // expression are encapsulate to get result
  296.                         .map( i -> i instanceof IExpression ? new CRawAction<>( i ) : i )
  297.                         .collect( Collectors.toList() );
  298.     }

  299.     @Override
  300.     public final Object visitBody_formula( final PlanBundleParser.Body_formulaContext p_context )
  301.     {
  302.         return this.visitChildren( p_context );
  303.     }

  304.     @Override
  305.     public final Object visitRepair_formula( final PlanBundleParser.Repair_formulaContext p_context )
  306.     {
  307.         // a non-existing repair formula can return any object-item, so convert it
  308.         // to executable structure, because the grammar rule must return an executable item
  309.         if ( Objects.isNull( p_context.repair_formula() ) )
  310.             return this.visitChildren( p_context );


  311.         // if there exists any repair element, build a sequential hierarchie of repair calls
  312.         if ( Objects.nonNull( p_context.executable_term() ) )
  313.             return new CRepair(
  314.                 (IExecution) this.visitExecutable_term( p_context.executable_term() ),
  315.                 (IExecution) this.visitRepair_formula( p_context.repair_formula() )
  316.             );

  317.         if ( Objects.nonNull( p_context.test_action() ) )
  318.             return new CRepair(
  319.                 (IExecution) this.visitTest_action( p_context.test_action() ),
  320.                 (IExecution) this.visitRepair_formula( p_context.repair_formula() )
  321.             );

  322.         if ( Objects.nonNull( p_context.achievement_goal_action() ) )
  323.             return new CRepair(
  324.                 (IExecution) this.visitAchievement_goal_action( p_context.achievement_goal_action() ),
  325.                 (IExecution) this.visitRepair_formula( p_context.repair_formula() )
  326.             );

  327.         throw new CSyntaxErrorException( CCommon.languagestring( this, "repairelement", p_context.getText() ) );
  328.     }

  329.     @Override
  330.     public final Object visitUnification( final PlanBundleParser.UnificationContext p_context )
  331.     {
  332.         final Object l_constraint = this.visitUnification_constraint( p_context.unification_constraint() );

  333.         if ( l_constraint instanceof IExpression )
  334.             return new CExpressionUnify(
  335.                 p_context.AT() != null,
  336.                 (ILiteral) this.visitLiteral( p_context.literal() ),
  337.                 (IExpression) l_constraint
  338.             );

  339.         if ( l_constraint instanceof IVariable<?> )
  340.             return new CVariableUnify(
  341.                 p_context.AT() != null,
  342.                 (ILiteral) this.visitLiteral( p_context.literal() ),
  343.                 (IVariable<?>) l_constraint
  344.             );

  345.         return new CDefaultUnify( p_context.AT() != null, (ILiteral) this.visitLiteral( p_context.literal() ) );
  346.     }

  347.     @Override
  348.     public final Object visitUnification_constraint( final PlanBundleParser.Unification_constraintContext p_context )
  349.     {
  350.         if ( Objects.isNull( p_context ) )
  351.             return null;

  352.         if ( Objects.nonNull( p_context.expression() ) )
  353.             return this.visitExpression( p_context.expression() );

  354.         if ( Objects.nonNull( p_context.variable() ) )
  355.             return this.visitVariable( p_context.variable() );

  356.         return null;
  357.     }

  358.     @Override
  359.     public final Object visitBlock_formula( final PlanBundleParser.Block_formulaContext p_context )
  360.     {
  361.         if ( Objects.nonNull( p_context.body_formula() ) )
  362.         {
  363.             final LinkedList<IExecution> l_statement = new LinkedList<>();
  364.             l_statement.add( (IExecution) this.visitBody_formula( p_context.body_formula() ) );
  365.             return l_statement;
  366.         }

  367.         return this.visitBody( p_context.body() );
  368.     }

  369.     @Override
  370.     public final Object visitLambda( final PlanBundleParser.LambdaContext p_context )
  371.     {
  372.         if ( Objects.nonNull( p_context.lambda_return() ) )
  373.             return new CLambdaExpression(
  374.                 Objects.nonNull( p_context.AT() ),
  375.                 (IExecution) this.visitLambda_initialization( p_context.lambda_initialization() ),
  376.                 (IVariable<?>) this.visitVariable( p_context.variable() ),
  377.                 (IVariable<?>) this.visitLambda_return( p_context.lambda_return() ),
  378.                 (List<IExecution>) this.visitBlock_formula( p_context.block_formula() )
  379.             );

  380.         return new CLambdaExpression(
  381.             Objects.nonNull( p_context.AT() ),
  382.             (IExecution) this.visitLambda_initialization( p_context.lambda_initialization() ),
  383.             (IVariable<?>) this.visitVariable( p_context.variable() ),
  384.             (List<IExecution>) this.visitBlock_formula( p_context.block_formula() )
  385.         );
  386.     }

  387.     @Override
  388.     public final Object visitLambda_initialization( final PlanBundleParser.Lambda_initializationContext p_context )
  389.     {
  390.         if ( Objects.nonNull( p_context.variable() ) )
  391.             return new CRawAction<>( this.visitVariable( p_context.variable() ) );

  392.         if ( Objects.nonNull( p_context.literal() ) )
  393.             return new CProxyAction( m_actions, (ILiteral) this.visitLiteral( p_context.literal() ) );

  394.         throw new CSyntaxErrorException( CCommon.languagestring( this, "lambdainitialization", p_context.getText() ) );
  395.     }

  396.     @Override
  397.     public final Object visitLambda_return( final PlanBundleParser.Lambda_returnContext p_context )
  398.     {
  399.         return this.visitVariable( p_context.variable() );
  400.     }

  401.     @Override
  402.     public final Object visitExecutable_term( final PlanBundleParser.Executable_termContext p_context )
  403.     {
  404.         if ( Objects.nonNull( p_context.STRING() ) )
  405.             return new CRawAction<>( stringvalue( p_context.STRING().getText() ) );
  406.         if ( Objects.nonNull( p_context.number() ) )
  407.             return new CRawAction<>( this.visitNumber( p_context.number() ) );
  408.         if ( Objects.nonNull( p_context.LOGICALVALUE() ) )
  409.             return new CRawAction<>( logicalvalue( p_context.LOGICALVALUE().getText() ) );

  410.         if ( Objects.nonNull( p_context.executable_action() ) )
  411.             return this.visitExecutable_action( p_context.executable_action() );
  412.         if ( Objects.nonNull( p_context.executable_rule() ) )
  413.             return this.visitExecutable_rule( p_context.executable_rule() );

  414.         if ( Objects.nonNull( p_context.expression() ) )
  415.             return this.visitExpression( p_context.expression() );
  416.         if ( Objects.nonNull( p_context.ternary_operation() ) )
  417.             return this.visitTernary_operation( p_context.ternary_operation() );

  418.         throw new CIllegalArgumentException( CCommon.languagestring( this, "termunknown", p_context.getText() ) );
  419.     }

  420.     @Override
  421.     public final Object visitAssignment_expression( final PlanBundleParser.Assignment_expressionContext p_context )
  422.     {
  423.         return this.visitChildren( p_context );
  424.     }

  425.     @Override
  426.     public final Object visitAssignment_expression_singlevariable( final PlanBundleParser.Assignment_expression_singlevariableContext p_context )
  427.     {
  428.         return new CSingleAssignment<>(
  429.             (IVariable<?>) this.visitVariable( p_context.variable() ),
  430.             (IExecution) this.visitExecutable_term( p_context.executable_term() )
  431.         );
  432.     }

  433.     @Override
  434.     public final Object visitAssignment_expression_multivariable( final PlanBundleParser.Assignment_expression_multivariableContext p_context )
  435.     {
  436.         return new CMultiAssignment<>(
  437.             p_context.variablelist().variable().stream().map( i -> (IVariable<?>) this.visitVariable( i ) )
  438.                      .collect( Collectors.toList() ),
  439.             (IExecution) this.visitExecutable_term( p_context.executable_term() )
  440.         );
  441.     }

  442.     @Override
  443.     public final Object visitUnary_expression( final PlanBundleParser.Unary_expressionContext p_context )
  444.     {
  445.         switch ( p_context.UNARYOPERATOR().getText() )
  446.         {
  447.             case "++":
  448.                 return new CIncrement<>( (IVariable<Number>) this.visitVariable( p_context.variable() ) );

  449.             case "--":
  450.                 return new CDecrement<>( (IVariable<Number>) this.visitVariable( p_context.variable() ) );

  451.             default:
  452.                 throw new CIllegalArgumentException( CCommon.languagestring( this, "unaryoperator", p_context.getText() ) );
  453.         }
  454.     }

  455.     @Override
  456.     public final Object visitBinary_expression( final PlanBundleParser.Binary_expressionContext p_context )
  457.     {
  458.         final IVariable<Number> l_lhs = (IVariable<Number>) this.visitVariable( p_context.variable( 0 ) );
  459.         final ITerm l_rhs = p_context.variable().size() == 2
  460.                             ? (IVariable<Number>) this.visitVariable( p_context.variable( 1 ) )
  461.                             : CRawTerm.from( this.visitNumber( p_context.number() ) );

  462.         return new COperatorAssign(
  463.             l_lhs, l_rhs, org.lightjason.agentspeak.language.execution.expressionbinary.EOperator.from( p_context.BINARYOPERATOR().getText() )
  464.         );
  465.     }

  466.     @Override
  467.     public final Object visitAchievement_goal_action( final PlanBundleParser.Achievement_goal_actionContext p_context )
  468.     {
  469.         if ( Objects.nonNull( p_context.literal() ) )
  470.             return new CAchievementGoalLiteral( (ILiteral) this.visitLiteral( p_context.literal() ), Objects.nonNull( p_context.DOUBLEEXCLAMATIONMARK() ) );

  471.         if ( Objects.nonNull( p_context.variable_evaluate() ) )
  472.             return new CAchievementGoalVariable(
  473.                 (IVariableEvaluate) this.visitVariable_evaluate( p_context.variable_evaluate() ),
  474.                 p_context.DOUBLEEXCLAMATIONMARK() != null
  475.             );

  476.         throw new CIllegalArgumentException( CCommon.languagestring( this, "achievmentgoal", p_context.getText() ) );
  477.     }

  478.     @Override
  479.     public final Object visitTernary_operation( final PlanBundleParser.Ternary_operationContext p_context )
  480.     {
  481.         return new CTernaryOperation(
  482.             (IExpression) this.visitExpression( p_context.expression() ),
  483.             (IExecution) this.visitTernary_operation_true( p_context.ternary_operation_true() ),
  484.             (IExecution) this.visitTernary_operation_false( p_context.ternary_operation_false() )
  485.         );
  486.     }

  487.     @Override
  488.     public final Object visitTernary_operation_true( final PlanBundleParser.Ternary_operation_trueContext p_context )
  489.     {
  490.         return this.visitExecutable_term( p_context.executable_term() );
  491.     }

  492.     @Override
  493.     public final Object visitTernary_operation_false( final PlanBundleParser.Ternary_operation_falseContext p_context )
  494.     {
  495.         return this.visitExecutable_term( p_context.executable_term() );
  496.     }

  497.     @Override
  498.     public final Object visitTest_action( final PlanBundleParser.Test_actionContext p_context )
  499.     {
  500.         // dollar sign is used to recognize a rule
  501.         return p_context.DOLLAR() != null
  502.                ? new CTestRule( CPath.from( (String) this.visitAtom( p_context.atom() ) ) )
  503.                : new CTestGoal( CPath.from( (String) this.visitAtom( p_context.atom() ) ) );
  504.     }

  505.     @Override
  506.     public final Object visitBelief_action( final PlanBundleParser.Belief_actionContext p_context )
  507.     {
  508.         if ( Objects.nonNull( p_context.PLUS() ) )
  509.             return new CBeliefAction( (ILiteral) this.visitLiteral( p_context.literal() ), CBeliefAction.EAction.ADD );

  510.         if ( Objects.nonNull( p_context.MINUS() ) )
  511.             return new CBeliefAction( (ILiteral) this.visitLiteral( p_context.literal() ), CBeliefAction.EAction.DELETE );

  512.         throw new CIllegalArgumentException( CCommon.languagestring( this, "beliefaction", p_context.getText() ) );
  513.     }

  514.     @Override
  515.     public final Object visitDeconstruct_expression( final PlanBundleParser.Deconstruct_expressionContext p_context )
  516.     {
  517.         return new CDeconstruct<>(
  518.             p_context.variablelist().variable().stream().map( i -> (IVariable<?>) this.visitVariable( i ) ).collect( Collectors.toList() ),
  519.             (ITerm) ( p_context.literal() != null ? this.visitLiteral( p_context.literal() ) : this.visitVariable( p_context.variable() ) )
  520.         );
  521.     }

  522.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------


  523.     // --- simple datatypes ------------------------------------------------------------------------------------------------------------------------------------

  524.     @Override
  525.     public final Object visitLiteral( final PlanBundleParser.LiteralContext p_context )
  526.     {
  527.         return new CLiteral(
  528.             p_context.AT() != null,
  529.             p_context.STRONGNEGATION() != null,
  530.             CPath.from( this.visitAtom( p_context.atom() ).toString() ),
  531.             (Collection<ITerm>) this.visitTermlist( p_context.termlist() )
  532.         );
  533.     }

  534.     @Override
  535.     public final Object visitTerm( final PlanBundleParser.TermContext p_context )
  536.     {
  537.         if ( Objects.nonNull( p_context.STRING() ) )
  538.             return stringvalue( p_context.STRING().getText() );
  539.         if ( Objects.nonNull( p_context.number() ) )
  540.             return this.visitNumber( p_context.number() );
  541.         if ( Objects.nonNull( p_context.LOGICALVALUE() ) )
  542.             return logicalvalue( p_context.LOGICALVALUE().getText() );

  543.         if ( Objects.nonNull( p_context.literal() ) )
  544.             return this.visitLiteral( p_context.literal() );
  545.         if ( Objects.nonNull( p_context.variable() ) )
  546.             return this.visitVariable( p_context.variable() );

  547.         if ( Objects.nonNull( p_context.termlist() ) )
  548.             return this.visitTermlist( p_context.termlist() );
  549.         if ( Objects.nonNull( p_context.expression() ) )
  550.             return this.visitExpression( p_context.expression() );
  551.         if ( Objects.nonNull( p_context.ternary_operation() ) )
  552.             return this.visitTernary_operation( p_context.ternary_operation() );

  553.         throw new CIllegalArgumentException( CCommon.languagestring( this, "termunknown", p_context.getText() ) );
  554.     }

  555.     @Override
  556.     public final Object visitTermlist( final PlanBundleParser.TermlistContext p_context )
  557.     {
  558.         if ( ( Objects.isNull( p_context ) ) || ( p_context.isEmpty() ) )
  559.             return Collections.<ITerm>emptyList();

  560.         return p_context.term().stream()
  561.                         .map( i -> this.visitTerm( i ) )
  562.                         .filter( i -> Objects.nonNull( i ) )
  563.                         .map( i -> i instanceof ITerm ? (ITerm) i : CRawTerm.from( i ) )
  564.                         .collect( Collectors.toList() );
  565.     }

  566.     @Override
  567.     public final Object visitVariablelist( final PlanBundleParser.VariablelistContext p_context )
  568.     {
  569.         return this.visitChildren( p_context );
  570.     }

  571.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------


  572.     // --- raw rules -------------------------------------------------------------------------------------------------------------------------------------------

  573.     @Override
  574.     public final Object visitNumber( final PlanBundleParser.NumberContext p_context )
  575.     {
  576.         if ( Objects.nonNull( p_context.CONSTANTNUMBER() ) )
  577.             return numericonstant( p_context.CONSTANTNUMBER().getText() );

  578.         final Number l_value = (Number) this.visitChildren( p_context );
  579.         return p_context.MINUS() != null
  580.                ? -1 * l_value.doubleValue()
  581.                : l_value.doubleValue();
  582.     }

  583.     @Override
  584.     public final Object visitDigitsequence( final PlanBundleParser.DigitsequenceContext p_context )
  585.     {
  586.         return Double.valueOf( p_context.getText() );
  587.     }

  588.     @Override
  589.     public final Object visitAtom( final PlanBundleParser.AtomContext p_context )
  590.     {
  591.         return p_context.getText();
  592.     }

  593.     @Override
  594.     public final Object visitVariable( final PlanBundleParser.VariableContext p_context )
  595.     {
  596.         return Objects.isNull( p_context.AT() ) ? new CVariable<>( p_context.getText() ) : new CMutexVariable<>( p_context.getText() );
  597.     }

  598.     @Override
  599.     public final Object visitVariableatom( final PlanBundleParser.VariableatomContext p_context )
  600.     {
  601.         return p_context.getText();
  602.     }

  603.     @Override
  604.     public final Object visitExpression( final PlanBundleParser.ExpressionContext p_context )
  605.     {
  606.         // bracket expression
  607.         if ( Objects.nonNull( p_context.expression_bracket() ) )
  608.             return this.visitExpression_bracket( p_context.expression_bracket() );

  609.         // or-expression
  610.         return org.lightjason.agentspeak.grammar.CCommon.createLogicalBinaryExpression(
  611.             EOperator.OR,
  612.             (IExpression) this.visitExpression_logical_and( p_context.expression_logical_and() ),
  613.             p_context.expression() != null
  614.             ? p_context.expression().stream().map( i -> (IExpression) this.visitExpression( i ) ).collect( Collectors.toList() )
  615.             : Collections.emptyList()
  616.         );
  617.     }

  618.     @Override
  619.     public final Object visitExpression_bracket( final PlanBundleParser.Expression_bracketContext p_context )
  620.     {
  621.         return this.visitExpression( p_context.expression() );
  622.     }

  623.     @Override
  624.     public final Object visitExpression_logical_and( final PlanBundleParser.Expression_logical_andContext p_context )
  625.     {
  626.         return org.lightjason.agentspeak.grammar.CCommon.createLogicalBinaryExpression(
  627.             EOperator.AND,
  628.             (IExpression) this.visitExpression_logical_xor( p_context.expression_logical_xor() ),
  629.             p_context.expression() != null
  630.             ? p_context.expression().stream().map( i -> (IExpression) this.visitExpression( i ) ).collect( Collectors.toList() )
  631.             : Collections.emptyList()
  632.         );
  633.     }

  634.     @Override
  635.     public final Object visitExpression_logical_xor( final PlanBundleParser.Expression_logical_xorContext p_context )
  636.     {
  637.         if ( Objects.nonNull( p_context.expression_logical_element() ) )
  638.             return org.lightjason.agentspeak.grammar.CCommon.createLogicalBinaryExpression(
  639.                 EOperator.XOR,
  640.                 (IExpression) this.visitExpression_logical_element( p_context.expression_logical_element() ),
  641.                 p_context.expression() != null
  642.                 ? p_context.expression().stream().map( i -> (IExpression) this.visitExpression( i ) ).collect( Collectors.toList() )
  643.                 : Collections.emptyList()
  644.             );

  645.         if ( Objects.nonNull( p_context.expression_logical_negation() ) )
  646.             return this.visitExpression_logical_negation( p_context.expression_logical_negation() );

  647.         if ( Objects.nonNull( p_context.expression_numeric() ) )
  648.             return this.visitExpression_numeric( p_context.expression_numeric() );

  649.         throw new CSyntaxErrorException( CCommon.languagestring( this, "logicallefthandside", p_context.getText() ) );
  650.     }

  651.     @Override
  652.     public final Object visitExpression_logical_negation( final PlanBundleParser.Expression_logical_negationContext p_context )
  653.     {
  654.         return new CUnary( EOperator.NEGATION, (IExpression) this.visitExpression( p_context.expression() ) );
  655.     }

  656.     @Override
  657.     public final Object visitExpression_logical_element( final PlanBundleParser.Expression_logical_elementContext p_context )
  658.     {
  659.         if ( Objects.nonNull( p_context.LOGICALVALUE().getSymbol() ) )
  660.             return new CAtom( logicalvalue( p_context.LOGICALVALUE().getText() ) );

  661.         if ( Objects.nonNull( p_context.variable() ) )
  662.             return new CAtom( this.visitVariable( p_context.variable() ) );

  663.         if ( Objects.nonNull( p_context.unification() ) )
  664.             return new CProxyReturnExpression<>( (IExecution) this.visitUnification( p_context.unification() ) );

  665.         if ( Objects.nonNull( p_context.executable_action() ) )
  666.             return new CProxyReturnExpression<>( (IExecution) this.visitExecutable_action( p_context.executable_action() ) );

  667.         if ( Objects.nonNull( p_context.executable_rule() ) )
  668.             return new CProxyReturnExpression<>( (IExecution) this.visitExecutable_rule( p_context.executable_rule() ) );

  669.         throw new CSyntaxErrorException( CCommon.languagestring( this, "logicalelement", p_context.getText() ) );
  670.     }

  671.     @Override
  672.     public final Object visitExpression_numeric( final PlanBundleParser.Expression_numericContext p_context )
  673.     {
  674.         if ( Objects.isNull( p_context.expression_numeric() ) )
  675.             return this.visitExpression_numeric_relation( p_context.expression_numeric_relation() );

  676.         if ( Objects.nonNull( p_context.EQUAL() ) )
  677.             return new CComparable(
  678.                 EOperator.EQUAL,
  679.                 (IExpression) this.visitExpression_numeric_relation( p_context.expression_numeric_relation() ),
  680.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  681.             );

  682.         if ( Objects.nonNull( p_context.NOTEQUAL() ) )
  683.             return new CComparable(
  684.                 EOperator.NOTEQUAL,
  685.                 (IExpression) this.visitExpression_numeric_relation( p_context.expression_numeric_relation() ),
  686.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  687.             );

  688.         throw new CSyntaxErrorException( CCommon.languagestring( this, "compareoperator", p_context.getText() ) );
  689.     }

  690.     @Override
  691.     public final Object visitExpression_numeric_relation( final PlanBundleParser.Expression_numeric_relationContext p_context )
  692.     {
  693.         if ( Objects.isNull( p_context.expression_numeric() ) )
  694.             return this.visitExpression_numeric_additive( p_context.expression_numeric_additive() );

  695.         if ( Objects.nonNull( p_context.GREATER() ) )
  696.             return new CRelational(
  697.                 EOperator.GREATER,
  698.                 (IExpression) this.visitExpression_numeric_additive( p_context.expression_numeric_additive() ),
  699.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  700.             );

  701.         if ( Objects.nonNull( p_context.GREATEREQUAL() ) )
  702.             return new CRelational(
  703.                 EOperator.GREATEREQUAL,
  704.                 (IExpression) this.visitExpression_numeric_additive( p_context.expression_numeric_additive() ),
  705.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  706.             );

  707.         if ( Objects.nonNull( p_context.LESS() ) )
  708.             return new CRelational(
  709.                 EOperator.LESS,
  710.                 (IExpression) this.visitExpression_numeric_additive( p_context.expression_numeric_additive() ),
  711.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  712.             );

  713.         if ( Objects.nonNull( p_context.LESSEQUAL() ) )
  714.             return new CRelational(
  715.                 EOperator.LESSEQUAL,
  716.                 (IExpression) this.visitExpression_numeric_additive( p_context.expression_numeric_additive() ),
  717.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  718.             );

  719.         throw new CSyntaxErrorException( CCommon.languagestring( this, "relationaloperator", p_context.getText() ) );
  720.     }

  721.     @Override
  722.     public final Object visitExpression_numeric_additive( final PlanBundleParser.Expression_numeric_additiveContext p_context )
  723.     {
  724.         if ( Objects.isNull( p_context.expression_numeric() ) )
  725.             return this.visitExpression_numeric_multiplicative( p_context.expression_numeric_multiplicative() );

  726.         if ( Objects.nonNull( p_context.PLUS() ) )
  727.             return new CAdditive(
  728.                 EOperator.PLUS,
  729.                 (IExpression) this.visitExpression_numeric_multiplicative( p_context.expression_numeric_multiplicative() ),
  730.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  731.             );

  732.         if ( Objects.nonNull( p_context.MINUS() ) )
  733.             return new CAdditive(
  734.                 EOperator.MINUS,
  735.                 (IExpression) this.visitExpression_numeric_multiplicative( p_context.expression_numeric_multiplicative() ),
  736.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  737.             );

  738.         throw new CSyntaxErrorException( CCommon.languagestring( this, "additiveoperator", p_context.getText() ) );
  739.     }

  740.     @Override
  741.     public final Object visitExpression_numeric_multiplicative( final PlanBundleParser.Expression_numeric_multiplicativeContext p_context )
  742.     {
  743.         if ( Objects.isNull( p_context.expression_numeric() ) )
  744.             return this.visitExpression_numeric_power( p_context.expression_numeric_power() );

  745.         if ( Objects.nonNull( p_context.MULTIPLY() ) )
  746.             return new CMultiplicative(
  747.                 EOperator.MULTIPLY,
  748.                 (IExpression) this.visitExpression_numeric_power( p_context.expression_numeric_power() ),
  749.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  750.             );

  751.         if ( Objects.nonNull( p_context.SLASH() ) )
  752.             return new CMultiplicative(
  753.                 EOperator.DIVIDE,
  754.                 (IExpression) this.visitExpression_numeric_power( p_context.expression_numeric_power() ),
  755.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  756.             );

  757.         if ( Objects.nonNull( p_context.MODULO() ) )
  758.             return new CMultiplicative(
  759.                 EOperator.MODULO,
  760.                 (IExpression) this.visitExpression_numeric_power( p_context.expression_numeric_power() ),
  761.                 (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  762.             );

  763.         throw new CSyntaxErrorException( CCommon.languagestring( this, "multiplicativeoperator", p_context.getText() ) );
  764.     }

  765.     @Override
  766.     public final Object visitExpression_numeric_power( final PlanBundleParser.Expression_numeric_powerContext p_context )
  767.     {
  768.         if ( Objects.isNull( p_context.expression_numeric() ) )
  769.             return this.visitExpression_numeric_element( p_context.expression_numeric_element() );

  770.         return new CPower(
  771.             EOperator.POWER,
  772.             (IExpression) this.visitExpression_numeric_element( p_context.expression_numeric_element() ),
  773.             (IExpression) this.visitExpression_numeric( p_context.expression_numeric() )
  774.         );
  775.     }

  776.     @Override
  777.     public final Object visitExpression_numeric_element( final PlanBundleParser.Expression_numeric_elementContext p_context )
  778.     {
  779.         if ( Objects.nonNull( p_context.number() ) )
  780.             return new CAtom( this.visitNumber( p_context.number() ) );

  781.         if ( Objects.nonNull( p_context.variable() ) )
  782.             return new CAtom( this.visitVariable( p_context.variable() ) );

  783.         if ( Objects.nonNull( p_context.executable_action() ) )
  784.             return new CProxyReturnExpression<>( (IExecution) this.visitExecutable_action( p_context.executable_action() ) );

  785.         if ( Objects.nonNull( p_context.executable_rule() ) )
  786.             return new CProxyReturnExpression<>( (IExecution) this.visitExecutable_rule( p_context.executable_rule() ) );

  787.         throw new CSyntaxErrorException( CCommon.languagestring( this, "numericelement", p_context.getText() ) );
  788.     }

  789.     @Override
  790.     public final Object visitExecutable_action( final PlanBundleParser.Executable_actionContext p_context )
  791.     {
  792.         return new CProxyAction( m_actions, (ILiteral) this.visitLiteral( p_context.literal() ) );
  793.     }

  794.     @Override
  795.     public final Object visitExecutable_rule( final PlanBundleParser.Executable_ruleContext p_context )
  796.     {
  797.         if ( Objects.nonNull( p_context.literal() ) )
  798.             return new CAchievementRuleLiteral( (ILiteral) this.visitLiteral( p_context.literal() ) );

  799.         if ( Objects.nonNull( p_context.variable_evaluate() ) )
  800.             return new CAchievementRuleVariable( (IVariableEvaluate) this.visitVariable_evaluate( p_context.variable_evaluate() ) );

  801.         throw new CSyntaxErrorException( CCommon.languagestring( this, "executablerule", p_context.getText() ) );
  802.     }

  803.     @Override
  804.     public final Object visitVariable_evaluate( final PlanBundleParser.Variable_evaluateContext p_context )
  805.     {
  806.         return new CVariableEvaluate(
  807.             (IVariable<?>) this.visitVariable( p_context.variable() ),
  808.             (List<ITerm>) this.visitTermlist( p_context.termlist() )
  809.         );
  810.     }

  811.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------


  812.     // --- helper ----------------------------------------------------------------------------------------------------------------------------------------------

  813.     /**
  814.      * create a rule placeholder object
  815.      *
  816.      * @param p_context logical rule context
  817.      * @return placeholder rule
  818.      */
  819.     protected Object visitLogicrulePlaceHolder( final PlanBundleParser.LogicruleContext p_context )
  820.     {
  821.         return new CRulePlaceholder( (ILiteral) this.visitLiteral( p_context.literal() ) );
  822.     }

  823.     /**
  824.      * returns the value of a numeric constant
  825.      *
  826.      * @param p_value constant name
  827.      * @return number value
  828.      */
  829.     private static Number numericonstant( @Nonnull final String p_value )
  830.     {
  831.         final Double l_constant = org.lightjason.agentspeak.grammar.CCommon.NUMERICCONSTANT.get( p_value );
  832.         if ( Objects.nonNull( l_constant ) )
  833.             return l_constant;

  834.         throw new CSyntaxErrorException( CCommon.languagestring( CASTVisitorPlanBundle.class, "constantunknown", p_value ) );
  835.     }

  836.     /**
  837.      * converts a string token to the type
  838.      *
  839.      * @param p_value string value
  840.      * @return boolean value
  841.      */
  842.     private static boolean logicalvalue( @Nonnull final String p_value )
  843.     {
  844.         return ( !p_value.isEmpty() ) && ( ( "true".equals( p_value ) ) || ( "success".equals( p_value ) ) );
  845.     }

  846.     /**
  847.      * create a string value without quotes
  848.      *
  849.      * @param p_value string
  850.      * @return string without quotes
  851.      */
  852.     private static String stringvalue( @Nonnull final String p_value )
  853.     {
  854.         return p_value.length() < 3 ? "" : p_value.substring( 1, p_value.length() - 1 );
  855.     }

  856.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------


  857.     // --- getter structure ------------------------------------------------------------------------------------------------------------------------------------

  858.     @Nonnull
  859.     @Override
  860.     public final Set<ILiteral> initialbeliefs()
  861.     {
  862.         return m_initialbeliefs;
  863.     }

  864.     @Nonnull
  865.     @Override
  866.     public final Set<IPlan> plans()
  867.     {
  868.         return m_plans;
  869.     }

  870.     @Nonnull
  871.     @Override
  872.     public final Set<IRule> rules()
  873.     {
  874.         return new HashSet<>( m_rules.values() );
  875.     }

  876.     // ---------------------------------------------------------------------------------------------------------------------------------------------------------
  877. }