# Interpreter - Design Pattern

### Objective `🎯`
Provide a way to interpret/evaluate a language grammar or expression.

### Type `✅`
✔️**Behavioral**: Describes how objects interact/communicate between themselves.

❌**Creational**: Describes how to instantiate an object without large and complex.

❌**Structural**: Describes how objects/classes are composed to form larger structures.

### UML `📐`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695743434/QrRkgsydm.png align="left")


### Participants `🔗`
• AbstractExpression:
-	Declares an *Evaluate()* operation that all nodes (leaf and non-leaf) must override

• Terminal Expression:
-	Implements a concrete operation 

• Nonterminal Expression:
-	Implements an operation and execute the next expression

• Interpreter:
-	Defines an interface to receive the Context
-	Based on the Context (user’s input) will create the Expression classes
-	Will interpret the user’s input (Context) by executing the Evaluate method of the Expression classes

• Client:
-	Will receive the user’s input data
-	Responsible to create and maintain the Context
-	Will instantiate an *Interpreter *object and call the method *Interpret *passing the Context as argument

### Notes `📝`
• This pattern is recommended for relatively simple grammar interpretation, which doesn't need to evolve and extend much.

• Terminal Expressions are considered the leaf nodes

• Non-Terminal Expressions are considered the non-leaf nodes

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695858680/moHCxhi-j.png align="left")

•  The example below illustrates how this pattern can be used to interpret SQL statements 


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695841311/7NFsLCVCm.png align="left")

### Sample Code `🎮`
#### Structural Example `🏛️`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695878222/5XUgifN_i.png align="left")

```csharp
public static class InterpreterStructural
    {
        // Client
        public static void Execute()
        {
            Context lContext = new Context();
            lContext._UserInput = "AABBCC";

            Interpreter lInterpreter = new Interpreter();
            lInterpreter.Interprete(lContext);
        }
    }

    public class Interpreter
    {
        public void Interprete(Context prContext)
        {
            List<Expression> _Expressions = new List<Expression>();
            _Expressions.Add(new NonTerminalExpression());
            _Expressions.Add(new TerminalExpression());

            foreach (Expression lExpressionCurrent in _Expressions)
            {
                lExpressionCurrent.Evaluate(prContext);
            }
        }
    }

    public abstract class Expression
    {
        public abstract void Evaluate(Context prContext);
    }

    public class NonTerminalExpression : Expression
    {
        public override void Evaluate(Context prContext)
        {
            Console.WriteLine($"--Executing a Non-Terminal Operation with the input \"{prContext._UserInput}\"");
        }
    }

    public class TerminalExpression : Expression
    {
        public override void Evaluate(Context prContext)
        {
            Console.WriteLine($"----Executing a Terminal Operation with the input \"{prContext._UserInput}\"");
        }
    }

    public class Context
    {
        public string _UserInput { get; set; }
    }
```
**Output**

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695908696/0au3WxPek.png align="left")

#### Real-world Example 🔥

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695889480/9fmDNI7iu.png align="left")
```csharp
public static class InterpreterPractical
    {
        // Client
        public static void Execute()
        {
            CommandLineContext lCommandLineContext = new CommandLineContext();
            lCommandLineContext._UserExpression = " Lorem Ipsum Dolor Sit Amet, Consectetur -u -t";

            CommandLineInterpreter lCommandLineInterpreter = new CommandLineInterpreter();
            lCommandLineInterpreter.Interprete(lCommandLineContext);

            lCommandLineContext._UserExpression = " Lorem Ipsum Dolor Sit Amet, Consectetur -l";
            lCommandLineInterpreter.Interprete(lCommandLineContext);
        }
    }

    public class CommandLineInterpreter
    {
        public void Interprete(CommandLineContext prCommandLineContext)
        {
            List<CommandLineExpression> _CommandLineExpressions = new List<CommandLineExpression>();

            // GET EXPRESSIONS
            List<string> lExpressions = prCommandLineContext._UserExpression.Substring(prCommandLineContext._UserExpression.IndexOf("-")).Split(" ").ToList();
            
            prCommandLineContext._Result = prCommandLineContext._UserExpression.Substring(0, prCommandLineContext._UserExpression.IndexOf("-"));

            foreach (string lExpressionCUrrent in lExpressions)
            {
                switch (lExpressionCUrrent)
                {
                    case ("-u"): _CommandLineExpressions.Add(new ToUpperCaseExpression()); break;
                    case ("-l"): _CommandLineExpressions.Add(new ToLowerCaseExpression()); break;
                    case ("-t"): _CommandLineExpressions.Add(new TrimExpression()); break;
                    default: break;
                }
            }

            // EXECUTE EXPRESSIONS
            Console.WriteLine($"\n\r- INTERPRETING INPUT: \"{prCommandLineContext._Result}\"");
            foreach (CommandLineExpression lCommandLineExpressionCurrent in _CommandLineExpressions)
            {
                lCommandLineExpressionCurrent.Evaluate(prCommandLineContext);
                Console.WriteLine($"-- {lCommandLineExpressionCurrent.GetType().Name} Executed - Result: \"{prCommandLineContext._Result}\"");
            }
            Console.WriteLine($"- INTERPRETATION RESULT: \"{prCommandLineContext._Result}\"");
        }
    }

    public abstract class CommandLineExpression
    {
        public abstract void Evaluate(CommandLineContext prCommandLineContext);
    }

    public class ToUpperCaseExpression : CommandLineExpression
    {
        public override void Evaluate(CommandLineContext prCommandLineContext)
        {
            prCommandLineContext._Result = prCommandLineContext._Result.ToUpper();
        }
    }

    public class ToLowerCaseExpression : CommandLineExpression
    {
        public override void Evaluate(CommandLineContext prCommandLineContext)
        {
            prCommandLineContext._Result = prCommandLineContext._Result.ToLower();
        }
    }

    public class TrimExpression : CommandLineExpression
    {
        public override void Evaluate(CommandLineContext prCommandLineContext)
        {
            prCommandLineContext._Result = prCommandLineContext._Result.Trim();
        }
    }

    public class CommandLineContext
    {
        public string _UserExpression { get; set; }
        public string _Result { get; set; }
    }
```
**Output**

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1654695923242/NIRlpC2nS.png align="left")

### Source Code `🎲`
https://github.com/VictorLins/DesignPatterns 

