commit
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
# CMP-7009A Reassessment 001 - Interpreter + Maths Visualiser
|
||||
|
||||
## How to open and run
|
||||
|
||||
1. Open **CMP7009A.sln** in Visual Studio 2022 (with the ".NET desktop
|
||||
development" and "F# desktop language support" workloads installed).
|
||||
2. Set **GUI** as the startup project (right-click GUI project -> "Set as
|
||||
Startup Project").
|
||||
3. Press F5 to build and run. The `GUI` project references `Interpreter`
|
||||
directly (project reference), so both build together.
|
||||
|
||||
If you prefer the command line (with the .NET SDK installed):
|
||||
|
||||
```
|
||||
dotnet build CMP7009A.sln
|
||||
dotnet run --project GUI
|
||||
```
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
CMP7009A.sln
|
||||
Interpreter/
|
||||
Interpreter.fsproj F# class library
|
||||
Interpreter.fs Tokenizer, parser, evaluator, public Engine class
|
||||
GUI/
|
||||
GUI.csproj C# WPF application (references Interpreter)
|
||||
App.xaml / App.xaml.cs
|
||||
MainWindow.xaml Input box, output box, drawing canvas
|
||||
MainWindow.xaml.cs Wires the UI to Engine; draws axes and lines
|
||||
```
|
||||
|
||||
## Using the app
|
||||
|
||||
Type into the input box and press Enter or click Run:
|
||||
|
||||
- `3 + 4 x 2` -> expression evaluation (`x` is multiplication) -> `11`
|
||||
- `a = 5` -> assignment, output shows `a = 5`; `a` is remembered
|
||||
- `a x 2 + 1` -> uses the stored variable `a` -> `11`
|
||||
- `y = 2x + 1` -> parsed as a line equation and drawn on the canvas
|
||||
- `y = x + 5` -> coefficient defaults to 1
|
||||
- `y = -2x - 3` -> negative coefficient/intercept supported
|
||||
- `y = ax + b` (after `a` and `b` have been assigned) -> uses their values
|
||||
|
||||
## BNF grammar (for the report's Implementation section)
|
||||
|
||||
```
|
||||
<statement> ::= <ident> "=" <expr> | <expr>
|
||||
|
||||
<expr> ::= <term> { ("+" | "-") <term> }
|
||||
<term> ::= <factor> { ("x" | "/") <factor> }
|
||||
<factor> ::= <number> | <ident> | "(" <expr> ")" | "-" <factor>
|
||||
|
||||
<number> ::= <integer> | <float>
|
||||
<integer> ::= <digit> [<digit> [<digit>]] (1 to 3 digits)
|
||||
<float> ::= <digit> [<digit>] "." <digit> [<digit>] (1-2 digits . 1-2 digits)
|
||||
|
||||
<ident> ::= <letter> [<alnum> [<alnum> [<alnum>]]] (max 4 characters)
|
||||
|
||||
<digit> ::= "0" | "1" | ... | "9"
|
||||
<letter> ::= "a" | ... | "z" | "A" | ... | "Z"
|
||||
<alnum> ::= <digit> | <letter>
|
||||
```
|
||||
|
||||
Separate line-drawing syntax (parsed directly from raw characters in
|
||||
`Engine.ParseLine`, since `x` is already the multiplication operator token
|
||||
in the grammar above):
|
||||
|
||||
```
|
||||
<line> ::= "y" "=" [ "-" ] [ <coefValue> ] ("x"|"X") ("+"|"-") <interceptValue>
|
||||
<coefValue> ::= <number> | <ident>
|
||||
<interceptValue> ::= <number> | <ident>
|
||||
```
|
||||
|
||||
## Design notes (for the report)
|
||||
|
||||
- **No library parsing functions are used.** The tokenizer builds integer
|
||||
and float values digit-by-digit using manual accumulator recursion
|
||||
(see `buildIntValue` / `buildFracValue` in `Interpreter.fs`); it does not
|
||||
call `Int32.Parse`, `Double.Parse`, `TryParse`, `String.Split`, or any
|
||||
regular expression. Identifiers are built character-by-character with a
|
||||
recursive `buildStr` helper instead of `Substring`.
|
||||
- **No collection-library functions are used.** List reversal
|
||||
(`reverseAcc`) and the variable environment lookup/update
|
||||
(`lookupVar` / `updateEnv`) are hand-written recursive functions over a
|
||||
plain association list, rather than `List.rev`, `Map`, or `Dictionary`.
|
||||
- **The only library/framework usage is the WPF `Canvas` and shape classes**
|
||||
(`Line`, `TextBlock`) in `MainWindow.xaml.cs`, which the assignment brief
|
||||
explicitly permits.
|
||||
- **Class diagram / sequence diagram**: the report should show
|
||||
`MainWindow` -> `Engine.Evaluate` / `Engine.ParseLine` -> internal
|
||||
`tokenize` -> `parseTokens` -> `evalExpr` pipeline for the class diagram,
|
||||
and a sequence diagram for the line-drawing path:
|
||||
`User -> MainWindow.RunInput -> Engine.ParseLine -> MainWindow.DrawLine -> Canvas`.
|
||||
- **Line-drawing algorithm**: the line is drawn using two endpoint
|
||||
coordinates computed analytically from `y = ax + b` at the left and right
|
||||
edges of the visible canvas, converted from maths coordinates to pixel
|
||||
coordinates via a fixed `Scale` (pixels per unit) and the canvas centre as
|
||||
the origin, then rendered with WPF's built-in `Line` shape (this is the
|
||||
permitted library use for the canvas itself - no custom rasterisation
|
||||
algorithm like Bresenham is needed because WPF's vector `Line` element
|
||||
handles anti-aliased rendering).
|
||||
|
||||
## Testing suggestions (for the report's Testing section)
|
||||
|
||||
Arithmetic:
|
||||
- `1 + 2`, `10 - 4`, `6 x 7`, `20 / 4`, `(1 + 2) x 3`, `10 / (5 - 5)` (division by zero error)
|
||||
- `999` (max 3-digit int, valid), `1000` (should error - exceeds 3 digits)
|
||||
- `99.99` (max digits, valid), `100.5` (should error - integer part too long)
|
||||
- `ab1` = `5` (valid 3-char identifier), `abcde` (should error - exceeds 4 chars)
|
||||
|
||||
Line drawing:
|
||||
- `y = 2x + 1`, `y = -x + 3`, `y = 0.5x - 2`, `y = ax + b` after assigning `a` and `b`
|
||||
Reference in New Issue
Block a user