- Unix
$ node -v
v14.2.0
$ npm -v
6.14.4
// not a requirement, only info
$ docker -v
Docker version 19.03.9, build 9d988398e7
git clone https://github.com/dohjon/calculator.git
npm install
npm test
Docker support
// Step 1. change code
...
// Step 2. build
docker build -t calculator:latest .
// Step 3. run
// arguments
docker run \
--rm \
-it \
--workdir /usr/src/app \
--volume $(pwd):/usr/src/app \
--init \
calculator:latest x add 3 print x
// interactive
docker run \
--rm \
-it \
--workdir /usr/src/app \
--volume $(pwd):/usr/src/app \
--init \
calculator:latest
// file
docker run \
--rm \
-it \
--workdir /usr/src/app \
--volume $(pwd):/usr/src/app \
--init \
calculator:latest test.txt
// link bin to path
sudo npm link
// or use path
$ lib/calculator.js
// arguments
$ calculator x add 3 print x
// interactive
$ calculator
// file
$ calculator text.txt
-
Assumption: Cross platform support is not needed.
-
Assumption: data does not need to be saved after application exits
-
Assumption: no advanced error handling
-
Assumption: only synchronous code
-
Assumption: no need to handle signals (SIGINT, SIGTERM, etc) in interactive mode
-
Assumption: no need to optimize by using steams (read file content into memory)
-
Assumption: process should exit with 0 even when invalid tokens.
-
Assumption: no special characters needs to be supported
-
Assumption: operations words cannot be valid register word
-
Assumption: quit, print cannot be valid register word
-
Assumption: Beacuse this is a test I avoided using external libraries except for linting, formatting and testing. In the real world I would use existing libraries for everything.
-
Assumption: Circular dependency is not implemenented. Input using below examples will cause endless recursion.
x => y
y => x
And
x => y
y => y
Scan => Parse => Evaluate => Calculate
Converts a string to tokens.
'x add 3'
To
['x', 'add', '3']
Converts tokens to AST (abstract syntax tree)
['x', 'add', '3', 'print', 'x']
To
[
{
val: 'x',
type: REGISTER,
children: [
{
val: 'add',
type: OPERATION,
children: [
{
val: 3,
type: VALUE,
children: [],
},
],
},
],
},
{
val: 'print',
type: PRINT,
children: [
{
val: 'x',
type: REGISTER,
children: [],
},
],
}
]
Add new operation handler in operations.js
function division(a, b) {
return a / b;
}
Add handler to operations in operations.js
const operations = {
division: division,
...
};
Add name of handler to operation in parser/rules.js
const operation = `^division$`;