MSDScript can be classified as a simple scripting language based on C++ that can parse user input and
then interpret it whenever possible. This language is not advanced enough to be compared to Python but they are
similar in some structural ways. MSDScript supports the following kinds of expression:
- Numbers
- Variables
- Addition
- Multiplication
- Boolean
- Let
var=exprinexpr - If
boolthenexprelseexpr - Equivalence
- Functions
- Function Calls
MSDScript can be compiled and used as a standalone interpreter just like Python, or it can be used a library to
use MSDScript as an embedded language.
〈 expr 〉 = 〈 comparg 〉
| 〈 comparg 〉 == 〈 expr 〉
〈 comparg 〉 = 〈 addend 〉
| 〈 addend 〉 + 〈 comparg 〉
〈 addend 〉 = 〈 multicand 〉
| 〈 multicand 〉 * 〈 addend 〉
〈 multicand 〉 = 〈 inner 〉
| 〈 multicand 〉(〈 expr 〉)
〈 inner 〉 = 〈 number 〉 | (〈 expr 〉) | 〈 variable 〉
| _let 〈 variable 〉 = 〈 expr 〉 _in 〈 expr 〉
| _true | _false
| _if 〈 expr 〉 _then 〈 expr 〉 _else 〈 expr 〉
| _fun (〈 variable 〉) 〈 expr 〉
Highest to the lowest precedence as follows:
- Multiplication Expressions
- Addition Expressions
- Equivalence Expressions
- Inner Expressions such as If, Let, Function & Function Call Expressions.
- Once you extract the archive, you will find
v1.0_Standalone.zip, you may extract the archive in your desired location. - Open a terminal window and
cdinto the extracted directory. It is important formaketo work in the next step. - Run
make. - This will generate an executable
msdscript.
There are multiple command line arguments that are needed to run the program. These arguments are:
--interpwill interpret all the expressions passed into the interpreter.--printwill print all the expressions in full form.--pretty-printwill print all the expressions in a reduced form.--testwill run tests MSDScript code.
There is no official support for using multiple commands at once, but in some cases it may or may not work.
The syntax to run MSDScript from command line is:
./msdscript <argument> where <argument> are the arguments mentioned above.
After running this command, the interpreter will start in the terminal window. The user can input MSDScript literals
(refer to User Guide section)
in this window and then use Control + D to finish inputting. This will execute the interpreter, and it will output
the expected result based on the arguments passed into the program.
- Once you extract the archive, you will find
v1.0_Library.zip, you may extract the archive in your desired location. - Then, you should copy the contents of the archive to the source directory of your project.
- Include
msdscript.hin your source file, for example#include "msdscript.h". Include path will depend on the location where you extracted the archive. I suggest extracting them in the source directory of your project.
The library can be used through the parser or directly using the API functions provided. I would personally just use strings to pass into the parser. Refer to the user guide section for more details.
MSDScript uses a parser to parse the user input and convert it into expressions. There are 2 ways in which this program can be used.
- String-based parsing through either terminal or directly in code. - Uses MSDScript interpreter.
- Using API functions directly. - For using API in C++.
Additionally, this program uses pointer.h to use std::shared_ptr() and helper functions to avoid memory leaks.
The user will have to follow this table to substitute general C++ keyword.
NEW(T) new T
PTR(T) T*
CAST(T) dynamic_cast<T*>
CLASS(T) class T
THIS this
In this guide, every expression will have either literals provided in its description.
-
Numbers
- Any positive or negative number.
- The use of separators, decimals or any other character that is not a number is illegal. Only a negative sign can
be put right before the number.
- Legal Examples:
1100232-23124
- Illegal Examples:
1.11,0001 1 1 01/4
- Legal Examples:
- Parser Syntax:
1000or any positive or negative number that follow the rules above. - Library Syntax:
PTR(Expr) two = NEW (NumExpr)(2);
-
Variables
- Any continuous string of only alphabets.
- The use of separators, decimals or any other character that is not an alphabet is illegal.
- Legal Examples:
xVARxyz
- Illegal Examples:
z.1x13dsd d s
- Legal Examples:
- Parser Syntax:
xor any other variable. - Library Syntax:
PTR(Expr) var1 = NEW (VarExpr)("hello");
-
Addition
-
Addition expression is basically
Expression1 + Expression2 -
If using parser, the use of
+is crucial to define an addition expression.- Legal Examples:
x + y1 + 2(1 + (-1))
- Illegal Examples:
1 - 11 -+ 1
- Legal Examples:
-
Parser Syntax:
expr + expr -
Library Syntax:
PTR(Expr)add1 = NEW (AddExpr)(expr1, expr2);wheretwoandthreeare expressions.
-
-
Multiplication
-
Multiplication expression is basically
Expression1 * Expression2 -
If using parser, the use of
*is crucial to define a multiplication expression.- Legal Examples:
x * y1 * 2(1 * (-1))
- Illegal Examples:
1 / 1
- Legal Examples:
-
Parser Syntax:
expr * expr -
Library Syntax:
PTR(Expr) mult1 = NEW (MultExpr)(expression1, expression2);
-
-
Boolean
-
Boolean expressions are basically
trueorfalse -
If using parser, the use of
_beforetrueorfalseis crucial to define a boolean expression.-
Legal Examples:
_false_true
-
Illegal Examples:
true1false0
-
-
Parser Syntax:
_trueor_false. -
Library Syntax:
PTR(Expr) trueExpr1 = NEW (BoolExpr)(boolean);
-
-
Let
var=exprinexpr-
_let <variable> = <expr>will assign the<variable>to the<expr>, then the<expr>is substituted in place of<variable>after_in. -
If using parser, the use of
_beforeletorinis crucial to define a let expression.-
Legal Examples:
_let x = 15 _in x + 1
-
Illegal Examples:
let x = 13 in x + 1_let 13 = x _in 13 + x
-
-
Parser Syntax:
_letvariable=expression1_inexpression2. -
Library Syntax:
PTR(Expr) let1 = NEW (LetExpr)(variable,expression1,expression2);
-
-
If
boolthenexprelseexpr-
_if <boolean>will check if true or false, if true, the_then <expr>will run else_else <expr>will run. -
If using parser, the use of
_beforeif,thenandelseis crucial to define an if expression.-
Legal Examples:
_if _true _then x + 1 _else x
-
Illegal Examples:
_if 2 _then x + 1 _else xif true then x + 1 else x
-
-
Parser Syntax:
_ifboolean_thenexpression1_elseexpression2. -
Library Syntax:
PTR(Expr) e1 = NEW (IfExpr)(boolean,expression1,expression2);
-
-
Equivalence
-
Equivalence expression is basically
Expression1 == Expression2 -
booleancompared tobooleanwill return desired result. -
numbercompared tobooleanwill always return false. -
exprcompared toexprwhereexprwith the same kind of value will return desired result. -
Undefined variable comparison will cause errors.
-
If using parser, the use of
==is crucial to define an equivalence expression.-
Legal Examples:
_true == _true_true == _false_true == 1
-
Illegal Examples:
1 = 1x == 2x == y
-
-
Parser Syntax:
expr1==expr2. -
Library Syntax:
PTR(Expr) e1 = NEW (EqualExpr)(expr1, expr2);
-
-
Functions
-
Similar to
_letin terms of functionality. -
Interpreter will interpret a function if the following syntax is followed:
_fun (variable) (expression) -
If using parser, the use of
_beforefunis crucial to define a function.-
Legal Examples:
_fun (x) x + 1is the same asf(x) = x + 1
-
Illegal Examples:
fun (x) x + 1(_fun (x) x) 1
-
-
Parser Syntax:
_fun (variable) (expr). -
Library Syntax:
PTR(Expr) e1 = NEW (FunExpr)(variable,expr);
-
-
Function Calls
-
Used in conjunction to functions to input value into the variable.
-
Interpreter will interpret a function if the following syntax is followed:
(_fun (variable) (expression1)) (expression2) -
If using parser, the use of
_beforefunis crucial to define a function.-
Legal Examples:
(_fun (x) x + 1)(1)will interpret to2
-
Illegal Examples:
(_fun (x) x) 1
-
-
Parser Syntax:
expr1 (expr2), with the non-syntactic constraint thatexpr1has a function value. -
Library Syntax:
PTR(Expr) e5 = NEW (CallExpr)(expr1,expr2);
-
Find the API Documentation below.
-
PTR(Expr) parse(std::istream &in)takes a input stream, parses it and returns an expression of the parsed input.@param &in- An input stream to parse.@returnsExpression of the parsed input.- Example -
parse(std:in);
-
PTR(Expr) parse_str(std::string s)takes a string, parses it and returns an expression of the parsed input.@param &s- A string you want to parse.@returnsExpression of the parsed input.- Example -
parse_str("1 + 1");
Additionally, once these functions return an expression, they can be,
- Interpreted -
parse_str("1 + 1")->interp(); - Printed -
parse_str("1 + 1")->to_string(false); - Pretty Printed -
parse_str("1 + 1")->to_string(true); - Compared -
parse_str("1 + 1")->equals(parse_str("2")); - Interpreted & Compared -
parse_str("1 + 1")->interp()->equals(parse_str("2")->interp());
All the different kinds of expressions are basically child classes of the Expr class. All the functions mentioned below are overidden in every sub class. The best practice would be to always create an Expr object and then define it will a sub expression class. For example, PTR(Expr) e1 = NEW(NumExpr)(2);.
-
std::string to_string(bool isPretty)returns a string of the expression based onisPrettyparameter.@param isPretty- Whether you want full form or reduced form of print.@returnsa string with the printed value.
-
bool equals(PTR(Expr)(e))returns a boolean value if the expression compared to the other expression has the exact same object contents.@param e- The expression to compare to.@returnstrue if the expression is exactly the same as the other else returns false.
-
PTR(Val) interp(PTR(Env)env = Env::empty)returns a value if the expression can be interpreted into a final value.@param env- The environment object, the scope of the variable.@returnsa value object if the expression can be fully interpreted.
std::string to_string()will convert the value into a string and return it.
All these API functions should be more than enough to do just about everything in this program. Thank you for visiting, have fun with my program!