The MSDScript is a programming language interpreter implemented by C++. It has some basic features like JavaScript and we can execute it through command line.
Addition Multiplication Comparison Boolean Human language parsing Variable bind If/else conditions Function execution
<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>
The precedence of the operators is ==
, +
, *
, _bool
,if/else
,function
. (from low precedence to high).
By the command line:
Drect to the msdscript file which contains the makefile, then run make
to compile the file.
After, we can get a out file -> msdscript
we can use command like ./msdscript --operation
to run our msdsrcipt coomand.
Operations list:
./msdscript --help
: get the manual of MSDScript
./msdscript --test
: execute the test part for the debug pattern
./msdscript --interp
: excute the MSDScript function
./msdscript --print
: parse human language and print out the valid MSDScript experssion
MSDScript can be run via the command line.
How to execute:
First use the ./msdscript --interp
command to start interpreting.
Then We need to use Ctrl+D
to begin the execute.
Numbers experssion should not contain commas, decimals or spaces between characters and numbers.
Examples:
Valid: 1+2
or 1 + 2
or 1 + 2
.
Invalid: 2,000 + 7.5
or 4 000 + 10
.
Variables' input rule like other languages as C++, variables are valid for any combinations of character between 'a - z' and 'A - Z' but invalid for starting of digit or _.
Examples:
Valid: x1
or abc
or string
.
Invalid: 1x
or _x
.
Booleans is represented as _true
or _false
.
Addition and Multiplication are represented as +
and *
.
Note : the subexpressions of +
and *
must produce numbers like 1 + 2
or 1 * 2
instead of x + 1
or x * 1
.
While the Comparison as ==
can compare variable and number and return true or false.
In the MSDScript we use EqualExpr
expressions to represent ==
. We will talk about in the API part.
Comparison is represented as ==
.
The _let
keyword assign value to a variable.
This keyword should be followed by an variable at the left and the assigned value at the right.
Examples:
_let x = 5 _in (_let y = 3 _in y + 2) + x
(_let x = 5 _in x) + 1
Note Parentheses should be put around the smallest expression needed to resolve an ambiguity.
This expersstion is similar to ternary operator in Java. It has 3 parts:
- Evaluation Section: if true, execute step 2, or step 3.
- then true branch.
- else false branch.
They are comprised of the_if
,_then
, and_else
keywords
Format:
_if //this
_then //do this
_else //do that
Functions are represented by the _fun
keyword.
Like JavaScript, everything is derived from the prototypes, the MSDScript expressions are derived from one class, so the function is same type as value and number.
The left part as ()
should be variables and follwing will be the function body.
The first subexpression of a function-call must have a function value so the definiltion like _fun() x + 1
is invalid.
Examples:
_fun (x) x + 1
creates function that add 1 to value x.
To execute a function, you should pass the value into the function after the close parentheses of ()
.
Examples:
(_fun (x) x + 1) (2)
will execute the answer 3.
The core files support the running of msdscript:
env.cpp and env.hpp
: Allow for quicker replacing of variable values.
expr.cpp and expr.hpp
: Expression files.
value.cpp and value.hpp
: Values used for function call.
The helper files help configure the msdscript and build user interface.
pointer.h
: MSDScript without shared pointers may result in memory leak so we use this file to configure the shared pointer.
main.cpp
: This file used to execute msd command like ./msdscript --interp
.
parse.cpp
and parse.hpp
: Used to parse human language to msdscript readable experssion.
Catch.cpp
: This framework will execute when doing testing.
The Expressions mean all the features that MSDScript have.
Grammer means parsing with conditions and comparisons.
Expressions:
<expr> = <NumExpr>
| <BoolExpr>
| <expr> == <expr> (EqualExpr)
| <expr> + <expr> (AddExpr)
| <expr> * <expr> (MultExpr)
| <VarExpr>
| _let <variable> = <expr> _in <expr> (LetExpr)
| _if <expr> _then <expr> _else <expr> (IfExpr)
| _fun(<VarExpr>)<expr> (FunExpr)
| <expr>(<expr>)
<Val> = <number>
| <boolean>
| _fun(〈variable〉)〈expr〉
expr is the basic class of MSDScipt, all the expressions are derived(or inherited)from this class.
That is why the function, value, and number expressions can be treated as the same type of 'variable'. Not like C++, we can operate functions like numbers!
The types or the subclass of expr is shown before.
When you run MSDScript in the interp pattern, the MSDScript will implement the parse
class to formate input and translate it to MSDScript expressions which can be executed by the Script.
Below are some key method of wrapping user's input:
PTR(expr)parse(std::istream &in)
Extract the input stream, parses it, and returns the entire input as an expr.
Like the grammer shown before, MSDScipt will parse the input like 'recursion', so the method 'linkedlist' is:
`PTR(expr)parse_expr(std::istream &in)` // parse '=='
|
`PTR(expr)parse_comparg(std::istream &in)` // parse '+'
|
`PTR(expr)parse_addend(std::istream &in)` // parse '*'
|
`PTR(expr)parse_multicand(std::istream &in)` // parse 'inner function' like _let, _boolean and _fun
|
`PTR(expr)parse_inner(std::istream &in)`
For the inner part, MSDSCript implement the help method like PTR(expr)parse_if(std::istream &in)
and PTR(expr)parse_fun(std::istream &in)
to help parse the expression.
The return type of parse is always an expr.
interp
is to find the value of an expression and this method return a new class Val which can be convert to a string so the MSDScript will response after calling function or expersions.
The implement of parse and interp is
PTR(expr) e = parse(std::cin);
cout<<e->interp(NEW(EmptyEnv)())->to_string()<<endl;