├── .gitattributes
├── .gitignore
├── .nuke
├── build.schema.json
└── parameters.json
├── .vscode
├── launch.json
└── tasks.json
├── LICENSE.md
├── README.md
├── build.cmd
├── build.ps1
├── build.sh
├── init.cmd
├── init.ps1
├── init.sh
├── nuget.config
├── screenshot.png
├── src
├── .editorconfig
├── Directory.Build.props
├── Directory.Build.targets
├── Directory.Packages.props
├── Environment.props
├── NotepadBasedCalculator.App.sln
├── app
│ ├── dev
│ │ ├── Directory.Build.props
│ │ ├── Directory.Build.targets
│ │ ├── NotepadBasedCalculator.Api
│ │ │ ├── AbstractSyntaxTree
│ │ │ │ ├── AbstractSyntaxTreeBase.cs
│ │ │ │ ├── BinaryOperatorExpression.cs
│ │ │ │ ├── BinaryOperatorType.cs
│ │ │ │ ├── DataExpression.cs
│ │ │ │ ├── Expression.cs
│ │ │ │ ├── FunctionExpression.cs
│ │ │ │ ├── GroupExpression.cs
│ │ │ │ ├── ReferenceExpression.cs
│ │ │ │ ├── Statement.cs
│ │ │ │ ├── VariableDeclarationStatement.cs
│ │ │ │ └── VariableReferenceExpression.cs
│ │ │ ├── Core
│ │ │ │ ├── CultureHelper.cs
│ │ │ │ ├── DictionaryExtensions.cs
│ │ │ │ ├── DictionaryWithSpecialEnumValueConverter.cs
│ │ │ │ ├── EnumExtension.cs
│ │ │ │ ├── ExtensionOrderer.cs
│ │ │ │ └── Threading
│ │ │ │ │ ├── AsyncLazy.cs
│ │ │ │ │ ├── CancellationTokenExtension.cs
│ │ │ │ │ ├── DisposableSempahore.cs
│ │ │ │ │ ├── TaskExtension.cs
│ │ │ │ │ └── TaskSchedulerAwaiter.cs
│ │ │ ├── Data
│ │ │ │ ├── Data.cs
│ │ │ │ ├── Definition
│ │ │ │ │ ├── AngleData.cs
│ │ │ │ │ ├── AreaData.cs
│ │ │ │ │ ├── BooleanData.cs
│ │ │ │ │ ├── CurrencyData.cs
│ │ │ │ │ ├── CurrencyValue.cs
│ │ │ │ │ ├── DateTimeData.cs
│ │ │ │ │ ├── DecimalData.cs
│ │ │ │ │ ├── DurationData.cs
│ │ │ │ │ ├── FractionData.cs
│ │ │ │ │ ├── InformationData.cs
│ │ │ │ │ ├── LengthData.cs
│ │ │ │ │ ├── MassData.cs
│ │ │ │ │ ├── OrdinalData.cs
│ │ │ │ │ ├── PercentageData.cs
│ │ │ │ │ ├── SpeedData.cs
│ │ │ │ │ ├── TemperatureData.cs
│ │ │ │ │ └── VolumeData.cs
│ │ │ │ ├── IData.cs
│ │ │ │ ├── IDataParser.cs
│ │ │ │ ├── IDecimal.cs
│ │ │ │ ├── INumericData.cs
│ │ │ │ ├── ISupportMultipleDataTypeForArithmeticOperation.cs
│ │ │ │ └── IValueRelativeToOtherData.cs
│ │ │ ├── DataOperationException.cs
│ │ │ ├── Grammar
│ │ │ │ ├── FunctionDefinition.cs
│ │ │ │ ├── IFunctionDefinitionProvider.cs
│ │ │ │ ├── IGrammarProvider.cs
│ │ │ │ └── TokenDefinitionGrammar.cs
│ │ │ ├── IArithmeticAndRelationOperationService.cs
│ │ │ ├── ICurrencyService.cs
│ │ │ ├── ILogger.cs
│ │ │ ├── IMefProvider.cs
│ │ │ ├── IncompatibleUnitsException.cs
│ │ │ ├── Lexer
│ │ │ │ ├── ILexer.cs
│ │ │ │ ├── IToken.cs
│ │ │ │ ├── ITokenEnumerator.cs
│ │ │ │ ├── LinkedToken.cs
│ │ │ │ ├── LinkedTokenExtensions.cs
│ │ │ │ ├── PredefinedTokenNames.cs
│ │ │ │ ├── Token.cs
│ │ │ │ └── TokenizedTextLine.cs
│ │ │ ├── Metadata
│ │ │ │ ├── CultureAttribute.cs
│ │ │ │ ├── CultureCodeMetadata.cs
│ │ │ │ ├── FunctionInterpreterMetadata.cs
│ │ │ │ ├── IOrderableMetadata.cs
│ │ │ │ ├── NameAttribute.cs
│ │ │ │ ├── OrderAttribute.cs
│ │ │ │ ├── ParserAndInterpreterMetadata.cs
│ │ │ │ └── SupportedCultures.cs
│ │ │ ├── NotepadBasedCalculator.Api.csproj
│ │ │ ├── ParserAndInterpreter
│ │ │ │ ├── ExpressionParserAndInterpreterResult.cs
│ │ │ │ ├── IExpressionParserAndInterpreter.cs
│ │ │ │ ├── IFunctionInterpreter.cs
│ │ │ │ ├── IParserAndInterpreterService.cs
│ │ │ │ ├── IParserAndInterpretersRepository.cs
│ │ │ │ ├── IStatementParserAndInterpreter.cs
│ │ │ │ ├── IVariableService.cs
│ │ │ │ ├── PredefinedExpressionParserAndInterpreterNames.cs
│ │ │ │ ├── PredefinedStatementParserAndInterpreterNames.cs
│ │ │ │ └── StatementParserAndInterpreterResult.cs
│ │ │ └── UnsupportedArithmeticOperationException.cs
│ │ ├── NotepadBasedCalculator.BuiltInPlugins
│ │ │ ├── Data
│ │ │ │ ├── BooleanDataParser.cs
│ │ │ │ ├── CurrencyDataParser.cs
│ │ │ │ ├── DateTimeDataParser.cs
│ │ │ │ ├── NumberDataParser.cs
│ │ │ │ ├── OrdinalDataParser.cs
│ │ │ │ ├── PercentageDataParser.cs
│ │ │ │ ├── TemperatureDataParser.cs
│ │ │ │ ├── UnitDataParser.cs
│ │ │ │ └── UnitMap.cs
│ │ │ ├── ExpressionParsersAndInterpreters
│ │ │ │ ├── Conditional
│ │ │ │ │ └── ConditionalExpressionParserAndInterpreter.cs
│ │ │ │ ├── Function
│ │ │ │ │ └── FunctionExpressionParserAndInterpreter.cs
│ │ │ │ └── Numerical
│ │ │ │ │ ├── NumericalExpressionParserAndInterpreter.cs
│ │ │ │ │ └── PrimitiveExpressionParserAndInterpreter.cs
│ │ │ ├── Functions
│ │ │ │ ├── General
│ │ │ │ │ ├── MidpointInterpreter.cs
│ │ │ │ │ ├── RandomNumberInterpreter.cs
│ │ │ │ │ └── RemainderInterpreter.cs
│ │ │ │ └── Percentage
│ │ │ │ │ ├── IsPercentOfWhatInterpreter.cs
│ │ │ │ │ ├── IsPercentOnWhatInterpreter.cs
│ │ │ │ │ ├── IsWhatPercentOfInterpreter.cs
│ │ │ │ │ ├── IsWhatPercentOffInterpreter.cs
│ │ │ │ │ ├── IsWhatPercentOnInterpreter.cs
│ │ │ │ │ ├── PercentOfInterpreter.cs
│ │ │ │ │ ├── PercentOffInterpreter.cs
│ │ │ │ │ └── PercentOnInterpreter.cs
│ │ │ ├── Grammars
│ │ │ │ ├── FunctionDefinitionProvider.cs
│ │ │ │ ├── GrammarProvider.cs
│ │ │ │ ├── SpecialTokenDefinition.json
│ │ │ │ ├── UnitMapProvider.cs
│ │ │ │ ├── en-us
│ │ │ │ │ ├── FunctionDefinition.json
│ │ │ │ │ ├── TokenDefinition.json
│ │ │ │ │ └── UnitNames.json
│ │ │ │ └── fr-fr
│ │ │ │ │ └── UnitNames.json
│ │ │ ├── NotepadBasedCalculator.BuiltInPlugins.csproj
│ │ │ └── StatementParsersAndInterpreters
│ │ │ │ ├── Comment
│ │ │ │ ├── CommentStatement.cs
│ │ │ │ └── CommentStatementParserAndInterpreter.cs
│ │ │ │ ├── Condition
│ │ │ │ ├── ConditionStatement.cs
│ │ │ │ ├── ConditionStatementParserAndInterpreter.cs
│ │ │ │ └── ConditionalExpressionStatementParserAndInterpreter.cs
│ │ │ │ ├── Function
│ │ │ │ └── FunctionExpressionStatementParserAndInterpreter.cs
│ │ │ │ ├── Header
│ │ │ │ ├── HeaderStatement.cs
│ │ │ │ └── HeaderStatementParserAndInterpreter.cs
│ │ │ │ ├── NumericalExpression
│ │ │ │ ├── NumericalCalculusStatement.cs
│ │ │ │ └── NumericalExpressionStatementParserAndInterpreter.cs
│ │ │ │ └── VariableDeclaration
│ │ │ │ └── VariableDeclarationStatementParserAndInterpreter.cs
│ │ ├── NotepadBasedCalculator.Core
│ │ │ ├── ArithmeticAndRelationOperationService.cs
│ │ │ ├── Assets
│ │ │ │ └── defaultExchangeRates.json
│ │ │ ├── Core
│ │ │ │ ├── CurrencyService.cs
│ │ │ │ └── DescendingComparer.cs
│ │ │ ├── Lexer.cs
│ │ │ ├── Logger.cs
│ │ │ ├── Mef
│ │ │ │ ├── MefComposer.cs
│ │ │ │ └── MefProvider.cs
│ │ │ ├── NotepadBasedCalculator.Core.csproj
│ │ │ ├── ParserAndInterpreter.cs
│ │ │ ├── ParserAndInterpreterFactory.cs
│ │ │ ├── ParserAndInterpreterResultLine.cs
│ │ │ ├── ParserAndInterpreterResultUpdatedEventArgs.cs
│ │ │ ├── ParserAndInterpreterService.cs
│ │ │ ├── ParserRepository.cs
│ │ │ ├── TextDocument.cs
│ │ │ └── VariableService.cs
│ │ ├── NotepadBasedCalculator.Desktop.Mac
│ │ │ ├── AppDelegate.cs
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── AppIcon.appiconset
│ │ │ │ │ ├── AppIcon-128.png
│ │ │ │ │ ├── AppIcon-128@2x.png
│ │ │ │ │ ├── AppIcon-16.png
│ │ │ │ │ ├── AppIcon-16@2x.png
│ │ │ │ │ ├── AppIcon-256.png
│ │ │ │ │ ├── AppIcon-256@2x.png
│ │ │ │ │ ├── AppIcon-32.png
│ │ │ │ │ ├── AppIcon-32@2x.png
│ │ │ │ │ ├── AppIcon-512.png
│ │ │ │ │ ├── AppIcon-512@2x.png
│ │ │ │ │ └── Contents.json
│ │ │ │ └── Contents.json
│ │ │ ├── Entitlements.plist
│ │ │ ├── Info.plist
│ │ │ ├── NotepadBasedCalculator.Desktop.Mac.csproj
│ │ │ ├── PlatformInitializer.cs
│ │ │ ├── Program.cs
│ │ │ ├── Properties
│ │ │ │ └── AssemblyInfo.cs
│ │ │ └── Services
│ │ │ │ └── ThemeService.cs
│ │ ├── NotepadBasedCalculator.Desktop.Windows
│ │ │ ├── NotepadBasedCalculator.Desktop.Windows.csproj
│ │ │ ├── PlatformInitializer.cs
│ │ │ ├── Program.cs
│ │ │ ├── Properties
│ │ │ │ └── AssemblyInfo.cs
│ │ │ └── Services
│ │ │ │ └── ThemeService.cs
│ │ ├── NotepadBasedCalculator.Desktop
│ │ │ ├── App.axaml
│ │ │ ├── App.axaml.cs
│ │ │ ├── MainWindow.axaml
│ │ │ ├── MainWindow.axaml.cs
│ │ │ ├── NotepadBasedCalculator.Desktop.csproj
│ │ │ └── Platform
│ │ │ │ ├── IPlatformInitializer.cs
│ │ │ │ └── Services
│ │ │ │ ├── IUiService.cs
│ │ │ │ └── Theme
│ │ │ │ ├── AppTheme.cs
│ │ │ │ ├── IThemeService.cs
│ │ │ │ └── UserPreferredTheme.cs
│ │ └── shared
│ │ │ ├── GlobalUsings.cs
│ │ │ ├── SharedAssemblyInfo.cs
│ │ │ └── SharedAssemblyVersion.cs
│ ├── tests
│ │ ├── NotepadBasedCalculator.Core.Tests
│ │ │ ├── AlgebraTests.cs
│ │ │ ├── BinaryOperationTests.cs
│ │ │ ├── DataParserTests.cs
│ │ │ ├── ExpressionParsersTests.cs
│ │ │ ├── ExtensionOrdererTests.cs
│ │ │ ├── FunctionTests.cs
│ │ │ ├── InterpreterTests.cs
│ │ │ ├── LexerTests.cs
│ │ │ ├── MefBaseTest.cs
│ │ │ ├── NotepadBasedCalculator.Core.Tests.csproj
│ │ │ ├── OperationHelperTests.cs
│ │ │ ├── ParserTests.cs
│ │ │ ├── StatementParsersTests.cs
│ │ │ └── TestHelper.cs
│ │ └── NotepadBasedCalculator.StandaloneConsoleTestApp
│ │ │ ├── NotepadBasedCalculator.StandaloneConsoleTestApp.csproj
│ │ │ └── Program.cs
│ └── tools
│ │ ├── Directory.Build.props
│ │ └── NotepadBasedCalculator.Benchmark
│ │ ├── CalculatorBenchmarks.cs
│ │ ├── NotepadBasedCalculator.Benchmark.csproj
│ │ └── Program.cs
└── build
│ ├── .editorconfig
│ ├── AppVersion
│ ├── AppVersion.cs
│ ├── AppxManifestUpdater.cs
│ ├── CSharpUpdater.cs
│ ├── CSharpVersionUpdateRule.cs
│ ├── VersionString.cs
│ └── VersionUpdateRule.cs
│ ├── Build.cs
│ ├── Configuration.cs
│ ├── Directory.Build.props
│ ├── Directory.Build.targets
│ ├── DotnetParameters.cs
│ ├── PlatformTarget.cs
│ ├── _build.csproj
│ └── _build.csproj.DotSettings
└── tools
├── Install-DotNet.ps1
├── Install-DotNet.sh
└── app-version-number.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.nuke/parameters.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./build.schema.json",
3 | "Solution": "src/NotepadBasedCalculator.App.sln"
4 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | // Use IntelliSense to find out which attributes exist for C# debugging
6 | // Use hover for the description of the existing attributes
7 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
8 | "name": "Desktop macOS App (launch)",
9 | "type": "coreclr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | // If you have changed target frameworks, make sure to update the program path.
13 | "program": "${workspaceFolder}/bin/Debug/anycpu/NotepadBasedCalculator.Desktop.Mac/net6.0-macos/osx-x64/NotepadBasedCalculator.Desktop.Mac.app/Contents/MacOS/NotepadBasedCalculator.Desktop.Mac",
14 | "args": [],
15 | "cwd": "${workspaceFolder}",
16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
17 | "console": "internalConsole",
18 | "stopAtEntry": false
19 | },
20 | {
21 | // Use IntelliSense to find out which attributes exist for C# debugging
22 | // Use hover for the description of the existing attributes
23 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
24 | "name": "Desktop Windows App (launch)",
25 | "type": "coreclr",
26 | "request": "launch",
27 | "preLaunchTask": "build",
28 | // If you have changed target frameworks, make sure to update the program path.
29 | "program": "${workspaceFolder}\\bin\\Debug\\AnyCPU\\NotepadBasedCalculator.Desktop.Windows\\net6.0-win10\\NotepadBasedCalculator.Desktop.Windows.exe",
30 | "args": [],
31 | "cwd": "${workspaceFolder}",
32 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
33 | "console": "internalConsole",
34 | "stopAtEntry": false
35 | }
36 | ]
37 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "type": "shell",
7 | "command": "${workspaceFolder}/build.sh Compile --incremental-build true --configuration Debug",
8 | "windows": {
9 | "command": "${workspaceFolder}\\build.cmd Compile --incremental-build true --configuration Debug"
10 | }
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Etienne Baudoux
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | :; set -eo pipefail
2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
3 | :; ${SCRIPT_DIR}/build.sh "$@"
4 | :; exit $?
5 |
6 | @ECHO OFF
7 | powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
8 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | Param(
3 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
4 | [string[]]$BuildArguments
5 | )
6 |
7 | function ExecSafe([scriptblock] $cmd) {
8 | & $cmd
9 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
10 | }
11 |
12 | Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
13 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
14 |
15 | # Install .Net
16 | ExecSafe { & $PSScriptRoot\tools\Install-DotNet.ps1 -RootFolder $PSScriptRoot }
17 |
18 | # Build the builder project.
19 | Write-Host "Building the pipeline"
20 | $BuildProjectFile = "$PSScriptRoot\src\build\_build.csproj"
21 |
22 | ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
23 | Write-Host "Done."
24 | Write-Output "---------------------------------------"
25 |
26 | # Run the builder
27 | ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }
28 | Write-Host "Done."
29 | Write-Output "---------------------------------------"
30 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -eo pipefail
4 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
5 |
6 | # Install .Net
7 | . "./tools/Install-DotNet.sh" $SCRIPT_DIR
8 |
9 | # Build the build project.
10 | echo "Building the pipeline"
11 | BUILD_PROJECT_FILE="$SCRIPT_DIR/src/build/_build.csproj"
12 |
13 | "$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
14 | echo "Done."
15 | echo "--------------------------------------"
16 |
17 | # Run the building
18 | "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
19 | echo "Done."
20 | echo "--------------------------------------"
21 |
--------------------------------------------------------------------------------
/init.cmd:
--------------------------------------------------------------------------------
1 | :; set -eo pipefail
2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
3 | :; ${SCRIPT_DIR}/init.sh "$@"
4 | :; exit $?
5 |
6 | @ECHO OFF
7 | powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0init.ps1" %*
8 |
--------------------------------------------------------------------------------
/init.ps1:
--------------------------------------------------------------------------------
1 | function ExecSafe([scriptblock] $cmd) {
2 | & $cmd
3 | if ($LASTEXITCODE) { exit $LASTEXITCODE }
4 | }
5 |
6 | Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
7 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
8 |
9 | # Install .Net
10 | ExecSafe { & $PSScriptRoot\tools\Install-DotNet.ps1 -RootFolder $PSScriptRoot }
11 |
12 | # Restore workloads
13 | Write-Host "Restoring all workloads"
14 | ExecSafe { & $env:DOTNET_EXE workload install macos -v:quiet }
15 | Get-ChildItem $PSScriptRoot\src\ -rec |? { $_.FullName.EndsWith('proj') -and ($_.FullName.Contains('Mac') -or $_.FullName.Contains('iOS') -or $_.FullName.Contains('Android') -or $_.FullName.Contains('Windows') -or $_.FullName.Contains('Linux')) } |% {
16 | $ProjectPath = $_.FullName;
17 | Write-Host "Restoring workload for $($ProjectPath)..."
18 | ExecSafe { & $env:DOTNET_EXE workload restore -v:quiet --project $ProjectPath }
19 | }
20 | Write-Host "Done."
21 | Write-Output "---------------------------------------"
22 |
23 | # Restore NuGet solution dependencies
24 | Write-Host "Restoring all dependencies"
25 | Get-ChildItem $PSScriptRoot\src\ -rec |? { $_.FullName.EndsWith('.sln') } |% {
26 | $SolutionPath = $_.FullName;
27 | Write-Host "Restoring packages for $($SolutionPath)..."
28 | ExecSafe { & $env:DOTNET_EXE restore -v:quiet $SolutionPath }
29 | }
30 | Write-Host "Done."
31 | Write-Output "---------------------------------------"
--------------------------------------------------------------------------------
/init.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -eo pipefail
4 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
5 |
6 | # Install .Net
7 | . "./tools/Install-DotNet.sh" $SCRIPT_DIR
8 |
9 | # Restore workloads
10 | echo "Restoring all workloads"
11 | "$DOTNET_EXE" workload restore macos -v:quiet
12 | PROJECTS=$(find ./src/ -type f \( -name "*Mac.csproj" -o -iname "*Windows.csproj" -o -name "*iOS.csproj" -o -name "*Android.csproj" -o -name "*Linux.csproj" \) -print )
13 | for PROJECT_FILE in $PROJECTS
14 | do
15 | echo "Restoring workload for $PROJECT_FILE..."
16 | "$DOTNET_EXE" workload restore -v:quiet --project $PROJECT_FILE
17 | done
18 | echo "Done."
19 | echo "---------------------------------------"
20 |
21 | # Restore NuGet solution dependencies
22 | echo "Restoring all dependencies"
23 | SOLUTIONS=$(find ./src/ -iname "*.sln" -print)
24 | for SOLUTION_FILE in $SOLUTIONS
25 | do
26 | echo "Restoring packages for $SOLUTION_FILE..."
27 | "$DOTNET_EXE" restore -v:quiet $SOLUTION_FILE
28 | done
29 | echo "Done."
30 | echo "---------------------------------------"
31 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/veler/notepad-based-calculator/0748213d0dae153dc8d736a90a0db74f5c4766bd/screenshot.png
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 16.0
6 |
7 | netstandard2.0;netstandard2.1
8 | net6.0
9 | $(NetCore)-windows10.0.17763.0
10 | $(NetCore)-macos
11 | $(NetStandardVersion);$(NetCore)
12 |
13 |
14 | Debug
15 | Any CPU
16 | anycpu
17 | 10.0
18 | true
19 |
20 |
21 | $([System.IO.Path]::GetDirectoryName($([MSBuild]::GetPathOfFileAbove('.gitignore', '$(MSBuildThisFileDirectory)'))))\
22 | $(RepoRoot)bin\$(Configuration)\$(Platform)\
23 | $(BaseOutputPath)$(MSBuildProjectName)\
24 | $(RepoRoot)obj\$(Platform)\$(MSBuildProjectName)\
25 | $(BaseIntermediateOutputPath)
26 | $(BaseIntermediateOutputPath)Generated Files\
27 | $(RepoRoot)packages\
28 |
29 |
30 | true
31 |
32 |
33 |
34 | 16.0
35 |
36 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/Environment.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | $([MSBuild]::IsOSPlatform('Windows'))
4 | $([MSBuild]::IsOSPlatform('OSX'))
5 | $([MSBuild]::IsOSPlatform('Linux'))
6 |
7 |
8 |
9 | $(DefineConstants);MAC
10 |
11 |
--------------------------------------------------------------------------------
/src/app/dev/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | enable
7 | enable
8 | false
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/app/dev/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/AbstractSyntaxTreeBase.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public abstract class AbstractSyntaxTreeBase
4 | {
5 | public LinkedToken FirstToken { get; }
6 |
7 | public LinkedToken LastToken { get; }
8 |
9 | protected AbstractSyntaxTreeBase(LinkedToken firstToken, LinkedToken lastToken)
10 | {
11 | Guard.IsNotNull(firstToken);
12 | Guard.IsNotNull(lastToken);
13 | FirstToken = firstToken;
14 | LastToken = lastToken;
15 | }
16 |
17 | ///
18 | /// Gets a string representation of the expression or statement.
19 | ///
20 | /// String that reprensents the expression or statement
21 | public abstract override string ToString();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/BinaryOperatorExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Represents a binary conditional expression
5 | ///
6 | public sealed class BinaryOperatorExpression : Expression
7 | {
8 | ///
9 | /// Gets or sets the left expression
10 | ///
11 | public Expression LeftExpression { get; }
12 |
13 | ///
14 | /// Gets the binary operator
15 | ///
16 | public BinaryOperatorType Operator { get; }
17 |
18 | ///
19 | /// Gets or sets the right expression
20 | ///
21 | public Expression RightExpression { get; }
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | /// The left expression
27 | /// The binary operator
28 | /// The right expression
29 | public BinaryOperatorExpression(Expression leftExpression, BinaryOperatorType conditionalOperator, Expression rightExpression)
30 | : base(leftExpression.FirstToken, rightExpression.LastToken)
31 | {
32 | Guard.IsNotNull(leftExpression);
33 | Guard.IsNotNull(rightExpression);
34 | LeftExpression = leftExpression;
35 | Operator = conditionalOperator;
36 | RightExpression = rightExpression;
37 | }
38 |
39 | public override string ToString()
40 | {
41 | return $"({LeftExpression} {Operator.GetDescription()} {RightExpression})";
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/BinaryOperatorType.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Defines identifiers for supported binary operators
5 | ///
6 | public enum BinaryOperatorType
7 | {
8 | ///
9 | /// Identity equal operator
10 | ///
11 | [Description("==")]
12 | Equality = 0,
13 |
14 | ///
15 | /// Identity no equal operator
16 | ///
17 | [Description("!=")]
18 | NoEquality = 1,
19 |
20 | ///
21 | /// Less than operator
22 | ///
23 | [Description("<")]
24 | LessThan = 2,
25 |
26 | ///
27 | /// Less than or equal operator
28 | ///
29 | [Description("<=")]
30 | LessThanOrEqualTo = 3,
31 |
32 | ///
33 | /// Greater than operator
34 | ///
35 | [Description(">")]
36 | GreaterThan = 4,
37 |
38 | ///
39 | /// Greater than or equal operator
40 | ///
41 | [Description(">=")]
42 | GreaterThanOrEqualTo = 5,
43 |
44 | ///
45 | /// Addition operator
46 | ///
47 | [Description("+")]
48 | Addition = 6,
49 |
50 | ///
51 | /// Subtraction operator
52 | ///
53 | [Description("-")]
54 | Subtraction = 7,
55 |
56 | ///
57 | /// Multiplication operator
58 | ///
59 | [Description("*")]
60 | Multiply = 8,
61 |
62 | ///
63 | /// Division operator
64 | ///
65 | [Description("/")]
66 | Division = 9,
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/DataExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public class DataExpression : ReferenceExpression
4 | {
5 | public IData Data { get; }
6 |
7 | public DataExpression(LinkedToken firstToken, LinkedToken lastToken, IData data)
8 | : base(firstToken, lastToken)
9 | {
10 | Guard.IsNotNull(data);
11 | Data = data;
12 | }
13 |
14 | public override string ToString()
15 | {
16 | return Data.ToString() ?? string.Empty;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/Expression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Basic class that represents an expression in a statement.
5 | ///
6 | public abstract class Expression : AbstractSyntaxTreeBase
7 | {
8 | protected Expression(LinkedToken firstToken, LinkedToken lastToken)
9 | : base(firstToken, lastToken)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/FunctionExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public sealed class FunctionExpression : Expression
4 | {
5 | public FunctionDefinition FunctionDefinition { get; }
6 |
7 | public FunctionExpression(FunctionDefinition functionDefinition, LinkedToken firstToken, LinkedToken lastToken)
8 | : base(firstToken, lastToken)
9 | {
10 | FunctionDefinition = functionDefinition;
11 | }
12 |
13 | public override string ToString()
14 | {
15 | return $"function {FunctionDefinition.FunctionFullName}()";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/GroupExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Represents an expression between parenthesis.
5 | ///
6 | public sealed class GroupExpression : Expression
7 | {
8 | ///
9 | /// Gets or sets the expression in the group
10 | ///
11 | public Expression InnerExpression { get; }
12 |
13 | public GroupExpression(LinkedToken firstToken, LinkedToken lastToken, Expression innerExpression)
14 | : base(firstToken, lastToken)
15 | {
16 | Guard.IsNotNull(innerExpression);
17 | InnerExpression = innerExpression;
18 | }
19 |
20 | public override string ToString()
21 | {
22 | return $"({InnerExpression})";
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/ReferenceExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Basic class for a reference to something.
5 | ///
6 | public abstract class ReferenceExpression : Expression
7 | {
8 | protected ReferenceExpression(LinkedToken firstToken, LinkedToken lastToken)
9 | : base(firstToken, lastToken)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/Statement.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | ///
4 | /// Basic class that represents a statement.
5 | ///
6 | public abstract class Statement : AbstractSyntaxTreeBase
7 | {
8 | protected Statement(LinkedToken firstToken, LinkedToken lastToken)
9 | : base(firstToken, lastToken)
10 | {
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/VariableDeclarationStatement.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public sealed class VariableDeclarationStatement : Statement
4 | {
5 | public string VariableName { get; }
6 |
7 | public LinkedToken VariableNameStart { get; }
8 |
9 | public LinkedToken VariableNameEnd { get; }
10 |
11 | public Expression AssignedValue { get; }
12 |
13 | public VariableDeclarationStatement(LinkedToken variableNameStart, LinkedToken variableNameEnd, string variableName, Expression assignedValue)
14 | : base(variableNameStart, assignedValue.LastToken)
15 | {
16 | Guard.IsNotNull(variableNameStart);
17 | Guard.IsNotNull(variableNameEnd);
18 | Guard.IsNotNull(assignedValue);
19 | Guard.IsNotNullOrWhiteSpace(variableName);
20 | VariableNameStart = variableNameStart;
21 | VariableNameEnd = variableNameEnd;
22 | AssignedValue = assignedValue;
23 | VariableName = variableName;
24 | }
25 |
26 | public override string ToString()
27 | {
28 | return $"Variable $({VariableName}) = {AssignedValue}";
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/AbstractSyntaxTree/VariableReferenceExpression.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public sealed class VariableReferenceExpression : ReferenceExpression
4 | {
5 | public string VariableName { get; }
6 |
7 | public LinkedToken VariableToken { get; }
8 |
9 | public VariableReferenceExpression(LinkedToken token)
10 | : base(token, token)
11 | {
12 | Guard.IsNotNull(token);
13 | VariableToken = token;
14 | VariableName = token.Token.GetText();
15 | }
16 |
17 | public override string ToString()
18 | {
19 | return $"$({VariableName})";
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/CultureHelper.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public static class CultureHelper
4 | {
5 | ///
6 | /// Determines whether the given is compatible with the .
7 | ///
8 | public static bool IsCultureApplicable(string culture, string targetCulture)
9 | {
10 | Guard.IsNotNull(culture);
11 | Guard.IsNotNull(targetCulture);
12 | return culture == SupportedCultures.Any || string.Equals(culture, targetCulture, StringComparison.OrdinalIgnoreCase);
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/DictionaryExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public static class DictionaryExtensions
4 | {
5 | ///
6 | /// Gets the value at the given key, or a default value.
7 | ///
8 | public static TValue? GetValueOrDefault(this IDictionary dictionary, TKey key)
9 | {
10 | return dictionary.TryGetValue(key, out TValue? value) ? value : default;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/DictionaryWithSpecialEnumValueConverter.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using Newtonsoft.Json;
3 |
4 | namespace NotepadBasedCalculator.Api
5 | {
6 | public class DictionaryWithSpecialEnumValueConverter : JsonConverter where T : struct, Enum
7 | {
8 | public override bool CanWrite => false;
9 |
10 | public override bool CanConvert(Type objectType)
11 | {
12 | return true;
13 | }
14 |
15 | public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
16 | {
17 | if (reader.TokenType == JsonToken.Null)
18 | {
19 | return null;
20 | }
21 |
22 | Type valueType = objectType.GetGenericArguments()[1];
23 | Type intermediateDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeof(string), valueType);
24 |
25 | var intermediateDictionary = Activator.CreateInstance(intermediateDictionaryType) as IDictionary;
26 | var finalDictionary = Activator.CreateInstance(objectType) as IDictionary;
27 |
28 | if (intermediateDictionary is not null && finalDictionary is not null)
29 | {
30 | serializer.Populate(reader, intermediateDictionary);
31 | foreach (DictionaryEntry pair in intermediateDictionary)
32 | {
33 | string? key = pair.Key.ToString();
34 | string? value = pair.Value?.ToString();
35 | if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
36 | {
37 | finalDictionary.Add(key, value!.ToEnum());
38 | }
39 | }
40 | }
41 |
42 | return finalDictionary;
43 | }
44 |
45 | public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
46 | {
47 | throw new NotSupportedException();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/EnumExtension.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.Serialization;
3 |
4 | namespace NotepadBasedCalculator.Api
5 | {
6 | ///
7 | /// Provides a set of extension for enumerations
8 | ///
9 | internal static class EnumExtension
10 | {
11 | ///
12 | /// Retrieves the 's value.
13 | ///
14 | /// The targeted enumeration
15 | /// The value
16 | /// A string that corresponds to the description of the enumeration.
17 | internal static string GetDescription(this T enumerationValue) where T : struct, Enum
18 | {
19 | Guard.IsNotNull(enumerationValue!);
20 |
21 | MemberInfo[]? memberInfo = enumerationValue.GetType().GetMember(enumerationValue.ToString()!);
22 |
23 | if (memberInfo is not null && memberInfo.Length > 0)
24 | {
25 | object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false).ToArray();
26 |
27 | if (attrs is not null && attrs.Length > 0)
28 | {
29 | return ((DescriptionAttribute)attrs[0]).Description;
30 | }
31 | }
32 |
33 | return enumerationValue.ToString()!;
34 | }
35 |
36 | ///
37 | /// Converts the given text into an enum.
38 | ///
39 | internal static T ToEnum(this string input) where T : struct, Enum
40 | {
41 | Type enumType = typeof(T);
42 |
43 | if (Enum.TryParse(input, out T result))
44 | {
45 | return result;
46 | }
47 |
48 | foreach (string name in Enum.GetNames(enumType))
49 | {
50 | var fieldInfo = enumType.GetField(name)?.GetCustomAttributes(typeof(EnumMemberAttribute), true) as EnumMemberAttribute[];
51 | if (fieldInfo is not null && fieldInfo.Length == 1)
52 | {
53 | if (fieldInfo[0].Value == input)
54 | {
55 | return (T)Enum.Parse(enumType, name);
56 | }
57 | }
58 | }
59 |
60 | return default;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/Threading/AsyncLazy.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public sealed class AsyncLazy
4 | {
5 | private readonly Lazy> _innerLazy;
6 |
7 | public bool IsValueCreated => _innerLazy.IsValueCreated && _innerLazy.Value.IsCompleted && !_innerLazy.Value.IsFaulted;
8 |
9 | public AsyncLazy(Func> valueFactory)
10 | {
11 | _innerLazy = new Lazy>(valueFactory);
12 | }
13 |
14 | public AsyncLazy(Func> valueFactory, bool isThreadSafe)
15 | {
16 | _innerLazy = new Lazy>(valueFactory, isThreadSafe);
17 | }
18 |
19 | public AsyncLazy(Func> valueFactory, LazyThreadSafetyMode mode)
20 | {
21 | _innerLazy = new Lazy>(valueFactory, mode);
22 | }
23 |
24 | public Task GetValueAsync()
25 | {
26 | return IsValueCreated ? Task.FromResult(_innerLazy.Value.Result) : _innerLazy.Value;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/dev/NotepadBasedCalculator.Api/Core/Threading/CancellationTokenExtension.cs:
--------------------------------------------------------------------------------
1 | namespace NotepadBasedCalculator.Api
2 | {
3 | public static class CancellationTokenExtension
4 | {
5 | ///
6 | /// Converts the to a
7 | /// that canceled when the is being canceled.
8 | ///
9 | public static Task AsTask(this CancellationToken cancellationToken)
10 | {
11 | var tcs = new TaskCompletionSource