From 3c059c4e419e0112d52a36beae52f5e74b6cb112 Mon Sep 17 00:00:00 2001 From: KTSnowy Date: Thu, 8 Feb 2024 18:12:52 -0300 Subject: [PATCH] [Update]: Archive COBOL compiler code (see ARCHIVE branch) --- .github/workflows/codeql.yml | 77 - .github/workflows/compile-native.yml | 80 - .gitignore | 10 - LICENSE | 2 +- Libraries/Otterkit.Extensions/Extensions.cs | 6 - .../Otterkit.Extensions.csproj | 9 - Libraries/Otterkit.Extensions/comp3.gnomes | 36 - .../Otterkit.Extensions/extensiontest.json | 57 - Libraries/Otterkit.Native/src/Allocator.cs | 21 - .../src/Otterkit.Native.csproj | 47 - Libraries/Otterkit.Native/src/Ref.cs | 36 - Libraries/Otterkit.Native/src/u8Color.cs | 47 - Libraries/Otterkit.Native/src/u8Console.cs | 73 - Libraries/Otterkit.Native/src/u8Span.cs | 55 - .../Otterkit.Templates.csproj | 43 - .../.template.config/template.json | 16 - .../templates/Application/package.otterproj | 16 - .../Library/.template.config/template.json | 16 - .../templates/Library/package.otterproj | 16 - NOTICE | 4 +- Otterkit.Analyzers/Otterkit.Analyzers.csproj | 42 - Otterkit.Analyzers/README.md | 5 - Otterkit.Analyzers/src/Analyzer.cs | 100 - Otterkit.Analyzers/src/Common.cs | 1931 --------- Otterkit.Analyzers/src/DataClauses.cs | 1678 -------- Otterkit.Analyzers/src/DataDivision.cs | 1103 ------ Otterkit.Analyzers/src/EnvironmentClauses.cs | 718 ---- Otterkit.Analyzers/src/EnvironmentDivision.cs | 686 ---- Otterkit.Analyzers/src/Expressions.cs | 255 -- Otterkit.Analyzers/src/ExtensionMethods.cs | 87 - .../src/IdentificationDivision.cs | 829 ---- Otterkit.Analyzers/src/Literals.cs | 162 - Otterkit.Analyzers/src/PictureString.cs | 221 -- Otterkit.Analyzers/src/ProcedureDivision.cs | 720 ---- Otterkit.Analyzers/src/References.cs | 856 ---- Otterkit.Analyzers/src/Statements.cs | 3514 ----------------- .../Otterkit.CodeGenerators.csproj | 43 - Otterkit.CodeGenerators/README.md | 5 - .../src/Builders/ProgramBuilder.cs | 62 - .../src/Builders/StatementBuilder.cs | 252 -- .../src/Builders/VariableBuilder.cs | 297 -- Otterkit.CodeGenerators/src/CodeGenerator.cs | 84 - .../Otterkit.Tokenizers.csproj | 43 - Otterkit.Tokenizers/README.md | 5 - Otterkit.Tokenizers/src/Tokenizer.Lexer.cs | 157 - .../src/Tokenizer.Pipelines.cs | 147 - .../src/Tokenizer.Preprocessor.cs | 220 -- Otterkit.Tokenizers/src/Tokenizer.cs | 51 - Otterkit.Types/Otterkit.Types.csproj | 39 - Otterkit.Types/README.md | 5 - Otterkit.Types/src/Compact.cs | 43 - Otterkit.Types/src/CompilerContext.cs | 65 - Otterkit.Types/src/CompilerEnums.cs | 30 - Otterkit.Types/src/CompilerOptions.cs | 24 - .../DirectiveToken/DirectiveToken.Methods.cs | 19 - .../src/DirectiveToken/DirectiveToken.cs | 13 - .../src/DirectiveToken/DirectiveType.cs | 7 - .../src/EntryTypes/AbstractEntry.cs | 36 - Otterkit.Types/src/EntryTypes/DataEntry.cs | 199 - .../src/EntryTypes/FileControlEntry.cs | 11 - .../src/EntryTypes/RepositoryEntry.cs | 18 - Otterkit.Types/src/Enums/Categories.cs | 21 - Otterkit.Types/src/Enums/Classes.cs | 16 - Otterkit.Types/src/Enums/DataClause.cs | 70 - Otterkit.Types/src/Enums/EntryKind.cs | 12 - Otterkit.Types/src/Enums/EvaluateOperand.cs | 14 - Otterkit.Types/src/Enums/Identifiers.cs | 21 - Otterkit.Types/src/Enums/Names.cs | 38 - Otterkit.Types/src/Enums/RepositoryClause.cs | 9 - Otterkit.Types/src/Enums/SourceScope.cs | 23 - Otterkit.Types/src/Enums/UnitKind.cs | 18 - Otterkit.Types/src/Enums/Usages.cs | 31 - .../src/ErrorHandler/ErrorHandler.Helpers.cs | 87 - .../src/ErrorHandler/ErrorHandler.Methods.cs | 175 - .../src/ErrorHandler/ErrorHandler.cs | 18 - Otterkit.Types/src/ErrorHandler/ErrorType.cs | 10 - Otterkit.Types/src/ExtensionMethods.cs | 34 - Otterkit.Types/src/Name.cs | 115 - Otterkit.Types/src/NameTables/DataNames.cs | 72 - Otterkit.Types/src/NameTables/GlobalNames.cs | 66 - Otterkit.Types/src/NameTables/LocalNames.cs | 32 - Otterkit.Types/src/Optimization.cs | 40 - Otterkit.Types/src/Option.cs | 103 - Otterkit.Types/src/Token/Token.Lookup.cs | 748 ---- Otterkit.Types/src/Token/Token.Methods.cs | 356 -- Otterkit.Types/src/Token/Token.cs | 26 - Otterkit.Types/src/Token/TokenContext.cs | 12 - Otterkit.Types/src/Token/TokenScope.cs | 16 - Otterkit.Types/src/Token/TokenType.cs | 24 - Otterkit.Types/src/TokenHandling.cs | 222 -- Otterkit.Types/src/UnitTypes/AbstractUnit.cs | 14 - Otterkit.Types/src/UnitTypes/CallableUnit.cs | 18 - Otterkit.Types/src/UnitTypes/ClassUnit.cs | 17 - Otterkit.Types/src/UnitTypes/InterfaceUnit.cs | 14 - Otterkit.Types/src/UnitTypes/IntrinsicUnit.cs | 18 - .../Otterkit.Workspaces.csproj | 43 - Otterkit.Workspaces/README.md | 4 - Otterkit.Workspaces/src/Build.Properties.cs | 20 - .../src/Otterproj.Properties.cs | 20 - Otterkit.Workspaces/src/Project.Properties.cs | 19 - Otterkit.Workspaces/src/ProjectJsonContext.cs | 12 - Otterkit.Workspaces/src/ProjectLoader.cs | 79 - README.md | 109 +- SECURITY.md | 6 +- src/IR-design.md | 120 - src/Otterkit.cs | 430 -- src/Otterkit.csproj | 55 - src/Tools/GenerateExceptionIndex.cs | 196 - src/Tools/GenerateSwitchLookup.cs | 48 - src/Tools/GenerateUnicodeTable.cs | 229 -- src/Tools/TestCaseFolding.cs | 54 - src/parsinginfo.json | 662 ---- src/schema.json | 64 - 113 files changed, 8 insertions(+), 20121 deletions(-) delete mode 100644 .github/workflows/codeql.yml delete mode 100644 .github/workflows/compile-native.yml delete mode 100644 Libraries/Otterkit.Extensions/Extensions.cs delete mode 100644 Libraries/Otterkit.Extensions/Otterkit.Extensions.csproj delete mode 100644 Libraries/Otterkit.Extensions/comp3.gnomes delete mode 100644 Libraries/Otterkit.Extensions/extensiontest.json delete mode 100644 Libraries/Otterkit.Native/src/Allocator.cs delete mode 100644 Libraries/Otterkit.Native/src/Otterkit.Native.csproj delete mode 100644 Libraries/Otterkit.Native/src/Ref.cs delete mode 100644 Libraries/Otterkit.Native/src/u8Color.cs delete mode 100644 Libraries/Otterkit.Native/src/u8Console.cs delete mode 100644 Libraries/Otterkit.Native/src/u8Span.cs delete mode 100644 Libraries/Otterkit.Templates/Otterkit.Templates.csproj delete mode 100644 Libraries/Otterkit.Templates/templates/Application/.template.config/template.json delete mode 100644 Libraries/Otterkit.Templates/templates/Application/package.otterproj delete mode 100644 Libraries/Otterkit.Templates/templates/Library/.template.config/template.json delete mode 100644 Libraries/Otterkit.Templates/templates/Library/package.otterproj delete mode 100644 Otterkit.Analyzers/Otterkit.Analyzers.csproj delete mode 100644 Otterkit.Analyzers/README.md delete mode 100644 Otterkit.Analyzers/src/Analyzer.cs delete mode 100644 Otterkit.Analyzers/src/Common.cs delete mode 100644 Otterkit.Analyzers/src/DataClauses.cs delete mode 100644 Otterkit.Analyzers/src/DataDivision.cs delete mode 100644 Otterkit.Analyzers/src/EnvironmentClauses.cs delete mode 100644 Otterkit.Analyzers/src/EnvironmentDivision.cs delete mode 100644 Otterkit.Analyzers/src/Expressions.cs delete mode 100644 Otterkit.Analyzers/src/ExtensionMethods.cs delete mode 100644 Otterkit.Analyzers/src/IdentificationDivision.cs delete mode 100644 Otterkit.Analyzers/src/Literals.cs delete mode 100644 Otterkit.Analyzers/src/PictureString.cs delete mode 100644 Otterkit.Analyzers/src/ProcedureDivision.cs delete mode 100644 Otterkit.Analyzers/src/References.cs delete mode 100644 Otterkit.Analyzers/src/Statements.cs delete mode 100644 Otterkit.CodeGenerators/Otterkit.CodeGenerators.csproj delete mode 100644 Otterkit.CodeGenerators/README.md delete mode 100644 Otterkit.CodeGenerators/src/Builders/ProgramBuilder.cs delete mode 100644 Otterkit.CodeGenerators/src/Builders/StatementBuilder.cs delete mode 100644 Otterkit.CodeGenerators/src/Builders/VariableBuilder.cs delete mode 100644 Otterkit.CodeGenerators/src/CodeGenerator.cs delete mode 100644 Otterkit.Tokenizers/Otterkit.Tokenizers.csproj delete mode 100644 Otterkit.Tokenizers/README.md delete mode 100644 Otterkit.Tokenizers/src/Tokenizer.Lexer.cs delete mode 100644 Otterkit.Tokenizers/src/Tokenizer.Pipelines.cs delete mode 100644 Otterkit.Tokenizers/src/Tokenizer.Preprocessor.cs delete mode 100644 Otterkit.Tokenizers/src/Tokenizer.cs delete mode 100644 Otterkit.Types/Otterkit.Types.csproj delete mode 100644 Otterkit.Types/README.md delete mode 100644 Otterkit.Types/src/Compact.cs delete mode 100644 Otterkit.Types/src/CompilerContext.cs delete mode 100644 Otterkit.Types/src/CompilerEnums.cs delete mode 100644 Otterkit.Types/src/CompilerOptions.cs delete mode 100644 Otterkit.Types/src/DirectiveToken/DirectiveToken.Methods.cs delete mode 100644 Otterkit.Types/src/DirectiveToken/DirectiveToken.cs delete mode 100644 Otterkit.Types/src/DirectiveToken/DirectiveType.cs delete mode 100644 Otterkit.Types/src/EntryTypes/AbstractEntry.cs delete mode 100644 Otterkit.Types/src/EntryTypes/DataEntry.cs delete mode 100644 Otterkit.Types/src/EntryTypes/FileControlEntry.cs delete mode 100644 Otterkit.Types/src/EntryTypes/RepositoryEntry.cs delete mode 100644 Otterkit.Types/src/Enums/Categories.cs delete mode 100644 Otterkit.Types/src/Enums/Classes.cs delete mode 100644 Otterkit.Types/src/Enums/DataClause.cs delete mode 100644 Otterkit.Types/src/Enums/EntryKind.cs delete mode 100644 Otterkit.Types/src/Enums/EvaluateOperand.cs delete mode 100644 Otterkit.Types/src/Enums/Identifiers.cs delete mode 100644 Otterkit.Types/src/Enums/Names.cs delete mode 100644 Otterkit.Types/src/Enums/RepositoryClause.cs delete mode 100644 Otterkit.Types/src/Enums/SourceScope.cs delete mode 100644 Otterkit.Types/src/Enums/UnitKind.cs delete mode 100644 Otterkit.Types/src/Enums/Usages.cs delete mode 100644 Otterkit.Types/src/ErrorHandler/ErrorHandler.Helpers.cs delete mode 100644 Otterkit.Types/src/ErrorHandler/ErrorHandler.Methods.cs delete mode 100644 Otterkit.Types/src/ErrorHandler/ErrorHandler.cs delete mode 100644 Otterkit.Types/src/ErrorHandler/ErrorType.cs delete mode 100644 Otterkit.Types/src/ExtensionMethods.cs delete mode 100644 Otterkit.Types/src/Name.cs delete mode 100644 Otterkit.Types/src/NameTables/DataNames.cs delete mode 100644 Otterkit.Types/src/NameTables/GlobalNames.cs delete mode 100644 Otterkit.Types/src/NameTables/LocalNames.cs delete mode 100644 Otterkit.Types/src/Optimization.cs delete mode 100644 Otterkit.Types/src/Option.cs delete mode 100644 Otterkit.Types/src/Token/Token.Lookup.cs delete mode 100644 Otterkit.Types/src/Token/Token.Methods.cs delete mode 100644 Otterkit.Types/src/Token/Token.cs delete mode 100644 Otterkit.Types/src/Token/TokenContext.cs delete mode 100644 Otterkit.Types/src/Token/TokenScope.cs delete mode 100644 Otterkit.Types/src/Token/TokenType.cs delete mode 100644 Otterkit.Types/src/TokenHandling.cs delete mode 100644 Otterkit.Types/src/UnitTypes/AbstractUnit.cs delete mode 100644 Otterkit.Types/src/UnitTypes/CallableUnit.cs delete mode 100644 Otterkit.Types/src/UnitTypes/ClassUnit.cs delete mode 100644 Otterkit.Types/src/UnitTypes/InterfaceUnit.cs delete mode 100644 Otterkit.Types/src/UnitTypes/IntrinsicUnit.cs delete mode 100644 Otterkit.Workspaces/Otterkit.Workspaces.csproj delete mode 100644 Otterkit.Workspaces/README.md delete mode 100644 Otterkit.Workspaces/src/Build.Properties.cs delete mode 100644 Otterkit.Workspaces/src/Otterproj.Properties.cs delete mode 100644 Otterkit.Workspaces/src/Project.Properties.cs delete mode 100644 Otterkit.Workspaces/src/ProjectJsonContext.cs delete mode 100644 Otterkit.Workspaces/src/ProjectLoader.cs delete mode 100644 src/IR-design.md delete mode 100644 src/Otterkit.cs delete mode 100644 src/Otterkit.csproj delete mode 100644 src/Tools/GenerateExceptionIndex.cs delete mode 100644 src/Tools/GenerateSwitchLookup.cs delete mode 100644 src/Tools/GenerateUnicodeTable.cs delete mode 100644 src/Tools/TestCaseFolding.cs delete mode 100644 src/parsinginfo.json delete mode 100644 src/schema.json diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index fef88649..00000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,77 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ "main" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "main" ] - schedule: - - cron: '0 0 * * MON' - workflow_dispatch: - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'csharp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Use only 'java' to analyze code written in Java, Kotlin or both - # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" diff --git a/.github/workflows/compile-native.yml b/.github/workflows/compile-native.yml deleted file mode 100644 index 83dfe726..00000000 --- a/.github/workflows/compile-native.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Compile Native Bindings - -on: workflow_dispatch - -jobs: - compile-linux-x64: - runs-on: ubuntu-latest - env: - COMMIT_MESSAGE: Automated Linux-x64 Build Files - COMMIT_AUTHOR: Continuous Integration - steps: - - uses: actions/checkout@v3 - with: - token: ${{ secrets.OTTERKIT_GITHUB_TOKEN }} - - - name: Compile Native Bindings - run: | - cd Libraries/Otterkit.Native/nativelib - - clang -shared -Wl,-rpath -fPIC -O3 -Wall -W -o ../build/nativelib.so allocator.c u8console.c decimals.c ../decNumber/decContext.c ../decNumber/decDouble.c ../decNumber/decQuad.c ../decNumber/decNumber.c ../decNumber/decimal128.c ../decNumber/decimal64.c - - - name: GIT Commit Build Files - run: | - git config --global user.name "${{ env.COMMIT_AUTHOR }}" - git config --global user.email "KTSnowy@users.noreply.github.com" - git pull - git add --all - git commit -m "${{ env.COMMIT_MESSAGE }}" - git push - - compile-macos-x64: - runs-on: macos-latest - env: - COMMIT_MESSAGE: Automated macOS-x64 Build Files - COMMIT_AUTHOR: Continuous Integration - steps: - - uses: actions/checkout@v3 - with: - token: ${{ secrets.OTTERKIT_GITHUB_TOKEN }} - - - name: Compile Native Bindings - run: | - cd Libraries/Otterkit.Native/nativelib - - clang -dynamiclib -O3 -Wall -W -o ../build/nativelib.dylib allocator.c u8console.c decimals.c ../decNumber/decContext.c ../decNumber/decDouble.c ../decNumber/decQuad.c ../decNumber/decNumber.c ../decNumber/decimal128.c ../decNumber/decimal64.c - - - name: GIT Commit Build Files - run: | - git config --global user.name "${{ env.COMMIT_AUTHOR }}" - git config --global user.email "KTSnowy@users.noreply.github.com" - git pull - git add --all - git commit -m "${{ env.COMMIT_MESSAGE }}" - git push - - compile-windows-x64: - runs-on: windows-latest - env: - COMMIT_MESSAGE: Automated Windows-x64 Build Files - COMMIT_AUTHOR: Continuous Integration - steps: - - uses: actions/checkout@v3 - with: - token: ${{ secrets.OTTERKIT_GITHUB_TOKEN }} - - - name: Compile Native Bindings - shell: cmd - run: | - cd Libraries\Otterkit.Native\nativelib - "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - - cl.exe /O2 /LD /Fe:..\build\nativelib.dll allocator.c u8console.c decimals.c ..\decNumber\decContext.c ..\decNumber\decDouble.c ..\decNumber\decQuad.c ..\decNumber\decNumber.c ..\decNumber\decimal128.c ..\decNumber\decimal64.c - - - name: GIT Commit Build Files - run: | - git config --global user.name "${{ env.COMMIT_AUTHOR }}" - git config --global user.email "KTSnowy@users.noreply.github.com" - git add --all - git commit -m "${{ env.COMMIT_MESSAGE }}" - git push diff --git a/.gitignore b/.gitignore index 45120403..8681a231 100644 --- a/.gitignore +++ b/.gitignore @@ -3,16 +3,6 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore -# Otterkit compiler files -.otterkit/ -nupkg/ -publish/ - -# COBOL source files -*.cob -*.cbl -*.cpy - # Build files nativeBindings/*.dylib nativeBindings/*.dll diff --git a/LICENSE b/LICENSE index fa83e8e5..ee0b97eb 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2022 Gabriel Gonçalves + Copyright 2024 Gabriel Gonçalves Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Libraries/Otterkit.Extensions/Extensions.cs b/Libraries/Otterkit.Extensions/Extensions.cs deleted file mode 100644 index 8dd7c61d..00000000 --- a/Libraries/Otterkit.Extensions/Extensions.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Otterkit.Extensions; - -public static class Extensions -{ - -} diff --git a/Libraries/Otterkit.Extensions/Otterkit.Extensions.csproj b/Libraries/Otterkit.Extensions/Otterkit.Extensions.csproj deleted file mode 100644 index cfadb03d..00000000 --- a/Libraries/Otterkit.Extensions/Otterkit.Extensions.csproj +++ /dev/null @@ -1,9 +0,0 @@ - - - - net7.0 - enable - enable - - - diff --git a/Libraries/Otterkit.Extensions/comp3.gnomes b/Libraries/Otterkit.Extensions/comp3.gnomes deleted file mode 100644 index 48edf564..00000000 --- a/Libraries/Otterkit.Extensions/comp3.gnomes +++ /dev/null @@ -1,36 +0,0 @@ -EXTENSION-GNOMES SECTION. - - COMP3-PARSING. - USE ON USAGE-CLAUSE DURING PARSING - - IF VALUE EQUALS COMP-3 - REPLACE [WITH] PACKED-DECIMAL - CONTINUE - END-IF - - COMP6-PARSING. - USE [ON] USAGE-CLAUSE [DURING] PARSING - - IF CURRENT [VALUE] EQUALS COMP-6 [THEN] - REPLACE [BY] PACKED-DECIMAL - INSERT [TOKEN] NO - INSERT [TOKEN] SIGN - CONTINUE 3 - END-IF - - AUTHOR-PARSING. - USE [ON] IDENTIFICATION [DURING] PARSING - - IF CURRENT [VALUE] EQUALS AUTHOR [THEN] - CONTINUE - EXPECTED SEPARATOR-PERIOD - - REMOVE PREVIOUS 2 [TOKENS] - - IF CURRENT TYPE EQUALS IDENTIFIER [THEN] - CONTINUE - EXPECTED SEPARATOR-PERIOD - - REMOVE PREVIOUS 2 [TOKENS] - END-IF - END-IF diff --git a/Libraries/Otterkit.Extensions/extensiontest.json b/Libraries/Otterkit.Extensions/extensiontest.json deleted file mode 100644 index b789c462..00000000 --- a/Libraries/Otterkit.Extensions/extensiontest.json +++ /dev/null @@ -1,57 +0,0 @@ -[ - { - "name": "COMP3-PARSING", - "use": "USAGE-CLAUSE", - "during": "PARSING", - "steps": [ - "IF VALUE", - "COMP-3", - "REPLACE", - "PACKED-DECIMAL", - "CONTINUE", - "END-IF" - ] - }, - { - "name": "COMP6-PARSING", - "use": "USAGE-CLAUSE", - "during": "PARSING", - "steps": [ - "IF VALUE", - "COMP-6", - "REPLACE", - "PACKED-DECIMAL", - "INSERT", - "NO", - "INSERT", - "SIGN", - "CONTINUE", - "CONTINUE", - "CONTINUE", - "END-IF" - ] - }, - { - "name": "AUTHOR-PARSING", - "use": "IDENTIFICATION", - "during": "PARSING", - "steps": [ - "IF VALUE", - "AUTHOR", - "CONTINUE", - "EXPECTED", - "SEPARATOR-PERIOD", - "REMOVE PREVIOUS", - "REMOVE PREVIOUS", - "IF TYPE", - "IDENTIFIER", - "CONTINUE", - "EXPECTED", - "SEPARATOR-PERIOD", - "REMOVE PREVIOUS", - "REMOVE PREVIOUS", - "END-IF", - "END-IF" - ] - } -] diff --git a/Libraries/Otterkit.Native/src/Allocator.cs b/Libraries/Otterkit.Native/src/Allocator.cs deleted file mode 100644 index ee8b5536..00000000 --- a/Libraries/Otterkit.Native/src/Allocator.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Otterkit.Native; - -public static unsafe partial class Allocator -{ - public static int StackUsage => GetStackUsage(); - public static int StackFree => GetStackFree(); - - [LibraryImport("nativelib", EntryPoint = "GetStackUsage")] - private static partial int GetStackUsage(); - - [LibraryImport("nativelib", EntryPoint = "GetStackFree")] - private static partial int GetStackFree(); - - [LibraryImport("nativelib", EntryPoint = "Alloc")] - public static partial byte* Alloc(int length); - - [LibraryImport("nativelib", EntryPoint = "Dealloc")] - public static partial void Dealloc(byte* memory); -} diff --git a/Libraries/Otterkit.Native/src/Otterkit.Native.csproj b/Libraries/Otterkit.Native/src/Otterkit.Native.csproj deleted file mode 100644 index 0c79f6ef..00000000 --- a/Libraries/Otterkit.Native/src/Otterkit.Native.csproj +++ /dev/null @@ -1,47 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - - true - $(NoWarn);NU5100 - - - - true - Otterkit.Native - ./nupkg - Apache-2.0 - 1.7.80 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Native;Library - https://github.com/otterkit - https://github.com/otterkit/libotterkit - git - - This package contains native interop methods for Otterkit's runtime library. - - - - - - - - - - - PreserveNewest - true - - - - diff --git a/Libraries/Otterkit.Native/src/Ref.cs b/Libraries/Otterkit.Native/src/Ref.cs deleted file mode 100644 index d278980d..00000000 --- a/Libraries/Otterkit.Native/src/Ref.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Otterkit.Native; - -// This is essentially a managed pointer to a struct, so a reference to a struct. -// We can use this to avoid copying structs around, a nice performance boost. -public readonly unsafe ref struct Ref where T : unmanaged -{ - internal readonly ref T Reference; - - public readonly bool IsNull => Unsafe.IsNullRef(ref Reference); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ref() - { - Reference = ref Unsafe.NullRef(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ref(ref T reference) - { - Reference = ref reference; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Ref(T* pointer) - { - Reference = ref *(T*)pointer; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ref T Unwrap() => ref Reference; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T* AsPointer() => (T*)Unsafe.AsPointer(ref Reference); -} diff --git a/Libraries/Otterkit.Native/src/u8Color.cs b/Libraries/Otterkit.Native/src/u8Color.cs deleted file mode 100644 index b4091c5c..00000000 --- a/Libraries/Otterkit.Native/src/u8Color.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace Otterkit.Native; - -public static class u8Color -{ - public static ReadOnlySpan Black => "\x1B[30m"u8; - public static ReadOnlySpan Red => "\x1B[31m"u8; - public static ReadOnlySpan Green => "\x1B[32m"u8; - public static ReadOnlySpan Yellow => "\x1B[33m"u8; - public static ReadOnlySpan Blue => "\x1B[34m"u8; - public static ReadOnlySpan Magenta => "\x1B[35m"u8; - public static ReadOnlySpan Cyan => "\x1B[36m"u8; - public static ReadOnlySpan White => "\x1B[37m"u8; - - public static ReadOnlySpan BackgroundBlack => "\x1B[40m"u8; - public static ReadOnlySpan BackgroundRed => "\x1B[41m"u8; - public static ReadOnlySpan BackgroundGreen => "\x1B[42m"u8; - public static ReadOnlySpan BackgroundYellow => "\x1B[43m"u8; - public static ReadOnlySpan BackgroundBlue => "\x1B[44m"u8; - public static ReadOnlySpan BackgroundMagenta => "\x1B[45m"u8; - public static ReadOnlySpan BackgroundCyan => "\x1B[46m"u8; - public static ReadOnlySpan BackgroundWhite => "\x1B[47m"u8; - - public static ReadOnlySpan BrightBlack => "\x1B[90m"u8; - public static ReadOnlySpan BrightRed => "\x1B[91m"u8; - public static ReadOnlySpan BrightGreen => "\x1B[92m"u8; - public static ReadOnlySpan BrightYellow => "\x1B[93m"u8; - public static ReadOnlySpan BrightBlue => "\x1B[94m"u8; - public static ReadOnlySpan BrightMagenta => "\x1B[95m"u8; - public static ReadOnlySpan BrightCyan => "\x1B[96m"u8; - public static ReadOnlySpan BrightWhite => "\x1B[97m"u8; - - public static ReadOnlySpan BrightBackgroundBlack => "\x1B[100m"u8; - public static ReadOnlySpan BrightBackgroundRed => "\x1B[101m"u8; - public static ReadOnlySpan BrightBackgroundGreen => "\x1B[102m"u8; - public static ReadOnlySpan BrightBackgroundYellow => "\x1B[103m"u8; - public static ReadOnlySpan BrightBackgroundBlue => "\x1B[104m"u8; - public static ReadOnlySpan BrightBackgroundMagenta => "\x1B[105m"u8; - public static ReadOnlySpan BrightBackgroundCyan => "\x1B[106m"u8; - public static ReadOnlySpan BrightBackgroundWhite => "\x1B[107m"u8; - - public static ReadOnlySpan Bold => "\x1B[1m"u8; - public static ReadOnlySpan Dim => "\x1B[2m"u8; - public static ReadOnlySpan Underline => "\x1B[4m"u8; - public static ReadOnlySpan Blink => "\x1B[5m"u8; - public static ReadOnlySpan Reverse => "\x1B[7m"u8; - public static ReadOnlySpan Hide => "\x1B[8m"u8; -} diff --git a/Libraries/Otterkit.Native/src/u8Console.cs b/Libraries/Otterkit.Native/src/u8Console.cs deleted file mode 100644 index 1e084877..00000000 --- a/Libraries/Otterkit.Native/src/u8Console.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Otterkit.Native; - -public static unsafe partial class u8Console -{ - public static void WriteLine(ReadOnlySpan format, ReadOnlySpan utf8) - { - Span styled = stackalloc byte[format.Length + utf8.Length]; - - format.CopyTo(styled); - - utf8.CopyTo(styled.Slice(format.Length)); - - WriteLine(styled); - } - - public static void WriteLine(ReadOnlySpan utf8) - { - Span nullTerminated = stackalloc byte[utf8.Length + 1]; - - utf8.CopyTo(nullTerminated); - - nullTerminated[utf8.Length] = 0; - - fixed (byte* pointer = nullTerminated) - { - Writeln(pointer); - } - } - - public static void Write(ReadOnlySpan format, ReadOnlySpan utf8) - { - Span styled = stackalloc byte[format.Length + utf8.Length]; - - format.CopyTo(styled); - - utf8.CopyTo(styled.Slice(format.Length)); - - Write(styled); - } - - public static void Write(ReadOnlySpan utf8) - { - Span nullTerminated = stackalloc byte[utf8.Length + 1]; - - utf8.CopyTo(nullTerminated); - - nullTerminated[utf8.Length] = 0; - - fixed (byte* pointer = nullTerminated) - { - Write(pointer); - } - } - - public static void ReadLine(Span destination) - { - fixed (byte* pointer = destination) - { - Readln(pointer, 4096); - } - } - - [LibraryImport("nativelib", EntryPoint = "Write")] - private static partial void Write(byte* _string); - - [LibraryImport("nativelib", EntryPoint = "WriteLn")] - private static partial void Writeln(byte* _string); - - [LibraryImport("nativelib", EntryPoint = "ReadLn")] - private static partial void Readln(byte* buffer, int length); -} \ No newline at end of file diff --git a/Libraries/Otterkit.Native/src/u8Span.cs b/Libraries/Otterkit.Native/src/u8Span.cs deleted file mode 100644 index b6c44e0f..00000000 --- a/Libraries/Otterkit.Native/src/u8Span.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Runtime.CompilerServices; - -namespace Otterkit.Native; - -public unsafe struct u8Span : IDisposable -{ - private byte* Pointer; - private int Length { get; init; } - - public bool Allocated => Pointer is not null; - - public u8Span(int length) - { - Pointer = Allocator.Alloc(length); - Length = length; - } - - public Span Span - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(Pointer, Length); - } - - public ref byte this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref Span[index]; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span Slice(int start) => Span.Slice(start); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span Slice(int start, int length) => Span.Slice(start, length); - - public void CopyTo(Span destination) => Span.CopyTo(destination); - - public bool TryCopyTo(Span destination) => Span.TryCopyTo(destination); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte* AsPointer() => Pointer; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Span(u8Span span) => span.Span; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator byte*(u8Span span) => span.Pointer; - - public void Dispose() - { - Allocator.Dealloc(Pointer); - - Pointer = null; - } -} diff --git a/Libraries/Otterkit.Templates/Otterkit.Templates.csproj b/Libraries/Otterkit.Templates/Otterkit.Templates.csproj deleted file mode 100644 index 7ea062d2..00000000 --- a/Libraries/Otterkit.Templates/Otterkit.Templates.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - net7.0 - Template - Otterkit.Templates - Otterkit COBOL Templates - true - false - content - true - $(NoWarn);NU5128;NU5100 - - - - ./nupkg - Apache-2.0 - 1.7.50 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Project;Templates - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains the templates needed to generate new Otterkit COBOL projects. - - - - - - - - - - - - - - diff --git a/Libraries/Otterkit.Templates/templates/Application/.template.config/template.json b/Libraries/Otterkit.Templates/templates/Application/.template.config/template.json deleted file mode 100644 index 6e2188aa..00000000 --- a/Libraries/Otterkit.Templates/templates/Application/.template.config/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/template", - "author": "KTSnowy ", - "classifications": ["COBOL", "Application"], - "identity": "OtterkitApplication", - "name": "Otterkit COBOL Application", - "description": "Used by the Otterkit COBOL compiler to generate a new COBOL application", - "shortName": "otterkit-app", - "defaultName": "OtterkitApplication", - "preferNameDirectory": false, - "thirdPartyNotices": "https://github.com/otterkit/otterkit/", - "tags": { - "language": "C#", - "type": "project" - } -} \ No newline at end of file diff --git a/Libraries/Otterkit.Templates/templates/Application/package.otterproj b/Libraries/Otterkit.Templates/templates/Application/package.otterproj deleted file mode 100644 index ec85b225..00000000 --- a/Libraries/Otterkit.Templates/templates/Application/package.otterproj +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "MyProject", - - "project": { - "sdk": "Microsoft.NET.Sdk", - "target": "net7.0", - "standard": "2023" - }, - - "build": { - "main": "main.cob", - "output": "Application", - "format": "Auto", - "columns": 80 - } -} diff --git a/Libraries/Otterkit.Templates/templates/Library/.template.config/template.json b/Libraries/Otterkit.Templates/templates/Library/.template.config/template.json deleted file mode 100644 index c6d7b672..00000000 --- a/Libraries/Otterkit.Templates/templates/Library/.template.config/template.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/template", - "author": "KTSnowy ", - "classifications": ["COBOL", "Library"], - "identity": "OtterkitLibrary", - "name": "Otterkit COBOL Library", - "description": "Used by the Otterkit COBOL compiler to generate a new COBOL library", - "shortName": "otterkit-lib", - "defaultName": "OtterkitLibrary", - "preferNameDirectory": false, - "thirdPartyNotices": "https://github.com/otterkit/otterkit/", - "tags": { - "language": "C#", - "type": "project" - } -} \ No newline at end of file diff --git a/Libraries/Otterkit.Templates/templates/Library/package.otterproj b/Libraries/Otterkit.Templates/templates/Library/package.otterproj deleted file mode 100644 index 116d3b01..00000000 --- a/Libraries/Otterkit.Templates/templates/Library/package.otterproj +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "MyProject", - - "project": { - "sdk": "Microsoft.NET.Sdk", - "target": "net7.0", - "standard": "2023" - }, - - "build": { - "main": "main.cob", - "output": "Library", - "format": "Auto", - "columns": 80 - } -} diff --git a/NOTICE b/NOTICE index 95ae38de..6372ba7f 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ -Otterkit Standard COBOL compiler -Copyright © 2023 Gabriel Gonçalves . +Otterkit Toolchain +Copyright © 2024 Gabriel Gonçalves . This repo includes the following third-party software: diff --git a/Otterkit.Analyzers/Otterkit.Analyzers.csproj b/Otterkit.Analyzers/Otterkit.Analyzers.csproj deleted file mode 100644 index 3490127a..00000000 --- a/Otterkit.Analyzers/Otterkit.Analyzers.csproj +++ /dev/null @@ -1,42 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - - - - - true - Otterkit.Analyzers - ./nupkg - Apache-2.0 - 1.0.70 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Compiler;Analyzers - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains the Standard COBOL analyzer for the Otterkit compiler. - - - - - - - - - - - - - diff --git a/Otterkit.Analyzers/README.md b/Otterkit.Analyzers/README.md deleted file mode 100644 index 128cd24f..00000000 --- a/Otterkit.Analyzers/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Otterkit.Analyzers namespace - -This namespace contains the Standard COBOL analyzer -for the Otterkit compiler. - diff --git a/Otterkit.Analyzers/src/Analyzer.cs b/Otterkit.Analyzers/src/Analyzer.cs deleted file mode 100644 index 36623457..00000000 --- a/Otterkit.Analyzers/src/Analyzer.cs +++ /dev/null @@ -1,100 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -/// -/// Otterkit COBOL Syntax and Semantic Analyzer -/// This analyzer was built to be easily extensible, with some reusable COBOL parts. -/// It requires a list of tokens generated from the Lexer and the Token Classifier. -/// -public static class Analyzer -{ - public static List Analyze(List tokenList) - { - // Call the analyzer's main recursive method - // This should only return when the analyzer reaches the true EOF token - Source(); - - // Reset token index and setup resolution pass - SetupResolutionPass(); - - // Call the analyzer's main recursive method again - // But this time with name resolution enabled - Source(); - - // If a parsing error has occured, terminate the compilation process. - // We do not want the compiler to continue when the source code is not valid. - if (ErrorHandler.HasOccurred) ErrorHandler.StopCompilation("an analyzer"); - - // Return parsed list of tokens. - return tokenList; - } - - // Source() is the main method of the analyzer. - // It's responsible for parsing COBOL divisions until the EOF token. - // If EOF was not returned as the last Token in the list then, - // the analyzer has not finished reading through the list of tokens correctly. - private static void Source() - { - IdentificationDivision.Parse(); - - var sourceTypes = CompilerContext.SourceTypes; - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - var isClassOrInterface = sourceTypes.Peek() switch - { - UnitKind.Class => true, - UnitKind.Interface => true, - _ => false - }; - - if (!isClassOrInterface && CurrentEquals("PROCEDURE")) - { - ProcedureDivision.ParseProcedural(); - } - else if (sourceTypes.Peek() == UnitKind.Class) - { - ProcedureDivision.ParseObjects(); - } - else if (sourceTypes.Peek() == UnitKind.Interface) - { - ProcedureDivision.ParseInterface(); - } - - ProcedureDivision.EndMarker(); - - if (CurrentEquals("IDENTIFICATION PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID")) - { - Source(); - } - - if (CurrentEquals("EOF") && TokenHandling.Index < CompilerContext.SourceTokens.Count - 1) - { - Continue(); - Source(); - } - } - - private static void SetupResolutionPass() - { - // Set the index back to 0 to restart the analyzer - TokenHandling.Index = 0; - - // Enable name resolution checks - CompilerContext.IsResolutionPass = true; - - // Suppress analyzer error messages to avoid duplicates - // Note: Resolution errors should use 'ErrorType.Resolution' - ErrorHandler.SuppressedError = ErrorType.Analyzer; - } -} diff --git a/Otterkit.Analyzers/src/Common.cs b/Otterkit.Analyzers/src/Common.cs deleted file mode 100644 index 841521f1..00000000 --- a/Otterkit.Analyzers/src/Common.cs +++ /dev/null @@ -1,1931 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public struct SetLcValues -{ - public bool LC_ALL; - public bool LC_COLLATE; - public bool LC_CTYPE; - public bool LC_MESSAGES; - public bool LC_MONETARY; - public bool LC_NUMERIC; - public bool LC_TIME; -} - -public static partial class Common -{ - // The following methods are responsible for parsing some commonly repeated pieces of COBOL statements. - // The ON SIZE ERROR, ON EXCEPTION, INVALID KEY, AT END, and the RETRY phrase are examples of pieces of COBOL syntax - // that appear on multiple statements. Reusing the same code in those cases keeps things much more modular and easier to maintain. - // - // The Arithmetic() and Condition() methods are responsible for parsing expressions and verifying if those expressions were - // written correctly. This is using a combination of the Shunting Yard algorithm, and some methods to verify if the - // parentheses are balanced and if it can be evaluated correctly. - - public static void AscendingDescendingKey() - { - while (CurrentEquals("ASCENDING DESCENDING")) - { - Choice("ASCENDING DESCENDING"); - Optional("KEY"); - Optional("IS"); - - References.Identifier(); - } - } - - public static void TimesPhrase() - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - - Expected("TIMES"); - } - - public static void UntilPhrase() - { - Expected("UNTIL"); - if (CurrentEquals("EXIT")) - { - Expected("EXIT"); - } - else - { - Condition(" "); - } - } - - public static void VaryingPhrase() - { - Expected("VARYING"); - References.Identifier(); - Expected("FROM"); - if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - References.Identifier(); - } - - if (CurrentEquals("BY")) - { - Expected("BY"); - if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - References.Identifier(); - } - } - - Expected("UNTIL"); - Condition("AFTER"); - - while (CurrentEquals("AFTER")) - { - Expected("AFTER"); - References.Identifier(); - Expected("FROM"); - if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - References.Identifier(); - } - - if (CurrentEquals("BY")) - { - Expected("BY"); - if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - References.Identifier(); - } - } - - Expected("UNTIL"); - Condition("AFTER"); - } - } - - public static void WithTest() - { - if (CurrentEquals("WITH TEST")) - { - Optional("WITH"); - Expected("TEST"); - Choice("BEFORE AFTER"); - } - } - - public static void RetryPhrase() - { - if (!CurrentEquals("RETRY")) return; - - var hasFor = false; - - Expected("RETRY"); - if (CurrentEquals("FOREVER")) - { - Expected("FOREVER"); - return; - } - - if (CurrentEquals("FOR")) - { - Optional("FOR"); - hasFor = true; - } - - Arithmetic("SECONDS TIMES"); - if (CurrentEquals("SECONDS") || hasFor) - { - Expected("SECONDS"); - } - else - { - Expected("TIMES"); - } - } - - public static void TallyingPhrase() - { - if (!CurrentEquals(TokenType.Identifier) && !PeekEquals(1, "FOR")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Tallying phrase, missing identifier. - """) - .WithSourceLine(Current(), """ - Tallying must start with an identifier, followed by the 'FOR' keyword. - """) - .CloseError(); - } - - while (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "FOR")) - { - References.Identifier(); - Expected("FOR"); - - if (!CurrentEquals("CHARACTERS ALL LEADING")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Tallying phrase, missing keyword. - """) - .WithSourceLine(Current(), """ - Missing phrase keyword. - """) - .WithNote(""" - Tallying must contain one of the following words: CHARACTERS, ALL or LEADING - """) - .CloseError(); - } - - while (CurrentEquals("CHARACTERS ALL LEADING")) - { - if (CurrentEquals("CHARACTERS")) - { - Expected("CHARACTERS"); - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - else if (CurrentEquals("ALL")) - { - Expected("ALL"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - } - else if (CurrentEquals("LEADING")) - { - Expected("LEADING"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - } - } - } - } - - public static void ReplacingPhrase() - { - if (!CurrentEquals("CHARACTERS ALL LEADING FIRST")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Replacing phrase, missing keyword. - """) - .WithSourceLine(Current(), """ - Missing phrase keyword. - """) - .WithNote(""" - Tallying must contain one of the following words: CHARACTERS, ALL, LEADING or FIRST. - """) - .CloseError(); - } - - while (CurrentEquals("CHARACTERS ALL LEADING FIRST")) - { - if (CurrentEquals("CHARACTERS")) - { - Expected("CHARACTERS"); - Expected("BY"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - else if (CurrentEquals("ALL")) - { - Expected("ALL"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - } - else if (CurrentEquals("LEADING")) - { - Expected("LEADING"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - } - else if (CurrentEquals("FIRST")) - { - Expected("FIRST"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("BY"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - - if (CurrentEquals("AFTER BEFORE")) - { - AfterBeforePhrase(); - } - } - } - } - } - - public static void AfterBeforePhrase(bool beforeExists = false, bool afterExists = false) - { - if (CurrentEquals("AFTER")) - { - if (afterExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - After phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - AFTER can only be specified once in this part of the statement. - """) - .WithNote(""" - The same applies to BEFORE. - """) - .CloseError(); - } - - afterExists = true; - Expected("AFTER"); - Optional("INITIAL"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - AfterBeforePhrase(beforeExists, afterExists); - - } - - if (CurrentEquals("BEFORE")) - { - if (beforeExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Before phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - BEFORE can only be specified once in this part of the statement. - """) - .WithNote(""" - The same applies to AFTER. - """) - .CloseError(); - } - - beforeExists = true; - Expected("BEFORE"); - Optional("INITIAL"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - AfterBeforePhrase(beforeExists, afterExists); - } - } - - public static void InvalidKey(ref bool isConditional, bool invalidKeyExists = false, bool notInvalidKeyExists = false) - { - if (CurrentEquals("INVALID")) - { - if (invalidKeyExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Invalid key phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - INVALID KEY can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT INVALID KEY. - """) - .CloseError(); - } - isConditional = true; - invalidKeyExists = true; - - Expected("INVALID"); - Optional("KEY"); - - Statements.WithoutSections(true); - - InvalidKey(ref isConditional, invalidKeyExists, notInvalidKeyExists); - } - - if (CurrentEquals("NOT")) - { - if (notInvalidKeyExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not invalid key phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT INVALID KEY can only be specified once in this statement. - """) - .WithNote(""" - The same applies to INVALID KEY. - """) - .CloseError(); - } - isConditional = true; - notInvalidKeyExists = true; - - Expected("NOT"); - Expected("INVALID"); - Optional("KEY"); - - Statements.WithoutSections(true); - - InvalidKey(ref isConditional, invalidKeyExists, notInvalidKeyExists); - } - } - - public static void OnException(ref bool isConditional, bool onExceptionExists = false, bool notOnExceptionExists = false) - { - if (CurrentEquals("ON") || CurrentEquals("EXCEPTION")) - { - if (onExceptionExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - On exception phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - ON EXCEPTION can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT ON EXCEPTION. - """) - .CloseError(); - } - isConditional = true; - onExceptionExists = true; - - Optional("ON"); - Expected("EXCEPTION"); - - Statements.WithoutSections(true); - - OnException(ref isConditional, onExceptionExists, notOnExceptionExists); - } - - if (CurrentEquals("NOT")) - { - if (notOnExceptionExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not on exception phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT ON EXCEPTION can only be specified once in this statement. - """) - .WithNote(""" - The same applies to ON EXCEPTION. - """) - .CloseError(); - } - isConditional = true; - notOnExceptionExists = true; - - Expected("NOT"); - Optional("ON"); - Expected("EXCEPTION"); - - Statements.WithoutSections(true); - - OnException(ref isConditional, onExceptionExists, notOnExceptionExists); - } - } - - public static void RaisingStatus(bool raisingExists = false, bool statusExists = false) - { - if (CurrentEquals("RAISING")) - { - if (raisingExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Raising phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - Raising can only be specified once in this statement. - """) - .WithNote(""" - The same applies to WITH ... ERROR STATUS. - """) - .CloseError(); - } - - Expected("RAISING"); - if (CurrentEquals("EXCEPTION")) - { - Expected("EXCEPTION"); - References.Identifier(); - } - else if (CurrentEquals("LAST")) - { - Expected("LAST"); - Optional("EXCEPTION"); - } - else - References.Identifier(); - - raisingExists = true; - RaisingStatus(raisingExists, statusExists); - - } - - if (CurrentEquals("WITH") || CurrentEquals("NORMAL") || CurrentEquals("ERROR")) - { - if (statusExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Error status phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - ERROR STATUS can only be specified once in this statement. - """) - .WithNote(""" - The same applies to RAISING. - """) - .CloseError(); - } - - Optional("WITH"); - Choice("NORMAL ERROR"); - Optional("STATUS"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - case TokenType.Numeric: - Literals.Numeric(); - break; - case TokenType.String: - Literals.String(); - break; - } - - statusExists = true; - RaisingStatus(raisingExists, statusExists); - } - } - - public static void AtEnd(ref bool isConditional, bool atEndExists = false, bool notAtEndExists = false) - { - if (CurrentEquals("AT") || CurrentEquals("END")) - { - if (atEndExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - At end phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - AT END can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT AT END. - """) - .CloseError(); - } - isConditional = true; - atEndExists = true; - - Optional("AT"); - Expected("END"); - - Statements.WithoutSections(true); - - AtEnd(ref isConditional, atEndExists, notAtEndExists); - } - - if (CurrentEquals("NOT")) - { - if (notAtEndExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not at end phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT AT END can only be specified once in this statement. - """) - .WithNote(""" - The same applies to AT END. - """) - .CloseError(); - } - isConditional = true; - notAtEndExists = true; - - Expected("NOT"); - Optional("AT"); - Expected("END"); - - Statements.WithoutSections(true); - - AtEnd(ref isConditional, atEndExists, notAtEndExists); - } - } - - public static void SizeError(ref bool isConditional, bool onErrorExists = false, bool notOnErrorExists = false) - { - if (CurrentEquals("ON") || CurrentEquals("SIZE")) - { - if (onErrorExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - On size error phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - ON SIZE ERROR can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT ON SIZE ERROR. - """) - .CloseError(); - } - isConditional = true; - onErrorExists = true; - - Optional("ON"); - Expected("SIZE"); - Expected("ERROR"); - - Statements.WithoutSections(true); - - SizeError(ref isConditional, onErrorExists, notOnErrorExists); - } - - if (CurrentEquals("NOT")) - { - if (notOnErrorExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not on size error phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT ON SIZE ERROR can only be specified once in this statement. - """) - .WithNote(""" - The same applies to ON SIZE ERROR. - """) - .CloseError(); - } - isConditional = true; - notOnErrorExists = true; - - Expected("NOT"); - Optional("ON"); - Expected("SIZE"); - Expected("ERROR"); - - Statements.WithoutSections(true); - - SizeError(ref isConditional, onErrorExists, notOnErrorExists); - } - } - - public static void OnOverflow(ref bool isConditional, bool onOverflowExists = false, bool notOnOverflowExists = false) - { - if (CurrentEquals("ON") || CurrentEquals("OVERFLOW")) - { - if (onOverflowExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - On overflow phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - ON OVERFLOW can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT ON OVERFLOW. - """) - .CloseError(); - } - isConditional = true; - onOverflowExists = true; - - Optional("ON"); - Expected("OVERFLOW"); - - Statements.WithoutSections(true); - - OnOverflow(ref isConditional, onOverflowExists, notOnOverflowExists); - } - - if (CurrentEquals("NOT")) - { - if (notOnOverflowExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not on overflow phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT ON OVERFLOW can only be specified once in this statement. - """) - .WithNote(""" - The same applies to ON OVERFLOW. - """) - .CloseError(); - } - isConditional = true; - notOnOverflowExists = true; - - Expected("NOT"); - Optional("ON"); - Expected("OVERFLOW"); - - Statements.WithoutSections(true); - - OnOverflow(ref isConditional, onOverflowExists, notOnOverflowExists); - } - } - - public static void WriteBeforeAfter(bool beforeExists = false, bool afterExists = false) - { - if (CurrentEquals("BEFORE")) - { - if (beforeExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Before phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - BEFORE can only be specified once in this statement. - """) - .WithNote(""" - The same applies to AFTER. - """) - .CloseError(); - } - beforeExists = true; - - Expected("BEFORE"); - - WriteBeforeAfter(beforeExists, afterExists); - } - - if (CurrentEquals("AFTER")) - { - if (afterExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - After phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - AFTER can only be specified once in this statement. - """) - .WithNote(""" - The same applies to BEFORE. - """) - .CloseError(); - } - afterExists = true; - - Expected("AFTER"); - - WriteBeforeAfter(beforeExists, afterExists); - } - } - - public static void SetLocale(SetLcValues locales = new()) - { - if (CurrentEquals("LC_ALL")) - { - if (locales.LC_ALL) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_ALL can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_ALL = true; - - Expected("LC_ALL"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_COLLATE")) - { - if (locales.LC_COLLATE) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_COLLATE can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_COLLATE = true; - - Expected("LC_COLLATE"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_CTYPE")) - { - if (locales.LC_CTYPE) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_CTYPE can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_CTYPE = true; - - Expected("LC_CTYPE"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_MESSAGES")) - { - if (locales.LC_MESSAGES) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_MESSAGES can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_MESSAGES = true; - - Expected("LC_MESSAGES"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_MONETARY")) - { - if (locales.LC_MONETARY) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_MONETARY can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_MONETARY = true; - - Expected("LC_MONETARY"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_NUMERIC")) - { - if (locales.LC_NUMERIC) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_NUMERIC can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_NUMERIC = true; - - Expected("LC_NUMERIC"); - - SetLocale(locales); - } - - if (CurrentEquals("LC_TIME")) - { - if (locales.LC_TIME) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132,""" - Locale phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LC_TIME can only be specified once in this statement. - """) - .WithNote(""" - The same applies to each of the other locale names. - """) - .CloseError(); - } - locales.LC_TIME = true; - - Expected("LC_TIME"); - - SetLocale(locales); - } - } - - public static void AtEndOfPage(ref bool isConditional, bool atEndOfPageExists = false, bool notAtEndOfPageExists = false) - { - if (CurrentEquals("AT END-OF-PAGE EOP")) - { - if (atEndOfPageExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - At end-of-page phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - AT END-OF-PAGE can only be specified once in this statement. - """) - .WithNote(""" - The same applies to NOT AT END-OF-PAGE. - """) - .CloseError(); - } - isConditional = true; - atEndOfPageExists = true; - - Optional("AT"); - Choice("END-OF-PAGE EOP"); - - Statements.WithoutSections(true); - - AtEndOfPage(ref isConditional, atEndOfPageExists, notAtEndOfPageExists); - } - - if (CurrentEquals("NOT")) - { - if (notAtEndOfPageExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Not at end-of-page phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - NOT AT END-OF-PAGE can only be specified once in this statement. - """) - .WithNote(""" - The same applies to AT END-OF-PAGE. - """) - .CloseError(); - } - isConditional = true; - notAtEndOfPageExists = true; - - Expected("NOT"); - Optional("AT"); - Choice("END-OF-PAGE EOP"); - - Statements.WithoutSections(true); - - AtEndOfPage(ref isConditional, atEndOfPageExists, notAtEndOfPageExists); - } - } - - public static void ForAlphanumericForNational(bool forAlphanumericExists = false, bool forNationalExists = false) - { - if (CurrentEquals("FOR") && PeekEquals(1, "ALPHANUMERIC") || CurrentEquals("ALPHANUMERIC")) - { - if (forAlphanumericExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - For alphanumeric phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - FOR ALPHANUMERIC can only be specified once in this statement. - """) - .WithNote(""" - The same applies to FOR NATIONAL. - """) - .CloseError(); - } - forAlphanumericExists = true; - - Optional("FOR"); - Expected("ALPHANUMERIC"); - Optional("IS"); - - References.Identifier(); - - ForAlphanumericForNational(forAlphanumericExists, forNationalExists); - } - - if (CurrentEquals("FOR") && PeekEquals(1, "NATIONAL") || CurrentEquals("NATIONAL")) - { - if (forNationalExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - For national phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - FOR NATIONAL can only be specified once in this statement. - """) - .WithNote(""" - The same applies to FOR ALPHANUMERIC. - """) - .CloseError(); - } - forNationalExists = true; - - Optional("FOR"); - Expected("NATIONAL"); - Optional("IS"); - - References.Identifier(); - - ForAlphanumericForNational(forAlphanumericExists, forNationalExists); - } - } - - public static void LineColumn(bool lineExists = false, bool columnExists = false) - { - if (CurrentEquals("LINE")) - { - if (lineExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Line number phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - LINE NUMBER can only be specified once in this statement. - """) - .WithNote(""" - The same applies to COLUMN NUMBER. - """) - .CloseError(); - } - lineExists = true; - - Expected("LINE"); - Optional("NUMBER"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - - LineColumn(lineExists, columnExists); - } - - if (CurrentEquals("COLUMN COL")) - { - if (columnExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Column number phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - COLUMN NUMBER can only be specified once in this statement. - """) - .WithNote(""" - The same applies to LINE NUMBER. - """) - .CloseError(); - } - columnExists = true; - - Expected(Current().Value); - Optional("NUMBER"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - - LineColumn(lineExists, columnExists); - } - } - - public static void RoundedPhrase() - { - Expected("ROUNDED"); - - if (CurrentEquals("MODE")) - { - Expected("MODE"); - Optional("IS"); - - Choice("AWAY-FROM-ZERO NEAREST-AWAY-FROM-ZERO NEAREST-EVEN NEAREST-TOWARD-ZERO PROHIBITED TOWARD-GREATER TOWARD-LESSER TRUNCATION"); - } - } - - public static void Arithmetic(TokenContext delimiter) - { - var expression = new List(); - - while (!CurrentEquals(TokenType.ReservedKeyword) && !CurrentEquals(delimiter) && !CurrentEquals(".")) - { - BuildArithmeticExpression(expression); - } - - if (!Expressions.IsBalanced(expression)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 320, """ - Unbalanced arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - one or more parenthesis don't have their matching pair. - """) - .CloseError(); - } - - var shuntingYard = Expressions.ShuntingYard(expression, Expressions.ArithmeticPrecedence); - - if (!Expressions.EvaluatePostfix(shuntingYard, Expressions.ArithmeticPrecedence, out Token error)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 325, """ - Invalid arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - This expression cannot be correctly evaluated. - """) - .WithNote(""" - Make sure that all operators have their matching operands. - """) - .CloseError(); - } - } - - public static void Arithmetic(ReadOnlySpan delimiters) - { - var expression = new List(); - - while (!CurrentEquals(TokenType.ReservedKeyword) && !CurrentEquals(delimiters)) - { - BuildArithmeticExpression(expression); - } - - if (!Expressions.IsBalanced(expression)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 320, """ - Unbalanced arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - one or more parenthesis don't have their matching pair. - """) - .CloseError(); - } - - var shuntingYard = Expressions.ShuntingYard(expression, Expressions.ArithmeticPrecedence); - - if (!Expressions.EvaluatePostfix(shuntingYard, Expressions.ArithmeticPrecedence, out Token error)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 325, """ - Invalid arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - This expression cannot be correctly evaluated. - """) - .WithNote(""" - Make sure that all operators have their matching operands. - """) - .CloseError(); - } - } - - public static void BuildArithmeticExpression(List expression) - { - static bool IsArithmeticSymbol(Token current) - { - return Expressions.ArithmeticPrecedence.ContainsKey(current.Value); - } - - if (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - expression.Add(Current()); - Continue(); - } - - if (IsArithmeticSymbol(Current())) - { - expression.Add(Current()); - Continue(); - } - - if (CurrentEquals(TokenType.Symbol) && !CurrentEquals(".") && !IsArithmeticSymbol(Current())) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 315, """ - Invalid arithmetic expression symbol. - """) - .WithSourceLine(Current(), $""" - This symbol is invalid. - """) - .WithNote(""" - Valid operators are: +, -, *, /, **, ( and ). - """) - .CloseError(); - } - } - - public static void Condition(TokenContext delimiter) - { - var expression = new List(); - - while (!CurrentEquals(delimiter)) - { - BuildConditionExpression(expression); - } - - if (!Expressions.IsBalanced(expression)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 320, """ - Unbalanced conditional expression. - """) - .WithSourceLine(expression[0], $""" - one or more parenthesis don't have their matching pair. - """) - .CloseError(); - } - - var shuntingYard = Expressions.ShuntingYard(expression, Expressions.ConditionalPrecedence); - - if (!Expressions.EvaluatePostfix(shuntingYard, Expressions.ConditionalPrecedence, out Token error)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 325, """ - Invalid arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - This expression cannot be correctly evaluated. - """) - .WithNote(""" - Make sure that all operators have their matching operands. - """) - .CloseError(); - } - } - - public static void Condition(ReadOnlySpan delimiters) - { - var expression = new List(); - - while (!CurrentEquals(TokenContext.IsStatement) && !CurrentEquals(delimiters)) - { - BuildConditionExpression(expression); - } - - if (!Expressions.IsBalanced(expression)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 320, """ - Unbalanced conditional expression. - """) - .WithSourceLine(expression[0], $""" - one or more parenthesis don't have their matching pair. - """) - .CloseError(); - } - - var shuntingYard = Expressions.ShuntingYard(expression, Expressions.ConditionalPrecedence); - - if (!Expressions.EvaluatePostfix(shuntingYard, Expressions.ConditionalPrecedence, out Token error)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 325, """ - Invalid arithmetic expression. - """) - .WithSourceLine(expression[0], $""" - This expression cannot be correctly evaluated. - """) - .WithNote(""" - Make sure that all operators have their matching operands. - """) - .CloseError(); - } - } - - public static void BuildConditionExpression(List expression) - { - if (CurrentEquals("IS") && (Peek(1).Value is "GREATER" or "LESS" or "EQUAL" or "NOT" || Peek(1).Type is TokenType.Symbol)) - { - Continue(); - } - else if (CurrentEquals("NOT") && (PeekEquals(1, ">") || PeekEquals(1, "<"))) - { - var combined = new Token($"NOT {Peek(1).Value}", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(combined); - Continue(2); - } - else if (CurrentEquals("NOT") && (PeekEquals(1, "GREATER") || PeekEquals(1, "LESS") || PeekEquals(1, "EQUAL"))) - { - if (PeekEquals(1, "GREATER")) - { - var combined = new Token($"NOT >", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(combined); - } - - if (PeekEquals(1, "LESS")) - { - var combined = new Token($"NOT <", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(combined); - } - - if (PeekEquals(1, "EQUAL")) - { - var combined = new Token($"<>", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(combined); - } - - Continue(2); - - if (CurrentEquals("THAN TO")) Continue(); - } - else if (CurrentEquals("GREATER") || CurrentEquals("LESS") || CurrentEquals("EQUAL")) - { - if (CurrentEquals("GREATER")) - { - var converted = new Token($">", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(converted); - } - - if (CurrentEquals("LESS")) - { - var converted = new Token($"<", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(converted); - } - - if (CurrentEquals("EQUAL")) - { - var converted = new Token($"=", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(converted); - } - - if (CurrentEquals("GREATER") && (PeekEquals(1, "OR") || PeekEquals(2, "OR"))) - { - if (!PeekEquals(1, "THAN")) Continue(2); - - if (PeekEquals(1, "THAN")) Continue(3); - - var converted = new Token($">=", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(converted); - } - - if (CurrentEquals("LESS") && (PeekEquals(1, "OR") || PeekEquals(2, "OR"))) - { - if (PeekEquals(1, "THAN")) Continue(3); - - if (!PeekEquals(1, "THAN")) Continue(2); - - var converted = new Token($"<=", TokenType.Symbol, Current().Line, Current().Column); - expression.Add(converted); - } - - Continue(); - - if (CurrentEquals("THAN TO")) Continue(); - } - else - { - if (CurrentEquals("FUNCTION") || CurrentEquals(TokenType.Identifier) && PeekEquals(1, "(")) - { - var current = Current(); - while (!CurrentEquals(")")) Continue(); - - Continue(); - expression.Add(new Token("FUNCTION-CALL", TokenType.Identifier, current.Line, current.Column)); - } - else - { - expression.Add(Current()); - Continue(); - } - } - } - - public static void StartRelationalOperator() - { - ReadOnlySpan operators = "< > <= >= ="; - - if (CurrentEquals("IS") && (PeekEquals(1, "GREATER LESS EQUAL NOT") || PeekEquals(1, TokenType.Symbol))) - { - Continue(); - } - - if (CurrentEquals("NOT") && PeekEquals(1, "> <")) - { - Continue(2); - } - else if (CurrentEquals("NOT") && PeekEquals(1, "GREATER LESS")) - { - Continue(2); - - if (CurrentEquals("THAN TO")) Continue(); - } - else if (CurrentEquals("GREATER LESS EQUAL")) - { - if (CurrentEquals("GREATER") && (PeekEquals(1, "OR") || PeekEquals(2, "OR"))) - { - if (!PeekEquals(1, "THAN")) Continue(2); - - if (PeekEquals(1, "THAN")) Continue(3); - } - - if (CurrentEquals("LESS") && (PeekEquals(1, "OR") || PeekEquals(2, "OR"))) - { - if (PeekEquals(1, "THAN")) Continue(3); - - if (!PeekEquals(1, "THAN")) Continue(2); - - } - - Continue(); - - if (CurrentEquals("THAN TO")) Continue(); - } - else if (CurrentEquals(operators)) - { - Continue(); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a relational operator. - """) - .WithNote(""" - With the exceptions being the "IS NOT EQUAL TO" and "IS NOT =" operators. - """) - .CloseError(); - - Continue(); - } - } - - public static void EncodingEndianness(bool encodingExists = false, bool endiannessExists = false) - { - if (CurrentEquals("BINARY-ENCODING DECIMAL-ENCODING")) - { - if (encodingExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Encoding phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - The encoding phrase can only be specified once in this statement. - """) - .WithNote(""" - The same applies to the endianness phrase. - """) - .CloseError(); - } - encodingExists = true; - - Expected(Current().Value); - - EncodingEndianness(encodingExists, endiannessExists); - } - - if (CurrentEquals("HIGH-ORDER-LEFT HIGH-ORDER-RIGHT")) - { - if (endiannessExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - Endianness phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - The endianness phrase can only be specified once in this statement. - """) - .WithNote(""" - The same applies to the encoding phrase. - """) - .CloseError(); - } - endiannessExists = true; - - Expected(Current().Value); - - EncodingEndianness(encodingExists, endiannessExists); - } - } - - public static EvaluateOperand SelectionSubject() - { - if (CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String) && !PeekEquals(1, TokenType.Symbol)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - return EvaluateOperand.Identifier; - } - - ParseLiteral(true, true); - return EvaluateOperand.Literal; - } - else if (CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String) && PeekEquals(1, TokenType.Symbol)) - { - if (Expressions.ArithmeticPrecedence.ContainsKey(Peek(1).Value)) - { - Arithmetic("ALSO WHEN"); - return EvaluateOperand.Arithmetic; - } - else - { - Condition("ALSO WHEN"); - return EvaluateOperand.Condition; - } - } - else if (CurrentEquals("TRUE FALSE")) - { - Choice("TRUE FALSE"); - return EvaluateOperand.TrueOrFalse; - } - - return EvaluateOperand.Invalid; - } - - public static void SelectionObject(EvaluateOperand operand) - { - bool identifier = operand is - EvaluateOperand.Identifier or EvaluateOperand.Literal or - EvaluateOperand.Arithmetic or EvaluateOperand.Boolean; - - bool literal = operand is - EvaluateOperand.Identifier or EvaluateOperand.Arithmetic or - EvaluateOperand.Boolean; - - bool arithmetic = operand is - EvaluateOperand.Identifier or EvaluateOperand.Literal or - EvaluateOperand.Arithmetic; - - bool boolean = operand is - EvaluateOperand.Identifier or EvaluateOperand.Literal or - EvaluateOperand.Boolean; - - bool range = operand is - EvaluateOperand.Identifier or EvaluateOperand.Literal or - EvaluateOperand.Arithmetic; - - bool condition = operand is - EvaluateOperand.Condition or EvaluateOperand.TrueOrFalse; - - bool truefalse = operand is - EvaluateOperand.Condition or EvaluateOperand.TrueOrFalse; - - if (identifier || literal && CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String) && !PeekEquals(1, TokenType.Symbol)) - { - if (identifier && CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - RangeExpression(range, EvaluateOperand.Identifier); - } - else if (CurrentEquals("ANY")) - { - Expected("ANY"); - } - else - { - ParseLiteral(true, true); - RangeExpression(range, EvaluateOperand.Literal); - } - } - else if (arithmetic || condition && CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String) && PeekEquals(1, TokenType.Symbol)) - { - if (arithmetic && Expressions.ArithmeticPrecedence.ContainsKey(Peek(1).Value)) - { - Arithmetic("ALSO WHEN"); - RangeExpression(range, EvaluateOperand.Arithmetic); - } - else if (CurrentEquals("ANY")) - { - Expected("ANY"); - } - else - { - Condition("ALSO WHEN"); - } - } - else if (truefalse && CurrentEquals("TRUE FALSE")) - { - Choice("TRUE FALSE ANY"); - } - else if (CurrentEquals("ANY")) - { - Expected("ANY"); - } - } - - public static void RangeExpression(bool canHaveRange, EvaluateOperand rangeType) - { - if (canHaveRange && CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - if (rangeType is EvaluateOperand.Identifier) - { - References.Identifier(); - } - else if (rangeType is EvaluateOperand.Literal) - { - ParseLiteral(true, true); - } - else if (rangeType is EvaluateOperand.Arithmetic) - { - Arithmetic("ALSO WHEN"); - } - - if (CurrentEquals("IS UTF-8")) - { - Optional("IS"); - // Need to implement other alphabet support - Expected("UTF-8"); - } - } - } - - public static void ParseLiteral(bool numeric, bool @string) - { - if (!CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or a literal. - """) - .CloseError(); - } - - if (numeric && CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else if (@string && CurrentEquals(TokenType.String)) - { - Literals.String(); - } - } - - public static bool NotIdentifierOrLiteral() - { - return !IdentifierOrLiteral(); - } - - public static bool IdentifierOrLiteral() - { - return CurrentEquals(TokenType.Identifier | TokenType.Numeric | TokenType.String | TokenType.HexString | TokenType.Boolean | TokenType.HexBoolean | TokenType.National | TokenType.HexNational | TokenType.Figurative); - } - - public static bool IdentifierOrLiteral(TokenType literalType) - { - return CurrentEquals(TokenType.Identifier | literalType); - } -} \ No newline at end of file diff --git a/Otterkit.Analyzers/src/DataClauses.cs b/Otterkit.Analyzers/src/DataClauses.cs deleted file mode 100644 index ce198816..00000000 --- a/Otterkit.Analyzers/src/DataClauses.cs +++ /dev/null @@ -1,1678 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static partial class DataDivision -{ - // The following methods are responsible for parsing data division clauses, - // each method is responsible for parsing only a single clause (Never parse two clauses with one method). - // The IsClauseErrorCheck() method handles an 'IS' keyword potentially missing its accompanying clause. - private static void IsClauseErrorCheck() - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 35, """ - Missing clause or potential clause mismatch. - """) - .WithSourceLine(Current(), """ - The 'IS' clause must only be followed by EXTERNAL, GLOBAL or TYPEDEF. - """) - .CloseError(); - } - - private static void FileEntryClauses(DataEntry fileLocal) - { - if (CurrentEquals("IS") && !PeekEquals(1, "EXTERNAL GLOBAL")) - { - IsClauseErrorCheck(); - } - - if ((CurrentEquals("IS") && PeekEquals(1, "EXTERNAL")) || CurrentEquals("EXTERNAL")) - { - ExternalClause(fileLocal); - } - - if ((CurrentEquals("IS") && PeekEquals(1, "GLOBAL")) || CurrentEquals("GLOBAL")) - { - GlobalClause(fileLocal); - } - - if (CurrentEquals("FORMAT")) - { - // TODO: This needs to be fixed later - Expected("FORMAT"); - Choice("BIT CHARACTER NUMERIC"); - Optional("DATA"); - } - - if (CurrentEquals("BLOCK")) - { - Expected("BLOCK"); - Optional("CONTAINS"); - - if (PeekEquals(1, "TO")) - { - Literals.Numeric(); - Expected("TO"); - } - - Literals.Numeric(); - Choice("CHARACTERS RECORDS"); - } - - if (CurrentEquals("RECORD")) - { - RecordClause(fileLocal); - } - - if (CurrentEquals("LINAGE")) - { - LinageClause(fileLocal); - } - - if (CurrentEquals("CODE-SET")) - { - CodeSetClause(fileLocal); - } - - if (CurrentEquals("REPORT REPORTS")) - { - ReportsClause(fileLocal); - } - } - - private static void DataEntryClauses(DataEntry entry) - { - if (CurrentEquals("IS") && !PeekEquals(1, "EXTERNAL GLOBAL TYPEDEF")) - { - IsClauseErrorCheck(); - } - - if ((CurrentEquals("IS") && PeekEquals(1, "EXTERNAL")) || CurrentEquals("EXTERNAL")) - { - ExternalClause(entry); - } - - if ((CurrentEquals("IS") && PeekEquals(1, "GLOBAL")) || CurrentEquals("GLOBAL")) - { - GlobalClause(entry); - } - - if ((CurrentEquals("IS") && PeekEquals(1, "TYPEDEF")) || CurrentEquals("TYPEDEF")) - { - TypedefClause(entry); - } - - if (CurrentEquals("REDEFINES")) - { - RedefinesClause(entry); - } - - if (CurrentEquals("ALIGNED")) - { - AlignedClause(entry); - } - - if (CurrentEquals("ANY") && PeekEquals(1, "LENGTH")) - { - AnyLengthClause(entry); - } - - if (CurrentEquals("BASED")) - { - BasedClause(entry); - } - - if (CurrentEquals("BLANK")) - { - BlankWhenClause(entry); - } - - if (CurrentEquals("CONSTANT") && PeekEquals(1, "RECORD")) - { - ConstantRecordClause(entry); - } - - if (CurrentEquals("DYNAMIC")) - { - DynamicClause(entry); - } - - if (CurrentEquals("GROUP-USAGE")) - { - GroupUsageClause(entry); - } - - if (CurrentEquals("JUSTIFIED JUST")) - { - JustifiedClause(entry); - } - - if (CurrentEquals("SYNCHRONIZED SYNC")) - { - SynchronizedClause(entry); - } - - if (CurrentEquals("PROPERTY")) - { - PropertyClause(entry); - } - - if (CurrentEquals("SAME")) - { - SameAsClause(entry); - } - - if (CurrentEquals("TYPE")) - { - TypeClause(entry); - } - - if (CurrentEquals("OCCURS")) - { - OccursClause(entry); - } - - if (CurrentEquals("PIC PICTURE")) - { - PictureClause(entry); - } - - if (CurrentEquals("VALUE VALUES")) - { - ValueClause(entry); - } - - if (CurrentEquals("USAGE")) - { - UsageClause(entry); - - ClassifyUsage(entry); - - CategorizeUsage(entry); - } - } - - private static void ReportEntryClauses() - { - if ((CurrentEquals("IS") && PeekEquals(1, "GLOBAL")) || CurrentEquals("GLOBAL")) - { - Optional("IS"); - Expected("GLOBAL"); - } - - if (CurrentEquals("CODE")) - { - Expected("CODE"); - Optional("IS"); - Common.IdentifierOrLiteral(TokenType.String); - } - - if (CurrentEquals("CONTROL CONTROLS")) - { - if (CurrentEquals("CONTROL")) - { - Expected("CONTROL"); - Optional("IS"); - } - else - { - Expected("CRONTROLS"); - Optional("ARE"); - } - - if (CurrentEquals("FINAL")) - { - Expected("FINAL"); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - return; - } - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - if (CurrentEquals("PAGE")) - { - Expected("PAGE"); - - if (CurrentEquals("LIMIT")) - { - Optional("LIMIT"); - Optional("IS"); - } - else - { - Optional("LIMITS"); - Optional("ARE"); - } - - Literals.Numeric(); - - if (CurrentEquals("LINE LINES")) - { - Choice("LINE LINES"); - } - - if (PeekEquals(1, "COL COLUMNS") && !PeekEquals(-1, TokenType.Numeric)) - { - Literals.Numeric(); - Choice("COL COLUMNS"); - } - else if (CurrentEquals("COL COLUMNS") && PeekEquals(-1, TokenType.Numeric)) - { - Choice("COL COLUMNS"); - } - - if (CurrentEquals("HEADING")) - { - Expected("HEADING"); - Optional("IS"); - Literals.Numeric(); - } - - if (CurrentEquals("FIRST")) - { - Expected("FIRST"); - Choice("DETAIL DE"); - Optional("IS"); - Literals.Numeric(); - } - - if (CurrentEquals("LAST") && PeekEquals(1, "CONTROL CH")) - { - Expected("LAST"); - if (CurrentEquals("CONTROL")) - { - Expected("CONTROL"); - Expected("HEADING"); - } - else - { - Expected("CH"); - } - - Optional("IS"); - Literals.Numeric(); - } - - if (CurrentEquals("LAST") && PeekEquals(1, "DETAIL DE")) - { - Expected("LAST"); - Choice("DETAIL DE"); - Optional("IS"); - Literals.Numeric(); - } - - if (CurrentEquals("FOOTING")) - { - Expected("FOOTING"); - Optional("IS"); - Literals.Numeric(); - } - } - } - - private static void ReportGroupClauses(DataEntry reportEntry) - { - if (CurrentEquals("TYPE")) - { - ReportTypeClause(reportEntry); - } - - if (CurrentEquals("NEXT")) - { - Expected("NEXT"); - Expected("GROUP"); - Optional("IS"); - - if (CurrentEquals("NEXT")) - { - Expected("NEXT"); - Expected("PAGE"); - - if (CurrentEquals("WITH RESET")) - { - Optional("WITH"); - Expected("RESET"); - } - } - else if (CurrentEquals("+ PLUS")) - { - Choice("+ PLUS"); - Literals.Numeric(); - } - else - { - Literals.Numeric(); - } - } - - if (CurrentEquals("LINE LINES")) - { - if (CurrentEquals("LINES")) - { - Expected("LINES"); - Optional("ARE"); - } - else - { - Expected("LINE"); - if (CurrentEquals("NUMBER")) - { - Optional("NUMBER"); - Optional("IS"); - } - else - { - Optional("NUMBERS"); - Optional("ARE"); - } - } - - while (CurrentEquals(TokenType.Numeric) || CurrentEquals("+ PLUS ON NEXT")) - { - ReportLineClauseLoop(); - } - } - - if (CurrentEquals("COLUMN COLUMNS COL COLS")) - { - if (CurrentEquals("COLUMN")) - { - Expected("COLUMN"); - OptionalChoice("NUMBER NUMBERS"); - } - else if (CurrentEquals("COLUMNS")) - { - Expected("COLUMNS"); - } - else if (CurrentEquals("COL")) - { - Expected("COL"); - OptionalChoice("NUMBER NUMBERS"); - } - else - { - Expected("COLS"); - } - - if (CurrentEquals("CENTER RIGHT")) - { - Choice("CENTER RIGHT"); - } - else - { - Optional("LEFT"); - } - - OptionalChoice("IS ARE"); - - while(CurrentEquals(TokenType.Numeric) || CurrentEquals("+ PLUS")) - { - if (CurrentEquals("+ PLUS")) - { - Choice("+ PLUS"); - Literals.Numeric(); - } - else - { - Literals.Numeric(); - } - } - } - - if (CurrentEquals("PICTURE PIC")) - { - PictureClause(reportEntry); - } - - if (CurrentEquals("SIGN")) - { - SignClause(reportEntry); - } - - if (CurrentEquals("JUSTIFIED JUST")) - { - JustifiedClause(reportEntry); - } - - if (CurrentEquals("BLANK")) - { - BlankWhenClause(reportEntry); - } - - if (CurrentEquals("PRESENT")) - { - Expected("PRESENT"); - Expected("WHEN"); - Common.Condition(TokenContext.IsClause); - } - - if (CurrentEquals("GROUP")) - { - Expected("GROUP"); - Optional("INDICATE"); - } - - if (CurrentEquals("OCCURS")) - { - Expected("OCCURS"); - if (PeekEquals(1, "TO")) - { - Literals.Numeric(); - Expected("TO"); - } - - Literals.Numeric(); - Optional("TIMES"); - - if (CurrentEquals("DEPENDING")) - { - Expected("DEPENDING"); - Optional("ON"); - References.Identifier(); - } - - if (CurrentEquals("STEP")) - { - Expected("STEP"); - Literals.Numeric(); - } - } - - if (CurrentEquals("USAGE")) - { - Expected("USAGE"); - Optional("IS"); - - Choice("DISPLAY NATIONAL"); - } - - if (CurrentEquals("SUM")) - { - while (CurrentEquals("SUM")) - { - Expected("SUM"); - Optional("OF"); - - // TODO: - // This clause has other formats - // that require identifier resolution - Common.Arithmetic(TokenContext.IsClause); - - if (CurrentEquals("UPON")) - { - Expected("UPON"); - References.Identifier(); - - while(CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - } - - if (CurrentEquals("RESET")) - { - Expected("RESET"); - Optional("ON"); - if (CurrentEquals("FINAL")) - { - Expected("FINAL"); - } - else - { - References.Identifier(); - } - } - - if (CurrentEquals("ROUNDED")) - { - Common.RoundedPhrase(); - } - } - - if (CurrentEquals("SOURCE SOURCES")) - { - if (CurrentEquals("SOURCES")) - { - Expected("SOURCES"); - Optional("ARE"); - } - else - { - Expected("SOURCE"); - Optional("IS"); - } - - Common.Arithmetic(TokenContext.IsClause); - - if (CurrentEquals("ROUNDED")) - { - Common.RoundedPhrase(); - } - } - - if (CurrentEquals("VALUE VALUES")) - { - if (CurrentEquals("VALUE")) - { - Expected("VALUE"); - Optional("IS"); - } - else - { - Expected("VALUE"); - Optional("ARE"); - } - - Literals.String(); - - while (CurrentEquals(TokenType.String)) - { - Literals.String(); - } - } - - if (CurrentEquals("VARYING")) - { - Expected("VARYING"); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - - if (CurrentEquals("FROM")) - { - Expected("FROM"); - Common.Arithmetic(" "); - } - - if (CurrentEquals("BY")) - { - Expected("BY"); - Common.Arithmetic(" "); - } - } - } - } - - private static void ReportLineClauseLoop() - { - if (CurrentEquals("ON NEXT")) - { - Optional("ON"); - Expected("NEXT"); - Expected("PAGE"); - } - else if (CurrentEquals("+ PLUS")) - { - Choice("+ PLUS"); - Literals.Numeric(); - } - else - { - Literals.Numeric(); - if (CurrentEquals("ON NEXT")) - { - Optional("ON"); - Expected("NEXT"); - Expected("PAGE"); - } - } - } - - private static void ScreenEntryClauses(DataEntry screen) - { - if ((CurrentEquals("IS") && PeekEquals(1, "GLOBAL")) || CurrentEquals("GLOBAL")) - { - GlobalClause(screen); - } - - if (CurrentEquals("LINE")) - { - LineClause(screen); - } - - if (CurrentEquals("COLUMN COL")) - { - ColumnClause(screen); - } - - if (CurrentEquals("PICTURE PIC")) - { - PictureClause(screen); - } - - if (CurrentEquals("BLANK") && PeekEquals(1, "SCREEN LINE")) - { - Expected("BLANK"); - Choice("SCREEN LINE"); - } - - if (CurrentEquals("BLANK") && !PeekEquals(1, "SCREEN LINE")) - { - BlankWhenClause(screen); - } - - if (CurrentEquals("JUSTIFIED JUST")) - { - JustifiedClause(screen); - } - - if (CurrentEquals("SIGN")) - { - SignClause(screen); - } - - if (CurrentEquals("FULL")) - { - Expected("FULL"); - } - - if (CurrentEquals("AUTO")) - { - Expected("AUTO"); - } - - if (CurrentEquals("SECURE")) - { - Expected("SECURE"); - } - - if (CurrentEquals("REQUIRED")) - { - Expected("REQUIRED"); - } - - if (CurrentEquals("BELL")) - { - Expected("BELL"); - } - - if (CurrentEquals("HIGHLIGHT LOWLIGHT")) - { - Choice("HIGHLIGHT LOWLIGHT"); - } - - if (CurrentEquals("REVERSE-VIDEO")) - { - Expected("REVERSE-VIDEO"); - } - - if (CurrentEquals("UNDERLINE")) - { - Expected("UNDERLINE"); - } - - if (CurrentEquals("FOREGROUND-COLOR")) - { - Expected("FOREGROUND-COLOR"); - Optional("IS"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - } - - if (CurrentEquals("BACKGROUND-COLOR")) - { - Expected("BACKGROUND-COLOR"); - Optional("IS"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - } - - if (CurrentEquals("OCCURS")) - { - Expected("OCCURS"); - Literals.Numeric(); - - Optional("TIMES"); - } - - if (CurrentEquals("USAGE")) - { - Expected("USAGE"); - Optional("IS"); - - Choice("DISPLAY NATIONAL"); - } - - ScreenValueClause(screen); - } - - private static void LinageClause(DataEntry fileLocal) - { - Expected("LINAGE"); - Optional("IS"); - - fileLocal[DataClause.Linage] = true; - - Common.IdentifierOrLiteral(TokenType.Numeric); - Optional("LINES"); - - if (CurrentEquals("WITH FOOTING")) - { - Optional("WITH"); - Expected("FOOTING"); - Common.IdentifierOrLiteral(TokenType.Numeric); - } - - if (CurrentEquals("LINES AT TOP")) - { - Optional("LINES"); - Optional("AT"); - Expected("TOP"); - Common.IdentifierOrLiteral(TokenType.Numeric); - } - - if (CurrentEquals("LINES AT BOTTOM")) - { - Optional("LINES"); - Optional("AT"); - Expected("BOTTOM"); - Common.IdentifierOrLiteral(TokenType.Numeric); - } - } - - private static void RecordClause(DataEntry fileLocal) - { - Expected("RECORD"); - - fileLocal[DataClause.Record] = true; - - if (CurrentEquals("IS VARYING")) - { - Optional("IS"); - Expected("VARYING"); - Optional("IN"); - Optional("SIZE"); - - if (CurrentEquals("FROM") || CurrentEquals(TokenType.Numeric)) - { - Optional("FROM"); - Literals.Numeric(); - } - - if (CurrentEquals("TO")) - { - Optional("TO"); - Literals.Numeric(); - } - - if (CurrentEquals("BYTES CHARACTERS")) - { - Expected(Current().Value); - } - - if (CurrentEquals("DEPENDING")) - { - Expected("DEPENDING"); - Optional("ON"); - References.Identifier(); - } - - return; - } - - // If the record is not varying in size - Optional("CONTAINS"); - - if (!PeekEquals(1, "TO")) - { - Literals.Numeric(); - - if (CurrentEquals("BYTES CHARACTERS")) - { - Expected(Current().Value); - } - - return; - } - - // If the record is fixed-or-variable - Literals.Numeric(); - - Expected("TO"); - - Literals.Numeric(); - - if (CurrentEquals("BYTES CHARACTERS")) - { - Expected(Current().Value); - } - } - - private static void ReportsClause(DataEntry fileLocal) - { - Choice("REPORT REPORTS"); - - fileLocal[DataClause.Report] = true; - - if (PeekEquals(-1, "REPORT")) - { - Optional("IS"); - } - else - { - Optional("ARE"); - } - - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static void CodeSetClause(DataEntry fileLocal) - { - Expected("CODE-SET"); - - fileLocal[DataClause.CodeSet] = true; - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Common.ForAlphanumericForNational(); - return; - } - - Optional("IS"); - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static void ScreenValueClause(DataEntry screenLocal) - { - if (CurrentEquals("FROM")) - { - Expected("FROM"); - Common.IdentifierOrLiteral(); - - screenLocal[DataClause.From] = true; - - return; - } - - if (CurrentEquals("TO")) - { - Expected("TO"); - References.Identifier(); - - screenLocal[DataClause.To] = true; - - return; - } - - if (CurrentEquals("USING")) - { - Expected("USING"); - References.Identifier(); - - screenLocal[DataClause.Using] = true; - - return; - } - - if (CurrentEquals("VALUE")) - { - Expected("VALUE"); - Optional("IS"); - - screenLocal[DataClause.Value] = true; - - Common.ParseLiteral(true, true); - } - } - - private static void LineClause(DataEntry screenLocal) - { - Expected("LINE"); - Optional("NUMBER"); - Optional("IS"); - - screenLocal[DataClause.Line] = true; - - if (CurrentEquals("PLUS + MINUS -")) - { - Expected(Current().Value); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - } - - private static void ColumnClause(DataEntry screenLocal) - { - Choice("COLUMN COL"); - Optional("NUMBER"); - Optional("IS"); - - screenLocal[DataClause.Column] = true; - - if (CurrentEquals("PLUS + MINUS -")) - { - Expected(Current().Value); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.Numeric(); - } - } - - private static void SignClause(DataEntry entryLocal) - { - Expected("SIGN"); - Optional("IS"); - - entryLocal[DataClause.Sign] = true; - - Choice("LEADING TRAILING"); - - if (CurrentEquals("SEPARATE")) - { - Expected("SEPARATE"); - Optional("CHARACTER"); - } - } - - private static void ExternalClause(DataEntry entryLocal) - { - Optional("IS"); - Expected("EXTERNAL"); - if (CurrentEquals("AS")) - { - Expected("AS"); - - entryLocal[DataClause.External] = true; - - entryLocal.ExternalizedName = Current().Value; - - Literals.String(); - } - - if (!CurrentEquals("AS")) - { - entryLocal[DataClause.External] = true; - - entryLocal.ExternalizedName = Current().Value; - } - } - - private static void GlobalClause(DataEntry entryLocal) - { - Optional("IS"); - Expected("GLOBAL"); - - entryLocal[DataClause.Global] = true; - } - - private static void TypedefClause(DataEntry entryLocal) - { - Optional("IS"); - Expected("TYPEDEF"); - - entryLocal[DataClause.Typedef] = true; - - if (CurrentEquals("STRONG")) Expected("STRONG"); - } - - private static void RedefinesClause(DataEntry entryLocal) - { - Expected("REDEFINES"); - References.Identifier(); - - entryLocal[DataClause.Redefines] = true; - } - - private static void AlignedClause(DataEntry entryLocal) - { - Expected("ALIGNED"); - - entryLocal[DataClause.Aligned] = true; - } - - private static void AnyLengthClause(DataEntry entryLocal) - { - Expected("ANY"); - Expected("LENGTH"); - - entryLocal[DataClause.AnyLength] = true; - } - - private static void BasedClause(DataEntry entryLocal) - { - Expected("BASED"); - - entryLocal[DataClause.Based] = true; - } - - private static void BlankWhenClause(DataEntry entryLocal) - { - Expected("BLANK"); - Optional("WHEN"); - Expected("ZERO"); - - entryLocal[DataClause.BlankWhenZero] = true; - } - - private static void ConstantRecordClause(DataEntry entryLocal) - { - Expected("CONSTANT"); - Expected("RECORD"); - - entryLocal[DataClause.ConstantRecord] = true; - } - - private static void DynamicClause(DataEntry entryLocal) - { - Expected("DYNAMIC"); - Optional("LENGTH"); - - entryLocal[DataClause.DynamicLength] = true; - - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - if (CurrentEquals("LIMIT")) - { - Expected("LIMIT"); - Optional("IS"); - Literals.Numeric(); - } - } - - private static void GroupUsageClause(DataEntry entryLocal) - { - Expected("GROUP-USAGE"); - Optional("IS"); - Choice("BIT NATIONAL"); - - entryLocal[DataClause.GroupUsage] = true; - } - - private static void JustifiedClause(DataEntry entryLocal) - { - Choice("JUSTIFIED JUST"); - Optional("RIGHT"); - - entryLocal[DataClause.Justified] = true; - } - - private static void SynchronizedClause(DataEntry entryLocal) - { - Choice("SYNCHRONIZED SYNC"); - - entryLocal[DataClause.Synchronized] = true; - - if (CurrentEquals("LEFT")) - { - Expected("LEFT"); - } - else if (CurrentEquals("RIGHT")) - { - Expected("RIGHT"); - } - } - - private static void PropertyClause(DataEntry entryLocal) - { - Expected("PROPERTY"); - - entryLocal[DataClause.Property] = true; - - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Choice("GET SET"); - } - - if (CurrentEquals("IS FINAL")) - { - Optional("IS"); - Expected("FINAL"); - } - } - - private static void SameAsClause(DataEntry entryLocal) - { - Expected("SAME"); - Expected("AS"); - References.Identifier(); - - entryLocal[DataClause.SameAs] = true; - } - - private static void TypeClause(DataEntry entryLocal) - { - Expected("TYPE"); - References.Identifier(); - - entryLocal[DataClause.Type] = true; - } - - private static void ReportTypeClause(DataEntry reportLocal) - { - Expected("TYPE"); - Optional("IS"); - - reportLocal[DataClause.Type] = true; - - if (CurrentEquals("REPORT")) - { - Expected("REPORT"); - Choice("HEADING FOOTING"); - } - - if (CurrentEquals("PAGE")) - { - Expected("PAGE"); - Choice("HEADING FOOTING"); - } - - if (CurrentEquals("DETAIL DE")) - { - Choice("DETAIL DE"); - } - - if (CurrentEquals("CONTROL CH CF")) - { - var isControlHeading = false; - - if (CurrentEquals("CONTROL") && PeekEquals(1, "HEADING")) - { - Expected("CONTROL"); - Expected("HEADING"); - isControlHeading = true; - } - else if (CurrentEquals("CONTROL") && PeekEquals(1, "FOOTING")) - { - Expected("CONTROL"); - Expected("FOOTING"); - } - else if (CurrentEquals("CH")) - { - Expected("CH"); - isControlHeading = true; - } - else if (CurrentEquals("CF")) - { - Expected("CF"); - } - - if (CurrentEquals("OR FOR FINAL") || CurrentEquals(TokenType.Identifier)) - { - OptionalChoice("ON FOR"); - if (CurrentEquals("FINAL")) - { - Expected("FINAL"); - } - else - { - References.Identifier(); - } - - if (isControlHeading && CurrentEquals("OR")) - { - Expected("OR"); - Expected("PAGE"); - } - } - } - - if (CurrentEquals("RH RF PH PF")) - { - Expected(Current().Value); - } - } - - private static void OccursClause(DataEntry entryLocal) - { - Expected("OCCURS"); - - entryLocal[DataClause.Occurs] = true; - - if (CurrentEquals("DYNAMIC")) - { - Expected("DYNAMIC"); - - if (CurrentEquals("CAPACITY")) - { - Expected("CAPACITY"); - Optional("IN"); - References.Identifier(); - } - - if (CurrentEquals("FROM")) - { - Expected("FROM"); - Literals.Numeric(); - } - - if (CurrentEquals("TO")) - { - Expected("TO"); - Literals.Numeric(); - } - - if (CurrentEquals("INITIALIZED")) - { - Expected("INITIALIZED"); - } - - Common.AscendingDescendingKey(); - - if (CurrentEquals("INDEXED")) - { - IndexedBy(); - } - - return; - } - - if (PeekEquals(1, "TO")) - { - Literals.Numeric(); - Expected("TO"); - - Literals.Numeric(); - Optional("TIMES"); - - Expected("DEPENDING"); - Optional("ON"); - - References.Identifier(); - - Common.AscendingDescendingKey(); - - if (CurrentEquals("INDEXED")) - { - IndexedBy(); - } - - return; - } - - Literals.Numeric(); - Optional("TIMES"); - - Common.AscendingDescendingKey(); - - if (CurrentEquals("INDEXED")) - { - IndexedBy(); - } - - static void IndexedBy() - { - Expected("INDEXED"); - Optional("BY"); - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - } - - private static void PictureClause(DataEntry entry) - { - Choice("PIC PICTURE"); - Optional("IS"); - - entry[DataClause.Picture] = true; - - var length = ParsePictureString(Current().Value); - - var valid = length != -1; - - (entry.Class, entry.Category) = PictureType(valid); - - entry.Length = valid ? length : 0; - - ResetSymbols(); - - Continue(); - } - - private static void ValueClause(DataEntry entryLocal) - { - Expected("VALUE"); - Optional("IS"); - - entryLocal[DataClause.Value] = true; - - if (!Literals.IsAny()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2, """ - Unexpected token. - """) - .WithSourceLine(Current(), """ - Expected a type literal. - """) - .CloseError(); - - Continue(); - - return; - } - - // TODO: Type check literals during resolution stage. - var literal = Literals.Any(); - } - - private static void UsageClause(DataEntry entry) - { - Expected("USAGE"); - Optional("IS"); - - entry[DataClause.Usage] = true; - - if (CurrentEquals("BINARY")) - { - Expected("BINARY"); - - entry.Usage = Usages.Binary; - return; - } - - if (CurrentEquals("BINARY-CHAR BINARY-SHORT BINARY-LONG BINARY-DOUBLE")) - { - Expected(Current().Value); - if (CurrentEquals("SIGNED")) - { - Expected("SIGNED"); - } - else if (CurrentEquals("UNSIGNED")) - { - Expected("UNSIGNED"); - } - - return; - } - - if (CurrentEquals("BIT")) - { - Expected("BIT"); - - entry.Usage = Usages.Bit; - return; - } - - if (CurrentEquals("COMP COMPUTATIONAL")) - { - Expected(Current().Value); - - entry.Usage = Usages.Computational; - return; - } - - if (CurrentEquals("DISPLAY")) - { - Expected("DISPLAY"); - - entry.Usage = Usages.Display; - return; - } - - if (CurrentEquals("FLOAT-BINARY-32")) - { - Expected("FLOAT-BINARY-32"); - Choice("HIGH-ORDER-LEFT HIGH-ORDER-RIGHT"); - - entry.Usage = Usages.FloatBinary32; - return; - } - - if (CurrentEquals("FLOAT-BINARY-64")) - { - Expected("FLOAT-BINARY-64"); - Choice("HIGH-ORDER-LEFT HIGH-ORDER-RIGHT"); - - entry.Usage = Usages.FloatBinary64; - return; - } - - if (CurrentEquals("FLOAT-BINARY-128")) - { - Expected("FLOAT-BINARY-128"); - Choice("HIGH-ORDER-LEFT HIGH-ORDER-RIGHT"); - - entry.Usage = Usages.FloatBinary128; - return; - } - - if (CurrentEquals("FLOAT-DECIMAL-16")) - { - Expected("FLOAT-DECIMAL-16"); - Common.EncodingEndianness(); - - entry.Usage = Usages.FloatDecimal16; - return; - } - - if (CurrentEquals("FLOAT-DECIMAL-32")) - { - Expected("FLOAT-DECIMAL-32"); - Common.EncodingEndianness(); - - entry.Usage = Usages.FloatDecimal32; - return; - } - - if (CurrentEquals("FLOAT-EXTENDED")) - { - Expected("FLOAT-EXTENDED"); - - entry.Usage = Usages.FloatExtended; - return; - } - - if (CurrentEquals("FLOAT-LONG")) - { - Expected("FLOAT-LONG"); - - entry.Usage = Usages.FloatLong; - return; - } - - if (CurrentEquals("FLOAT-SHORT")) - { - Expected("FLOAT-SHORT"); - - entry.Usage = Usages.FloatShort; - return; - } - - if (CurrentEquals("INDEX")) - { - Expected("INDEX"); - - entry.Usage = Usages.Index; - return; - } - - if (CurrentEquals("MESSAGE-TAG")) - { - Expected("MESSAGE-TAG"); - - entry.Usage = Usages.MessageTag; - return; - } - - if (CurrentEquals("NATIONAL")) - { - Expected("NATIONAL"); - - entry.Usage = Usages.National; - return; - } - - if (CurrentEquals("OBJECT")) - { - Expected("OBJECT"); - Expected("REFERENCE"); - // var isFactory = false; - // var isStronglyTyped = false; - - // Need implement identifier resolution first - // To parse the rest of this using clause correctly - if (CurrentEquals("Factory")) - { - Expected("FACTORY"); - Optional("OF"); - // isFactory = true; - } - - if (CurrentEquals("ACTIVE-CLASS")) - { - Expected("ACTIVE-CLASS"); - return; - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - if (CurrentEquals("ONLY")) - { - Expected("ONLY"); - // isStronglyTyped = true - } - - entry.Usage = Usages.ObjectReference; - return; - } - - if (CurrentEquals("POINTER")) - { - Expected("POINTER"); - - if (CurrentEquals("TO") || CurrentEquals(TokenType.Identifier)) - { - Optional("TO"); - References.Identifier(); - } - - entry.Usage = Usages.DataPointer; - return; - } - - if (CurrentEquals("FUNCTION-POINTER")) - { - Expected("FUNCTION-POINTER"); - Optional("TO"); - - References.Identifier(); - - entry.Usage = Usages.FunctionPointer; - return; - } - - if (CurrentEquals("PROGRAM-POINTER")) - { - Expected("PROGRAM-POINTER"); - - if (CurrentEquals("TO") || CurrentEquals(TokenType.Identifier)) - { - Optional("TO"); - - References.Identifier(); - } - - entry.Usage = Usages.ProgramPointer; - return; - } - - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 50, """ - Unrecognized USAGE clause. - """) - .WithSourceLine(Peek(-1)) - .WithNote(""" - This could be due to an unsupported third-party extension. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsClause); - } - - private static void ClassifyUsage(DataEntry entry) - { - if (entry[DataClause.Picture]) return; - - entry.Class = entry.Usage switch - { - Usages.None => entry.Class, - Usages.Display => entry.Class, - Usages.Bit => Classes.Boolean, - Usages.Index => Classes.Index, - Usages.MessageTag => Classes.MessageTag, - Usages.National => Classes.National, - Usages.ObjectReference => Classes.Object, - Usages.DataPointer => Classes.Pointer, - Usages.FunctionPointer => Classes.Pointer, - Usages.ProgramPointer => Classes.Pointer, - _ => Classes.Numeric, - }; - } - - private static void CategorizeUsage(DataEntry entry) - { - if (entry[DataClause.Picture]) return; - - entry.Category = entry.Usage switch - { - Usages.None => entry.Category, - Usages.Display => entry.Category, - Usages.Bit => Categories.Boolean, - Usages.Index => Categories.Index, - Usages.MessageTag => Categories.MessageTag, - Usages.National => Categories.National, - Usages.ObjectReference => Categories.ObjectReference, - Usages.DataPointer => Categories.DataPointer, - Usages.FunctionPointer => Categories.FunctionPointer, - Usages.ProgramPointer => Categories.ProgramPointer, - _ => Categories.Numeric, - }; - } -} \ No newline at end of file diff --git a/Otterkit.Analyzers/src/DataDivision.cs b/Otterkit.Analyzers/src/DataDivision.cs deleted file mode 100644 index 951ae2e7..00000000 --- a/Otterkit.Analyzers/src/DataDivision.cs +++ /dev/null @@ -1,1103 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static partial class DataDivision -{ - /// - /// Stack int LevelStack is used in the parser whenever it needs to know which data item level it is currently parsing. - /// This is used when handling the level number syntax rules, like which clauses are allowed for a particular level number or group item level number rules - /// - private static readonly Stack LevelStack = new(); - - /// - /// Stack string GroupStack is used in the parser whenever it needs to know which group the current data item belongs to. - /// This is used when handling the group item syntax rules, like which data items belong to which groups - /// - private static readonly Stack GroupStack = new(); - - // Method responsible for parsing the DATA DIVISION. - // That includes the FILE, WORKING-STORAGE, LOCAL-STORAGE, LINKAGE, REPORT and SCREEN sections. - // It is also responsible for showing appropriate error messages when an error occurs in the DATA DIVISION. - public static void Parse() - { - Expected("DATA"); - Expected("DIVISION"); - CompilerContext.ActiveScope = SourceScope.DataDivision; - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Division header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every division header must end with a separator period - """) - .CloseError(); - - AnchorPoint("WORKING-STORAGE LOCAL-STORAGE LINKAGE PROCEDURE"); - } - - if (CurrentEquals("FILE")) - FileSection(); - - if (CurrentEquals("WORKING-STORAGE")) - WorkingStorage(); - - if (CurrentEquals("LOCAL-STORAGE")) - LocalStorage(); - - if (CurrentEquals("LINKAGE")) - LinkageSection(); - - if (CurrentEquals("REPORT")) - ReportSection(); - - if (CurrentEquals("SCREEN")) - ScreenSection(); - } - - // The following methods are responsible for parsing the DATA DIVISION sections - // They are technically only responsible for parsing the section header, - // the Entries() method handles parsing the actual data items in their correct sections. - private static void FileSection() - { - Expected("FILE"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.FileSection; - - Expected("."); - while (CurrentEquals("FD SD")) - { - FileEntry(); - } - } - - private static void ReportSection() - { - Expected("REPORT"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.ReportSection; - - Expected("."); - while (CurrentEquals("RD")) - { - ReportEntry(); - } - } - - private static void ScreenSection() - { - Expected("SCREEN"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.ScreenSection; - - Expected("."); - while (CurrentEquals(TokenType.Numeric)) - { - ScreenEntries(); - } - } - - private static void WorkingStorage() - { - Expected("WORKING-STORAGE"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.WorkingStorage; - - Expected("."); - while (CurrentEquals(TokenType.Numeric)) - { - DataEntries(); - } - } - - private static void LocalStorage() - { - Expected("LOCAL-STORAGE"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.LocalStorage; - - Expected("."); - while (Current().Type is TokenType.Numeric) - { - DataEntries(); - } - } - - private static void LinkageSection() - { - Expected("LINKAGE"); - Expected("SECTION"); - CompilerContext.ActiveScope = SourceScope.LinkageSection; - - Expected("."); - while (Current().Type is TokenType.Numeric) - { - DataEntries(); - } - } - - - // The following methods are responsible for parsing the DATA DIVISION data items - // The Entries() method is responsible for identifying which kind of data item to - // parse based on it's level number. - - // The GroupEntry(), DataEntry(), and ConstantEntry() are then responsible for correctly - // parsing each data item, or in the case of the GroupEntry() a group item or 01-level elementary item. - private static void DataEntries() - { - if (CurrentEquals("77")) - DataEntry(); - - if ((CurrentEquals("01") || CurrentEquals("1")) && !PeekEquals(2, "CONSTANT")) - GroupEntry(); - - if (PeekEquals(2, "CONSTANT")) - ConstantEntry(); - } - - private static void ReportEntries() - { - if (!CurrentEquals("01 1")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Current(), """ - Expected a 01 level number. - """) - .WithNote(""" - Root level records must have a 01 level number. - """) - .CloseError(); - } - - if (CurrentEquals("01 1") && !PeekEquals(2, "CONSTANT")) - GroupEntry(); - - if (PeekEquals(2, "CONSTANT")) - ConstantEntry(); - } - - private static void RecordGroupEntries() - { - if (!CurrentEquals("01 1")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Current(), """ - Expected a 01 level number. - """) - .WithNote(""" - Root level records must have a 01 level number. - """) - .CloseError(); - } - - if (CurrentEquals("01 1") && !PeekEquals(2, "CONSTANT")) - GroupEntry(); - - if (PeekEquals(2, "CONSTANT")) - ConstantEntry(); - } - - private static void ScreenEntries() - { - if (!CurrentEquals("01 1")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Current(), """ - Expected a 01 level number. - """) - .WithNote(""" - Root level screen items must have a 01 level number. - """) - .CloseError(); - } - - if (CurrentEquals("01 1") && !PeekEquals(2, "CONSTANT")) - GroupEntry(); - - if (PeekEquals(2, "CONSTANT")) - ConstantEntry(); - } - - private static void ReportEntry() - { - Expected("RD"); - - References.Identifier(); - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected report description clauses or a separator period after this token. - """) - .CloseError(); - } - - while (CurrentEquals(TokenContext.IsClause)) - { - ReportEntryClauses(); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Report description, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every RD item must end with a separator period. - """) - .CloseError(); - } - - while(CurrentEquals(TokenType.Numeric)) - { - ReportEntries(); - } - } - - private static void ReportGroupEntry() - { - int levelNumber = int.Parse(Current().Value); - Literals.Numeric(); - - Token itemToken = Current(); - string dataName = itemToken.Value; - - CheckLevelNumber(levelNumber); - - if (CurrentEquals("FILLER")) - { - Expected("FILLER"); - } - else if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - DataEntry dataLocal = new(itemToken, EntryKind.ReportGroupDescription); - - dataLocal.LevelNumber = levelNumber; - dataLocal.Section = CompilerContext.ActiveScope; - - if (GroupStack.Count is not 0) - { - dataLocal.Parent = GroupStack.Peek(); - } - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected report item clauses or a separator period after this token - """) - .CloseError(); - } - - while (CurrentEquals(TokenContext.IsClause)) - { - ReportGroupClauses(dataLocal); - } - - HandleLevelStack(dataLocal); - - if (dataLocal.IsGroup) GroupStack.Push(dataLocal); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Report item definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every item must end with a separator period - """) - .CloseError(); - } - - CheckConditionNames(dataLocal); - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - if (dataName is "FILLER") return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(itemToken) && levelNumber is 1 or 77) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(itemToken, """ - A 01 or 77 level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(itemToken, dataLocal); - } - - private static void FileEntry() - { - Choice("FD SD"); - - Token itemToken = Current(); - string fileName = itemToken.Value; - - References.Identifier(); - - DataEntry fileLocal = new(itemToken, EntryKind.FileDescription); - - fileLocal.Section = CompilerContext.ActiveScope; - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected file description clauses or a separator period after this token - """) - .CloseError(); - } - - while (CurrentEquals(TokenContext.IsClause)) - { - FileEntryClauses(fileLocal); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - File description, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every FD item must end with a separator period - """) - .CloseError(); - } - - while(CurrentEquals(TokenType.Numeric)) - { - RecordGroupEntries(); - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(itemToken)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(itemToken, """ - A root level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(itemToken, fileLocal); - } - - private static void GroupEntryKind() - { - if (CompilerContext.ActiveScope is SourceScope.ScreenSection) - { - ScreenEntry(); - return; - } - - if (CompilerContext.ActiveScope is SourceScope.ReportSection) - { - ReportGroupEntry(); - return; - } - - DataEntry(); - } - - private static void GroupEntry() - { - GroupEntryKind(); - - _ = int.TryParse(Current().Value, out int level); - - while (level > 1 && level < 50) - { - GroupEntryKind(); - - _ = int.TryParse(Current().Value, out level); - } - - if (CompilerContext.IsResolutionPass) - { - CalculateGroupLengths(); - } - - LevelStack.Clear(); - GroupStack.Clear(); - } - - private static void CalculateGroupLengths() - { - foreach (var entry in GroupStack) - { - if (entry.Parent.Exists) - { - entry.Parent.Unwrap().Length += entry.Length; - } - } - } - - private static void DataEntry() - { - var levelNumber = int.Parse(Current().Value); - - Literals.Numeric(); - - CheckLevelNumber(levelNumber); - - Token variable; - - if (CurrentEquals(TokenType.Identifier)) - { - variable = References.LocalDefinition().Unwrap(); - } - else if (CurrentEquals("FILLER")) - { - variable = Current(); - - Optional("FILLER"); - } - else - { - variable = new("[FILLER]", TokenType.ReservedKeyword) - { - Line = CurrentLine(), - Column = CurrentColumn(), - FileIndex = CurrentFile() - }; - } - - var entry = new DataEntry(variable, EntryKind.DataDescription); - - entry.LevelNumber = levelNumber; - - entry.Section = CompilerContext.ActiveScope; - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected data item clauses or a separator period after this token - """) - .CloseError(); - } - - entry.DeclarationIndex = TokenHandling.Index; - - // COBOL standard requirement - // Usage display is the default unless specified otherwise - entry.Usage = Usages.Display; - - while (CurrentEquals(TokenContext.IsClause)) - { - DataEntryClauses(entry); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Data item definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every item must end with a separator period - """) - .CloseError(); - } - - HandleLevelStack(entry); - - if (entry.IsGroup) GroupStack.Push(entry); - - CheckClauseCompatibility(entry, variable); - - CheckConditionNames(entry); - - if (GroupStack.Count is not 0) - { - var parent = GroupStack.Peek(); - - entry.Parent = parent; - - parent.Length += entry.Length; - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - // We're also returning for filler items, they shouldn't be added to the symbol table - if (variable.Value is "FILLER" or "[FILLER]") return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(variable) && levelNumber is 1 or 77) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(variable, """ - A 01 or 77 level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(variable, entry); - } - - private static void ConstantEntry() - { - if (!CurrentEquals("01") && !CurrentEquals("1")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 40,""" - Invalid level number. - """) - .WithSourceLine(Current(), """ - CONSTANT variables must have a level number of '1' or '01'. - """) - .CloseError(); - } - - var levelNumber = int.Parse(Current().Value); - Literals.Numeric(); - - Token itemToken = Current(); - string dataName = itemToken.Value; - - References.Identifier(); - - DataEntry dataLocal = new(itemToken, EntryKind.DataDescription); - - dataLocal.LevelNumber = levelNumber; - dataLocal.Section = CompilerContext.ActiveScope; - dataLocal.IsConstant = true; - - Expected("CONSTANT"); - if (CurrentEquals("IS") || CurrentEquals("GLOBAL")) - { - Optional("IS"); - Expected("GLOBAL"); - dataLocal[DataClause.Global] = true; - } - - if (CurrentEquals("FROM")) - { - Expected("FROM"); - References.Identifier(); - } - else - { - Optional("AS"); - switch (Current().Type) - { - case TokenType.String: - Literals.String(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - case TokenType.Figurative: - Literals.Figurative(); - break; - } - - if (CurrentEquals("LENGTH")) - { - Expected("LENGTH"); - Optional("OF"); - References.Identifier(); - } - - if (CurrentEquals("BYTE-LENGTH")) - { - Expected("BYTE-LENGTH"); - Optional("OF"); - References.Identifier(); - } - - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Data item definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every item must end with a separator period - """) - .CloseError(); - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(itemToken) && levelNumber is 1 or 77) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(itemToken, """ - A 01 or 77 level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(itemToken, dataLocal); - } - - private static void ScreenEntry() - { - var levelNumber = int.Parse(Current().Value); - - Literals.Numeric(); - - CheckLevelNumber(levelNumber); - - Token variable; - - if (CurrentEquals(TokenType.Identifier)) - { - variable = References.LocalDefinition().Unwrap(); - } - else if (CurrentEquals("FILLER")) - { - variable = Current(); - - Optional("FILLER"); - } - else - { - variable = new("[FILLER]", TokenType.ReservedKeyword) - { - Line = CurrentLine(), - Column = CurrentColumn(), - FileIndex = CurrentFile() - }; - } - - var entry = new DataEntry(variable, EntryKind.ScreenDescription); - - entry.LevelNumber = levelNumber; - - entry.Section = CompilerContext.ActiveScope; - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected screen item clauses or a separator period after this token - """) - .CloseError(); - } - - entry.DeclarationIndex = TokenHandling.Index; - - // COBOL standard requirement - // Usage display is the default unless specified otherwise - entry.Usage = Usages.Display; - - while (CurrentEquals(TokenContext.IsClause)) - { - ScreenEntryClauses(entry); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Screen item definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every item must end with a separator period - """) - .CloseError(); - } - - HandleLevelStack(entry); - - if (entry.IsGroup) GroupStack.Push(entry); - - CheckClauseCompatibility(entry, variable); - - CheckConditionNames(entry); - - if (GroupStack.Count is not 0) - { - var parent = GroupStack.Peek(); - - entry.Parent = parent; - - parent.Length += entry.Length; - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - // We're also returning for filler items, they shouldn't be added to the symbol table - if (variable.Value is "FILLER" or "[FILLER]") return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(variable) && levelNumber is 1 or 77) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(variable, """ - A 01 or 77 level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(variable, entry); - } - - private static void HandleLevelStack(DataEntry entryLocal) - { - if (CurrentEquals(TokenType.Numeric) && LevelStack.Count > 0) - { - _ = int.TryParse(Current().Value, out int level); - var currentLevel = LevelStack.Peek(); - - if (currentLevel == 1 && level >= 2 && level <= 49 || level >= 2 && level <= 49 && level > currentLevel) - { - entryLocal.IsGroup = true; - } - } - } - - private static void CheckLevelNumber(int level) - { - if (level is 66 or 77 or 88) return; - - if (level is 1) - { - LevelStack.Push(level); - return; - } - - var currentLevel = LevelStack.Peek(); - - if (level == currentLevel) return; - - if (level > currentLevel && level <= 49) - { - LevelStack.Push(level); - return; - } - - if (level < currentLevel) - { - var current = LevelStack.Pop(); - var lowerLevel = LevelStack.Peek(); - if (level == lowerLevel) - { - GroupStack.Pop(); - return; - } - - if (level != lowerLevel) - { - LevelStack.Push(current); - - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 40,""" - Invalid level number. - """) - .WithSourceLine(Current(), $""" - This variable should have a level number of {lowerLevel}. - """) - .CloseError(); - } - } - } - - private static void CheckClauseCompatibility(DataEntry dataItem, Token itemToken) - { - bool usageCannotHavePicture = dataItem.Usage switch - { - Usages.BinaryChar => true, - Usages.BinaryDouble => true, - Usages.BinaryLong => true, - Usages.BinaryShort => true, - Usages.FloatShort => true, - Usages.FloatLong => true, - Usages.FloatExtended => true, - Usages.Index => true, - Usages.MessageTag => true, - Usages.ObjectReference => true, - Usages.DataPointer => true, - Usages.FunctionPointer => true, - Usages.ProgramPointer => true, - _ => false - }; - - if (usageCannotHavePicture && dataItem[DataClause.Picture]) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 45,""" - Invalid clause combination. - """) - .WithSourceLine(itemToken, $""" - Items with USAGE {dataItem.Usage.Display()} must not contain a PICTURE clause. - """) - .CloseError(); - } - - if (!usageCannotHavePicture && !dataItem.IsGroup && !dataItem[DataClause.Type] && !dataItem[DataClause.Picture] && !dataItem[DataClause.Usage] && !dataItem[DataClause.Value]) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 45,""" - Invalid clause combination. - """) - .WithSourceLine(itemToken, $""" - Elementary items must contain a PICTURE clause. - """) - .CloseError(); - } - - if (dataItem.IsGroup && dataItem[DataClause.Picture]) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 45,""" - Invalid clause combination. - """) - .WithSourceLine(itemToken, $""" - Group items must not contain a PICTURE clause. - """) - .CloseError(); - } - - if (dataItem[DataClause.Renames] && dataItem[DataClause.Picture]) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 45,""" - Invalid clause combination. - """) - .WithSourceLine(itemToken, $""" - Items with a RENAMES clause must not contain a PICTURE clause. - """) - .CloseError(); - } - - bool usageCannotHaveValue = dataItem.Usage switch - { - Usages.Index => true, - Usages.MessageTag => true, - Usages.ObjectReference => true, - Usages.DataPointer => true, - Usages.FunctionPointer => true, - Usages.ProgramPointer => true, - _ => false - }; - - if (usageCannotHaveValue && dataItem[DataClause.Value]) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 45,""" - Invalid clause combination. - """) - .WithSourceLine(itemToken, $""" - Items with USAGE {dataItem.Usage.Display()} must not contain a VALUE clause. - """) - .CloseError(); - } - } - - private static void CheckConditionNames(DataEntry parent) - { - if (!CurrentEquals("88")) return; - - while (CurrentEquals("88")) - { - Expected("88"); - - Token itemToken = Current(); - string dataName = itemToken.Value; - - References.Identifier(); - - DataEntry dataLocal = new(itemToken, EntryKind.DataDescription); - - dataLocal.Parent = parent; - dataLocal.LevelNumber = 88; - dataLocal.Section = CompilerContext.ActiveScope; - - if (CurrentEquals("VALUES")) - { - Expected("VALUES"); - Optional("ARE"); - } - else - { - Expected("VALUE"); - Optional("IS"); - } - - var firstConditionType = Current().Type; - - switch (Current().Type) - { - case TokenType.Numeric: Literals.Numeric(); break; - - case TokenType.String: - case TokenType.HexString: - case TokenType.Boolean: - case TokenType.HexBoolean: - case TokenType.National: - case TokenType.HexNational: - Literals.String(); break; - } - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - - switch (firstConditionType) - { - case TokenType.Numeric: Literals.Numeric(); break; - - case TokenType.String: - case TokenType.HexString: - case TokenType.Boolean: - case TokenType.HexBoolean: - case TokenType.National: - case TokenType.HexNational: - Literals.String(); break; - } - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - Data item definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every item must end with a separator period - """) - .CloseError(); - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) continue; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.DataNames.Exists(itemToken)) - { - // TODO: This is incorrect, but was done to replace the old error message system - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate condition name definition. - """) - .WithSourceLine(itemToken, """ - A condition variable already exists with this name - """) - .WithNote(""" - condition items must have a unique name. - """) - .CloseError(); - } - - sourceUnit.DataNames.Add(itemToken, dataLocal); - } - } -} diff --git a/Otterkit.Analyzers/src/EnvironmentClauses.cs b/Otterkit.Analyzers/src/EnvironmentClauses.cs deleted file mode 100644 index 7ea4d62b..00000000 --- a/Otterkit.Analyzers/src/EnvironmentClauses.cs +++ /dev/null @@ -1,718 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -/// -/// Otterkit COBOL Syntax and Semantic Analyzer -/// This parser was built to be easily extensible, with some reusable COBOL parts. -/// It requires a List of Tokens generated from the Lexer and the Token Classifier. -/// -public static partial class EnvironmentDivision -{ - private static void AlphabetName() - { - Expected("ALPHABET"); - References.Identifier(); - - if (CurrentEquals("NATIONAL") || PeekEquals(1, "NATIONAL")) - { - Optional("FOR"); - Expected("NATIONAL"); - Optional("IS"); - - if (CurrentEquals("LOCALE")) - { - Expected("LOCALE"); - References.Identifier(); - - return; - } - - if (CurrentEquals("NATIVE UCS-4 UTF-8 UTF-16 UTF-32")) - { - Expected(Current().Value); - - return; - } - - while (CurrentEquals(TokenType.National)) - { - NationalLiteralPhrase(); - } - - return; - } - - if (CurrentEquals("ALPHANUMERIC") || PeekEquals(1, "ALPHANUMERIC")) - { - Optional("FOR"); - Expected("ALPHANUMERIC"); - } - - Optional("IS"); - if (CurrentEquals("NATIVE STANDARD-1 STANDARD-2 UTF-8")) - { - Expected(Current().Value); - - return; - } - while (CurrentEquals(TokenType.String)) - { - AlphanumericLiteralPhrase(); - } - } - - private static void AlphanumericLiteralPhrase() - { - Literals.String(); - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - Literals.String(); - return; - } - - while (CurrentEquals("ALSO")) - { - Expected("ALSO"); - Literals.String(); - } - } - - private static void NationalLiteralPhrase() - { - Literals.National(); - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - Literals.National(); - return; - } - - while (CurrentEquals("ALSO")) - { - Expected("ALSO"); - Literals.National(); - } - } - - private static void ClassName() - { - Expected("CLASS"); - References.Identifier(); - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Optional("FOR"); - Choice("ALPHANUMERIC NATIONAL"); - } - - Optional("IS"); - - // Lookbehind: - var national = PeekEquals(-2, "NATIONAL"); - - var chosenType = national ? TokenType.National : TokenType.String; - - while(CurrentEquals(TokenType.String | TokenType.National)) - { - ClassLiteralPhrase(chosenType); - } - - if (CurrentEquals("IN")) - { - Expected("IN"); - References.Identifier(); - } - } - - private static void ClassLiteralPhrase(TokenType literalType) - { - if (literalType is TokenType.National) - { - Literals.National(); - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - Literals.National(); - } - - return; - } - - Literals.String(); - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - Literals.String(); - } - } - - private static void DynamicLengthStructure() - { - Expected("DYNAMIC"); - Expected("LENGTH"); - Optional("STRUCTURE"); - - References.Identifier(); - Optional("IS"); - - if (CurrentEquals(TokenType.Identifier)) - { - // TODO: Specify which physical structure names are allowed - References.Identifier(); - return; - } - - if (CurrentEquals("SIGNED SHORT DELIMITED")) - { - Optional("SIGNED"); - Optional("SHORT"); - - Expected("PREFIXED"); - } - - if (CurrentEquals("DELIMITED")) - { - Expected("DELIMITED"); - } - - if (!PeekEquals(-1, "PREFIXED DELIMITED")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Missing clause. - """) - .WithSourceLine(Peek(-1), """ - Expected PREFIXED and/or DELIMITED. - """) - .WithNote(""" - At least of the two must be present. - """) - .CloseError(); - } - } - - private static void SymbolicCharacters() - { - Expected("SYMBOLIC"); - Optional("CHARACTERS"); - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Optional("FOR"); - Choice("ALPHANUMERIC NATIONAL"); - } - - while (CurrentEquals(TokenType.Identifier)) - { - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - if (CurrentEquals("IS ARE")) - { - Choice("IS ARE"); - } - - while (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - } - - if (CurrentEquals("IN")) - { - Expected("IS"); - References.Identifier(); - } - } - - private static void CharacterClassification() - { - Optional("CHARACTER"); - Expected("CLASSIFICATION"); - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Common.ForAlphanumericForNational(); - return; - } - - Optional("IS"); - LocalePhrase(); - - if (CurrentEquals(TokenType.Identifier) || CurrentEquals("LOCALE SYSTEM-DEFAULT USER-DEFAULT")) - { - LocalePhrase(); - } - } - - private static void ForAlphaForNationalLocale(bool forAlphanumericExists = false, bool forNationalExists = false) - { - if (CurrentEquals("FOR") && PeekEquals(1, "ALPHANUMERIC") || CurrentEquals("ALPHANUMERIC")) - { - if (forAlphanumericExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - For alphanumeric phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - FOR ALPHANUMERIC can only be specified once in this statement. - """) - .WithNote(""" - The same applies to FOR NATIONAL. - """) - .CloseError(); - } - forAlphanumericExists = true; - - Optional("FOR"); - Expected("ALPHANUMERIC"); - Optional("IS"); - - LocalePhrase(); - - ForAlphaForNationalLocale(forAlphanumericExists, forNationalExists); - } - - if (CurrentEquals("FOR") && PeekEquals(1, "NATIONAL") || CurrentEquals("NATIONAL")) - { - if (forNationalExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 132, """ - For national phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - FOR NATIONAL can only be specified once in this statement. - """) - .WithNote(""" - The same applies to FOR ALPHANUMERIC. - """) - .CloseError(); - } - forNationalExists = true; - - Optional("FOR"); - Expected("NATIONAL"); - Optional("IS"); - - LocalePhrase(); - - ForAlphaForNationalLocale(forAlphanumericExists, forNationalExists); - } - } - - private static void LocalePhrase() - { - if (CurrentEquals("LOCALE SYSTEM-DEFAULT USER-DEFAULT")) - { - Expected(Current().Value); - } - else - { - References.Identifier(); - } - } - - private static void ProgramCollatingSequence() - { - Optional("PROGRAM"); - Optional("COLLATING"); - Expected("SEQUENCE"); - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Common.ForAlphanumericForNational(); - return; - } - - Optional("IS"); - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static void Same() - { - Expected("SAME"); - - if (CurrentEquals("RECORD SORT SORT-MERGE")) - { - Expected(Current().Value); - } - - Optional("AREA"); - Optional("FOR"); - - References.Identifier(); - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static FileControlEntry Assign(Token fileToken) - { - Expected("ASSIGN"); - - FileControlEntry fileControl; - - if (CurrentEquals("USING")) - { - Expected("USING"); - - fileControl = new(fileToken, EntryKind.FileControl); - - References.Identifier(); - } - else - { - Optional("TO"); - fileControl = new(fileToken, EntryKind.FileControl); - - if (CurrentEquals(TokenType.Identifier)) - { - References.LocalName(); - } - else - { - Literals.String(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.LocalName(); - } - else - { - Literals.String(); - } - } - } - - return fileControl; - } - - private static void FileControlClauses(FileControlEntry fileControl) - { - if (CurrentEquals("ACCESS")) - { - Access(fileControl); - } - - if (CurrentEquals("RECORD") && !PeekEquals(1, "DELIMITER")) - { - Record(fileControl); - } - - if (CurrentEquals("RECORD") && PeekEquals(1, "DELIMITER")) - { - RecordDelimiter(fileControl); - } - - while (CurrentEquals("ALTERNATE")) - { - AlternateRecord(fileControl); - } - - if (CurrentEquals("COLLATING SEQUENCE")) - { - CollatingSequence(fileControl); - } - - if (CurrentEquals("RELATIVE")) - { - Relative(fileControl); - } - - if (CurrentEquals("FILE STATUS")) - { - FileStatus(fileControl); - } - - if (CurrentEquals("LOCK")) - { - Lock(fileControl); - } - - if (CurrentEquals("ORGANIZATION INDEXED RELATIVE LINE RECORD SEQUENTIAL")) - { - Organization(fileControl); - } - - if (CurrentEquals("RESERVE")) - { - Reserve(fileControl); - } - - if (CurrentEquals("SHARING")) - { - Sharing(fileControl); - } - } - - private static void Access(FileControlEntry fileControl) - { - Expected("ACCESS"); - Optional("MODE"); - Optional("IS"); - - Choice("DYNAMIC RANDOM SEQUENTIAL"); - } - - private static void Record(FileControlEntry fileControl) - { - Expected("RECORD"); - - Optional("KEY"); - Optional("IS"); - - if (!PeekEquals(1, "SOURCE")) - { - References.Identifier(); - - return; - } - - // If Lookahead(1) does equal SOURCE: - References.Identifier(); - Expected("SOURCE"); - - Optional("IS"); - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static void AlternateRecord(FileControlEntry fileControl) - { - Expected("ALTERNATE"); - Expected("RECORD"); - - Optional("KEY"); - Optional("IS"); - - if (!PeekEquals(1, "SOURCE")) - { - References.Identifier(); - - if (CurrentEquals("WITH DUPLICATES")) - { - Optional("WITH"); - Expected("DUPLICATES"); - } - - if (CurrentEquals("SUPPRESS")) - { - Expected("SUPPRESS"); - Optional("WHEN"); - - Literals.String(); - } - - return; - } - - // If Lookahead(1) does equal SOURCE: - References.Identifier(); - Expected("SOURCE"); - - Optional("IS"); - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - if (CurrentEquals("WITH DUPLICATES")) - { - Optional("WITH"); - Expected("DUPLICATES"); - } - - if (CurrentEquals("SUPPRESS")) - { - Expected("SUPPRESS"); - Optional("WHEN"); - - Literals.String(); - } - } - - private static void Lock(FileControlEntry fileControl) - { - Expected("LOCK"); - Optional("MODE"); - Optional("IS"); - - Choice("MANUAL AUTOMATIC"); - - if (CurrentEquals("WITH LOCK")) - { - Optional("WITH"); - Expected("LOCK"); - Expected("ON"); - - if (CurrentEquals("MULTIPLES")) - { - Expected("MULTIPLE"); - } - - Choice("RECORD RECORDS"); - } - } - - private static void FileStatus(FileControlEntry fileControl) - { - Optional("FILE"); - Expected("STATUS"); - Optional("IS"); - - References.Identifier(); - } - - private static void CollatingSequence(FileControlEntry fileControl) - { - Optional("COLLATING"); - Expected("SEQUENCE"); - - if (CurrentEquals("OF")) - { - Expected("OF"); - - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - Optional("IS"); - References.Identifier(); - return; - } - - if (CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - Common.ForAlphanumericForNational(); - return; - } - - Optional("IS"); - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - } - - private static void Organization(FileControlEntry fileControl) - { - if (CurrentEquals("ORGANIZATION")) - { - Expected("ORGANIZATION"); - Optional("IS"); - } - - if (CurrentEquals("LINE")) - { - Expected("LINE"); - Expected("SEQUENTIAL"); - - return; - } - - if (CurrentEquals("RECORD SEQUENTIAL")) - { - Optional("RECORD"); - Expected("SEQUENTIAL"); - - return; - } - - Choice("INDEXED RELATIVE"); - } - - private static void Relative(FileControlEntry fileControl) - { - Expected("RELATIVE"); - Optional("KEY"); - Optional("IS"); - - References.Identifier(); - } - - private static void RecordDelimiter(FileControlEntry fileControl) - { - Expected("RECORD"); - Expected("DELIMITER"); - Optional("IS"); - - if (CurrentEquals("STANDARD-1")) - { - Expected("STANDARD-1"); - } - else - { - // We have to define the names for these later: - References.Identifier(); - } - } - - private static void Reserve(FileControlEntry fileControl) - { - Expected("RESERVE"); - Literals.Numeric(); - - if (CurrentEquals("AREA AREAS")) - { - Expected(Current().Value); - } - } - - private static void Sharing(FileControlEntry fileControl) - { - Expected("SHARING"); - Optional("WITH"); - - if (CurrentEquals("ALL")) - { - Expected("ALL"); - Optional("OTHER"); - return; - } - - if (CurrentEquals("NO")) - { - Expected("NO"); - Optional("OTHER"); - return; - } - - if (CurrentEquals("READ")) - { - Expected("READ"); - Expected("ONLY"); - return; - } - } -} diff --git a/Otterkit.Analyzers/src/EnvironmentDivision.cs b/Otterkit.Analyzers/src/EnvironmentDivision.cs deleted file mode 100644 index cdd4cc37..00000000 --- a/Otterkit.Analyzers/src/EnvironmentDivision.cs +++ /dev/null @@ -1,686 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using static Otterkit.Types.CompilerContext; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -/// -/// Otterkit COBOL Syntax and Semantic Analyzer -/// This parser was built to be easily extensible, with some reusable COBOL parts. -/// It requires a List of Tokens generated from the Lexer and the Token Classifier. -/// -public static partial class EnvironmentDivision -{ - // Method responsible for parsing the ENVIRONMENT DIVISION. - // That includes the CONFIGURATION and the INPUT-OUTPUT sections. - // It is also responsible for showing appropriate error messages when an error occurs in the ENVIRONMENT DIVISION. - public static void Parse() - { - Expected("ENVIRONMENT"); - Expected("DIVISION"); - CompilerContext.ActiveScope = SourceScope.EnvironmentDivision; - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Division header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every division header must end with a separator period - """) - .CloseError(); - } - - if (CurrentEquals("CONFIGURATION")) - { - Expected("CONFIGURATION"); - Expected("SECTION"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Section header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every section header must end with a separator period - """) - .CloseError(); - } - - if (CurrentEquals("SOURCE-COMPUTER")) - { - SourceComputer(); - } - - if (CurrentEquals("OBJECT-COMPUTER")) - { - ObjectComputer(); - } - - if (CurrentEquals("SPECIAL-NAMES")) - { - SpecialNames(); - } - - if (CurrentEquals("REPOSITORY")) - { - Repository(); - } - } - - if (CurrentEquals("INPUT-OUTPUT")) - { - Expected("INPUT-OUTPUT"); - Expected("SECTION"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Section header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every section header must end with a separator period - """) - .CloseError(); - } - - if (CurrentEquals("FILE-CONTROL")) - { - FileControl(); - } - - if (CurrentEquals("I-O-CONTROL")) - { - IoControl(); - } - } - } - - private static void SourceComputer() - { - Expected("SOURCE-COMPUTER"); - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(Current()); - - Expected("."); - } - } - - private static void ObjectComputer() - { - Expected("OBJECT-COMPUTER"); - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - var shouldHaveSeparator = false; - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(Current()); - shouldHaveSeparator = true; - } - - if (CurrentEquals("CHARACTER CLASSIFICATION")) - { - CharacterClassification(); - shouldHaveSeparator = true; - } - - if (CurrentEquals("PROGRAM COLLATING SEQUENCE")) - { - ProgramCollatingSequence(); - shouldHaveSeparator = true; - } - - if (shouldHaveSeparator) - { - Expected("."); - } - } - - private static void SpecialNames() - { - Expected("SPECIAL-NAMES"); - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - while (CurrentEquals("ALPHABET")) - { - AlphabetName(); - } - - while (CurrentEquals("CLASS")) - { - ClassName(); - } - - if (CurrentEquals("CRT")) - { - Expected("CRT"); - Expected("STATUS"); - Optional("IS"); - - References.Identifier(); - } - - while (CurrentEquals("CURRENCY")) - { - Expected("CURRENCY"); - Optional("SIGN"); - Optional("IS"); - - Literals.String(); - - if (CurrentEquals("WITH PICTURE")) - { - Optional("WITH"); - Expected("PICTURE"); - Expected("SYMBOL"); - - Literals.String(); - } - } - - if (CurrentEquals("CURSOR")) - { - Expected("CURSOR"); - Optional("IS"); - - References.Identifier(); - } - - if (CurrentEquals("DECIMAL-POINT")) - { - Expected("DECIMAL-POINT"); - Optional("IS"); - Expected("COMMA"); - } - - while (CurrentEquals("DYNAMIC")) - { - DynamicLengthStructure(); - } - - while (CurrentEquals("LOCALE")) - { - Expected("LOCALE"); - Optional("IS"); - - // TODO: Define allowed locale names - Literals.String(); - } - - while (CurrentEquals(TokenType.Identifier)) - { - // TODO: Define allowed device, feature and switch names - // and replace TokenType.Identifier with the allowed names - References.Identifier(); - Optional("IS"); - - // Mnemonic name - References.Identifier(); - } - - while (CurrentEquals("SYMBOLIC")) - { - SymbolicCharacters(); - } - - if (CurrentEquals("ORDER")) - { - Expected("ORDER"); - Expected("TABLE"); - References.Identifier(); - - Optional("IS"); - Literals.String(); - } - - if (!PeekEquals(-2, "SPECIAL-NAMES") && !PeekEquals(-1, "SPECIAL-NAMES")) - { - Expected("."); - } - } - - private static void Repository() - { - Expected("REPOSITORY"); - CompilerContext.ActiveScope = SourceScope.Repository; - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - while (CurrentEquals("CLASS INTERFACE FUNCTION PROGRAM PROPERTY")) - { - if (CurrentEquals("CLASS")) - { - Expected("CLASS"); - - var option = TryNewRepository(); - - if (!option.Exists) continue; - - var repository = option.Unwrap(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - - Literals.String(); - - repository[RepositoryClause.External] = true; - } - - if (CurrentEquals("EXPANDS")) - { - Expected("EXPANDS"); - References.GlobalName(true); - - repository[RepositoryClause.Expands] = true; - - Expected("USING"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 105, """ - Missing USING phrase class or interface name. - """) - .WithSourceLine(Peek(-1), """ - The USING phrase must define at least one class or interface name. - """) - .CloseError(); - - AnchorPoint("CLASS INTERFACE FUNCTION PROGRAM PROPERTY DATA PROCEDURE"); - } - - References.GlobalName(true); - - while (CurrentEquals(TokenType.Identifier)) - { - References.GlobalName(true); - } - } - - var token = repository.Identifier.Unwrap(); - - ActiveCallable.LocalNames.TryAdd(token, repository); - } - - if (CurrentEquals("INTERFACE")) - { - Expected("INTERFACE"); - - var option = TryNewRepository(); - - if (!option.Exists) continue; - - var repository = option.Unwrap(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - - Literals.String(); - - repository[RepositoryClause.External] = true; - } - - if (CurrentEquals("EXPANDS")) - { - Expected("EXPANDS"); - - References.GlobalName(true); - - repository[RepositoryClause.Expands] = true; - - Expected("USING"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 105, """ - Missing USING phrase class or interface name. - """) - .WithSourceLine(Peek(-1), """ - The USING phrase must define at least one class or interface name. - """) - .CloseError(); - - AnchorPoint("CLASS INTERFACE FUNCTION PROGRAM PROPERTY DATA PROCEDURE"); - } - - References.GlobalName(true); - - while (CurrentEquals(TokenType.Identifier)) - { - References.GlobalName(true); - } - } - - var token = repository.Identifier.Unwrap(); - - ActiveCallable.LocalNames.TryAdd(token, repository); - } - - if (CurrentEquals("FUNCTION")) - { - Expected("FUNCTION"); - if (CurrentEquals("ALL")) - { - Expected("ALL"); - Expected("INTRINSIC"); - - continue; - } - - if (CurrentEquals(TokenType.IntrinsicFunction) || PeekEquals(1, "INTRINSIC") || CurrentEquals(TokenType.Identifier) && PeekEquals(1, TokenType.Identifier | TokenType.IntrinsicFunction)) - { - References.IntrinsicName(); - - while (!CurrentEquals("INTRINSIC")) - { - References.IntrinsicName(); - } - - Expected("INTRINSIC"); - - continue; - } - - var option = TryNewRepository(); - - if (!option.Exists) continue; - - var repository = option.Unwrap(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - - repository[RepositoryClause.External] = true; - } - - var token = repository.Identifier.Unwrap(); - - ActiveCallable.LocalNames.TryAdd(token, repository); - } - - if (CurrentEquals("PROGRAM")) - { - Expected("PROGRAM"); - - var option = TryNewRepository(); - - if (!option.Exists) continue; - - var repository = option.Unwrap(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - - repository[RepositoryClause.External] = true; - } - - var token = repository.Identifier.Unwrap(); - - ActiveCallable.LocalNames.TryAdd(token, repository); - } - - if (CurrentEquals("PROPERTY")) - { - Expected("PROPERTY"); - - References.Identifier(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - } - } - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph body, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph body must end with a separator period. - """) - .CloseError(); - } - } - - private static Option TryNewRepository() - { - var token = References.GlobalName(true); - - if (!token.Exists) - { - return null; - } - - var repository = new RepositoryEntry(token.Unwrap(), EntryKind.RepositoryEntry); - - repository.DeclarationIndex = TokenHandling.Index; - - return repository; - } - - private static void IoControl() - { - Expected("I-O-CONTROL"); - CompilerContext.ActiveScope = SourceScope.FileControl; - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - if (CurrentEquals("APPLY")) - { - Expected("APPLY"); - Expected("COMMIT"); - Optional("ON"); - - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - Expected("."); - } - - if (CurrentEquals("SAME")) - { - while (CurrentEquals("SAME")) - { - Same(); - } - - Expected("."); - } - } - - private static void FileControl() - { - Expected("FILE-CONTROL"); - CompilerContext.ActiveScope = SourceScope.FileControl; - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Paragraph header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every paragraph header must end with a separator period. - """) - .CloseError(); - } - - while (CurrentEquals("SELECT")) - { - FileControlEntry(); - } - } - - private static void FileControlEntry() - { - Expected("SELECT"); - - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - } - - Token fileToken = Current(); - string fileName = fileToken.Value; - - References.Identifier(); - - var fileControl = Assign(fileToken); - - if (!CurrentEquals(TokenContext.IsClause) && !CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2,""" - Unexpected token. - """) - .WithSourceLine(Peek(-1), """ - Expected file control clauses or a separator period after this token. - """) - .CloseError(); - } - - while (CurrentEquals(TokenContext.IsClause)) - { - FileControlClauses(fileControl); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25,""" - File control, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every file control item must end with a separator period. - """) - .CloseError(); - } - - // We're returning during a resolution pass - if (CompilerContext.IsResolutionPass) return; - - // Because we don't want to run this again during it - var sourceUnit = CompilerContext.ActiveCallable; - - if (sourceUnit.LocalNames.Exists(fileToken)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 30,""" - Duplicate root level definition. - """) - .WithSourceLine(fileToken, """ - A root level variable already exists with this name. - """) - .WithNote(""" - Every root level item must have a unique name. - """) - .CloseError(); - } - - sourceUnit.LocalNames.TryAdd(fileToken, fileControl); - } -} diff --git a/Otterkit.Analyzers/src/Expressions.cs b/Otterkit.Analyzers/src/Expressions.cs deleted file mode 100644 index 287eb770..00000000 --- a/Otterkit.Analyzers/src/Expressions.cs +++ /dev/null @@ -1,255 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static class Expressions -{ - public static readonly Dictionary ArithmeticPrecedence = new() - { - ["("] = 0, - ["+"] = 1, - ["-"] = 1, - ["*"] = 2, - ["/"] = 2, - ["**"] = 3, - [")"] = 4, - }; - - public static readonly Dictionary ConditionalPrecedence = new() - { - ["("] = 0, - ["AND"] = 1, - ["OR"] = 1, - ["XOR"] = 1, - ["EXCLUSIVE-OR"] = 1, - ["NOT"] = 2, - ["<"] = 3, - [">"] = 3, - ["NOT <"] = 3, - ["NOT >"] = 3, - ["<="] = 3, - [">="] = 3, - ["="] = 3, - ["<>"] = 3, - [")"] = 4, - }; - - public static List ShuntingYard(List input, Dictionary precedence) - { - var output = new List(); - var stack = new Stack(); - var isArithmetic = precedence.ContainsKey("+"); - - foreach (var token in input) - { - if (token.Type is TokenType.Numeric or TokenType.Identifier or TokenType.String) - { - output.Add(token); - } - else if (token.Value.Equals("(")) - { - stack.Push(token); - } - else if (token.Value.Equals(")")) - { - while (!stack.Peek().Value.Equals("(")) - { - output.Add(stack.Pop()); - } - - stack.Pop(); - } - else if (precedence.ContainsKey(token.Value)) - { - var isExponentiation = token.Value == "**"; - - if (isArithmetic) - while (stack.Count > 0 && ((precedence[stack.Peek().Value] > precedence[token.Value] && !isExponentiation) || (precedence[stack.Peek().Value] >= precedence[token.Value] && !isExponentiation && stack.Peek().Value == "**"))) - { - output.Add(stack.Pop()); - } - - if (!isArithmetic) - while (stack.Count > 0 && precedence[stack.Peek().Value] >= precedence[token.Value]) - { - output.Add(stack.Pop()); - } - - stack.Push(token); - } - } - - while (stack.Count > 0) - { - output.Add(stack.Pop()); - } - - return output; - } - - public static string PostfixToInfix(List postfix, Dictionary precedence) - { - var stack = new Stack(); - - foreach (var token in postfix) - { - var isUnary = token.Value == "NOT"; - - if (token.Type is TokenType.Numeric or TokenType.Identifier or TokenType.String) - { - stack.Push(token.Value); - } - - else if (precedence.ContainsKey(token.Value) && isUnary) - { - var right = stack.Pop(); - stack.Push($"({token.Value} {right})"); - } - - else if (precedence.ContainsKey(token.Value) && !isUnary) - { - var right = stack.Pop(); - var left = stack.Pop(); - stack.Push($"({left} {token.Value} {right})"); - } - } - - return stack.Pop(); - } - - public static string PostfixToCSharpInfix(List postfix, Dictionary precedence) - { - var stack = new Stack(); - - foreach (var token in postfix) - { - var isUnary = token.Value == "NOT"; - - if (token.Type is TokenType.Numeric or TokenType.Identifier or TokenType.String) - { - stack.Push(token.Value); - } - - else if (precedence.ContainsKey(token.Value) && isUnary) - { - var right = stack.Pop(); - stack.Push($"!({right})"); - } - - else if (precedence.ContainsKey(token.Value) && !isUnary) - { - var right = stack.Pop(); - var left = stack.Pop(); - - switch (token.Value) - { - case "NOT >": - stack.Push($"!({left} > {right})"); break; - - case "NOT <": - stack.Push($"!({left} < {right})"); break; - - case "<>": - stack.Push($"({left} != {right})"); break; - - case "=": - stack.Push($"({left} == {right})"); break; - - case "AND": - stack.Push($"({left} && {right})"); break; - - case "OR": - stack.Push($"({left} || {right})"); break; - - case "XOR": - case "EXCLUSIVE-OR": - stack.Push($"({left} ^ {right})"); break; - - default: - stack.Push($"({left} {token.Value} {right})"); break; - } - - } - } - - return stack.Pop(); - } - - public static bool IsBalanced(List tokens) - { - Stack stack = new(); - - foreach (Token token in tokens) - { - if (token.Value.Equals("(")) - { - stack.Push(token); - } - else if (token.Value.Equals(")")) - { - if (stack.Count == 0 || !stack.Pop().Value.Equals("(")) - { - return false; - } - } - } - - return stack.Count == 0; - } - - public static bool EvaluatePostfix(List expression, Dictionary precedence, out Token error) - { - Stack stack = new(); - - foreach (var token in expression) - { - if (token.Type is TokenType.Numeric or TokenType.Identifier or TokenType.String) - { - stack.Push(token); - } - else if (precedence.ContainsKey(token.Value)) - { - var isUnary = token.Value == "NOT"; - - if (stack.Count < 1 && isUnary) - { - error = stack.Pop(); - return false; - } - - if (stack.Count < 2 && !isUnary) - { - error = stack.Pop(); - return false; - } - - if (isUnary) - { - var unary = stack.Pop(); - stack.Push(token); - } - - if (!isUnary) - { - var right = stack.Pop(); - var left = stack.Pop(); - stack.Push(token); - } - } - else - { - error = token; - return false; - } - } - - if (stack.Count != 1) - { - error = stack.Pop(); - return false; - } - - error = new Token("NoError", TokenType.EOF, -1, -1); - return true; - } -} \ No newline at end of file diff --git a/Otterkit.Analyzers/src/ExtensionMethods.cs b/Otterkit.Analyzers/src/ExtensionMethods.cs deleted file mode 100644 index 8dfd8888..00000000 --- a/Otterkit.Analyzers/src/ExtensionMethods.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static class ExtensionMethods -{ - public static string Display(this Usages usage) - { - return usage switch - { - Usages.Binary => "BINARY", - Usages.BinaryChar => "BINARY-CHAR", - Usages.BinaryShort => "BINARY-SHORT", - Usages.BinaryLong => "BINARY-LONG", - Usages.BinaryDouble => "BINARY-DOUBLE", - Usages.Bit => "BIT", - Usages.Computational => "COMPUTATIONAL", - Usages.Display => "DISPLAY", - Usages.FloatBinary32 => "FLOAT-BINARY-32", - Usages.FloatBinary64 => "FLOAT-BINARY-64", - Usages.FloatBinary128 => "FLOAT-BINARY-128", - Usages.FloatDecimal16 => "FLOAT-DECIMAL-16", - Usages.FloatDecimal32 => "FLOAT-DECIMAL-32", - Usages.FloatExtended => "FLOAT-EXTENDED", - Usages.FloatLong => "FLOAT-LONG", - Usages.FloatShort => "FLOAT-SHORT", - Usages.Index => "INDEX", - Usages.MessageTag => "MESSAGE-TAG", - Usages.National => "NATIONAL", - Usages.ObjectReference => "OBJECT REFERENCE", - Usages.PackedDecimal => "PACKED-DECIMAL", - Usages.DataPointer => "POINTER", - Usages.FunctionPointer => "FUNCTION-POINTER", - Usages.ProgramPointer => "PROGRAM-POINTER", - _ => "NONE" - }; - } - - public static string Display(this TokenType tokenType, bool uppercased) - { - return (tokenType, uppercased) switch - { - (TokenType.Identifier, true) => "Identifier", - (TokenType.Identifier, false) => "identifier", - - (TokenType.ReservedKeyword, true) => "Reserved word", - (TokenType.ReservedKeyword, false) => "reserved word", - - (TokenType.IntrinsicFunction, true) => "Intrinsic function", - (TokenType.IntrinsicFunction, false) => "intrinsic function", - - (TokenType.String, true) => "Alphanumeric literal", - (TokenType.String, false) => "alphanumeric literal", - - (TokenType.HexString, true) => "Hexadecimal alphanumeric literal", - (TokenType.HexString, false) => "hexadecimal alphanumeric literal", - - (TokenType.National, true) => "National literal", - (TokenType.National, false) => "national literal", - - (TokenType.HexNational, true) => "Hexadecimal national literal", - (TokenType.HexNational, false) => "hexadecimal national literal", - - (TokenType.Boolean, true) => "Boolean literal", - (TokenType.Boolean, false) => "boolean literal", - - (TokenType.HexBoolean, true) => "Hexadecimal boolean literal", - (TokenType.HexBoolean, false) => "hexadecimal boolean literal", - - (TokenType.Numeric, true) => "Numeric literal", - (TokenType.Numeric, false) => "numeric literal", - - (TokenType.Symbol, true) => "Symbol", - (TokenType.Symbol, false) => "symbol", - - (TokenType.Device, true) => "Device name", - (TokenType.Device, false) => "device name", - - (TokenType.EOF, true) => "End of file", - (TokenType.EOF, false) => "end of file", - - (TokenType.Expression, true) => "Expression", - (TokenType.Expression, false) => "expression", - _ => "Error" - }; - } -} diff --git a/Otterkit.Analyzers/src/IdentificationDivision.cs b/Otterkit.Analyzers/src/IdentificationDivision.cs deleted file mode 100644 index ccc08585..00000000 --- a/Otterkit.Analyzers/src/IdentificationDivision.cs +++ /dev/null @@ -1,829 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using static Otterkit.Types.CompilerContext; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -/// -/// Otterkit COBOL Syntax and Semantic Analyzer -/// This parser was built to be easily extensible, with some reusable COBOL parts. -/// It requires a List of Tokens generated from the Lexer and the Token Classifier. -/// -public static class IdentificationDivision -{ - // Method responsible for parsing the IDENTIFICATION DIVISION. - // That includes PROGRAM-ID, FUNCTION-ID, CLASS-ID, METHOD-ID, INTERFACE-ID, OBJECT, FACTORY and OPTIONS paragraphs. - // It is also responsible for showing appropriate error messages when an error occurs in the IDENTIFICATION DIVISION. - public static void Parse() - { - if (CurrentEquals("IDENTIFICATION")) - { - Expected("IDENTIFICATION"); - Expected("DIVISION"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Division header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every division header must end with a separator period - """) - .CloseError(); - - AnchorPoint("PROGRAM-ID FUNCTION-ID ENVIRONMENT DATA PROCEDURE"); - } - } - - IdDefinitions(); - - if (CurrentEquals("OPTIONS")) - Options(); - } - - private static void Options() - { - bool shouldHavePeriod = false; - - Expected("OPTIONS"); - Expected("."); - - if (CurrentEquals("ARITHMETIC")) - { - Expected("ARITHMETIC"); - Optional("IS"); - Choice("NATIVE STANDARD-BINARY STANDARD-DECIMAL"); - - shouldHavePeriod = true; - } - - if (CurrentEquals("DEFAULT")) - { - Expected("DEFAULT"); - Expected("ROUNDED"); - Optional("MODE"); - Optional("IS"); - - Choice("AWAY-FROM-ZERO NEAREST-AWAY-FROM-ZERO NEAREST-EVEN NEAREST-TOWARD-ZERO PROHIBITED TOWARD-GREATER TOWARD-LESSER TRUNCATION"); - - shouldHavePeriod = true; - } - - if (CurrentEquals("ENTRY-CONVENTION")) - { - Expected("ENTRY-CONVENTION"); - Optional("IS"); - Expected("COBOL"); - - shouldHavePeriod = true; - } - - if (CurrentEquals("FLOAT-BINARY")) - { - Expected("FLOAT-BINARY"); - Optional("DEFAULT"); - Optional("IS"); - - Choice("HIGH-ORDER-LEFT HIGH-ORDER-RIGHT"); - } - - if (CurrentEquals("FLOAT-DECIMAL")) - { - Expected("FLOAT-DECIMAL"); - Optional("DEFAULT"); - Optional("IS"); - - Common.EncodingEndianness(); - } - - if (CurrentEquals("INITIALIZE")) - { - Expected("INITIALIZE"); - - InitializeChoices(); - Optional("SECTION"); - Optional("TO"); - - if (CurrentEquals(TokenType.String)) - { - Literals.String(); - } - else if (CurrentEquals("BINARY")) - { - Expected("BINARY"); - Expected("ZEROS"); - } - else - { - Choice("SPACES LOW-VALUES HIGH-VALUES"); - } - } - - if (CurrentEquals("INTERMEDIATE")) - { - Expected("INTERMEDIATE"); - Expected("ROUNDING"); - - Choice("NEAREST-AWAY-FROM-ZERO NEAREST-EVEN PROHIBITED TRUNCATION"); - } - - if (shouldHavePeriod) Expected("."); - } - - private static void InitializeChoices(bool localExists = false, bool screenExists = false, bool workingExists = false) - { - if (CurrentEquals("LOCAL-STORAGE")) - { - if (localExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 134, """ - Initialize phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - A section can only be specified once in this phrase. - """) - .CloseError(); - } - localExists = true; - - Expected("LOCAL-STORAGE"); - - InitializeChoices(localExists, screenExists, workingExists); - - return; - } - - if (CurrentEquals("SCREEN")) - { - if (screenExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 134, """ - Initialize phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - A section can only be specified once in this phrase. - """) - .CloseError(); - } - screenExists = true; - - Expected("SCREEN"); - - InitializeChoices(localExists, screenExists, workingExists); - - return; - } - - if (CurrentEquals("WORKING-STORAGE")) - { - if (workingExists) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 134, """ - Initialize phrase, duplicate definition. - """) - .WithSourceLine(Current(), """ - A section can only be specified once in this phrase. - """) - .CloseError(); - } - workingExists = true; - - Expected("WORKING-STORAGE"); - - InitializeChoices(localExists, screenExists, workingExists); - - return; - } - - if (CurrentEquals("ALL")) - { - Expected("ALL"); - } - } - - - // The following methods are responsible for parsing the -ID paragraph. - // That includes the program, user-defined function, method, class, interface, factory or object identifier that should be specified right after. - // This is where SourceId and SourceTypeStack get their values for a COBOL source unit. - - private static void IdDefinitions() - { - if (CurrentEquals("CLASS-ID")) - { - ClassId(); - return; - } - - if (CurrentEquals("PROGRAM-ID")) - { - ProgramId(); - return; - } - - if (CurrentEquals("FUNCTION-ID")) - { - FunctionId(); - return; - } - - if (CurrentEquals("INTERFACE-ID")) - { - InterfaceId(); - return; - } - - if (CurrentEquals("METHOD-ID")) - { - MethodId(); - return; - } - - if (CurrentEquals("FACTORY")) - { - Factory(); - return; - } - - if (CurrentEquals("OBJECT")) - { - Object(); - return; - } - - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 85, """ - Missing source unit definition. - """) - .WithSourceLine(Current(), """ - Expected a source unit id definition. - """) - .WithNote(""" - The identification header is optional but every source unit must still have an ID. - """) - .CloseError(); - - AnchorPoint("OPTIONS ENVIRONMENT DATA PROCEDURE"); - } - - private static void ProgramId() - { - Expected("PROGRAM-ID"); - Expected("."); - - ActiveUnits.Push(Current()); - - SourceTypes.Push(UnitKind.Program); - - ActiveScope = SourceScope.ProgramId; - - References.GlobalName(false); - - if (CurrentEquals("AS")) - { - Expected("AS"); - - ActiveUnits.Pop(); - - Literals.String(); - - ActiveUnits.Push(Peek(-1)); - } - - if (CurrentEquals("IS COMMON INITIAL RECURSIVE PROTOTYPE")) - { - bool isCommon = false; - bool isInitial = false; - bool isPrototype = false; - bool isRecursive = false; - - Optional("IS"); - - while (CurrentEquals("COMMON INITIAL RECURSIVE PROTOTYPE")) - { - if (CurrentEquals("COMMON")) - { - Expected("COMMON"); - isCommon = true; - } - - if (CurrentEquals("INITIAL")) - { - Expected("INITIAL"); - isInitial = true; - } - - if (CurrentEquals("RECURSIVE")) - { - Expected("RECURSIVE"); - isRecursive = true; - } - - if (CurrentEquals("PROTOTYPE")) - { - Expected("PROTOTYPE"); - - SourceTypes.Pop(); - - SourceTypes.Push(UnitKind.ProgramPrototype); - - isPrototype = true; - } - } - - if (isPrototype && (isCommon || isInitial || isRecursive)) - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 55, """ - Invalid program prototype definition. - """) - .WithSourceLine(ActiveUnits.Peek(), """ - Program prototypes cannot be defined as common, initial or recursive. - """) - .CloseError(); - } - - if (isInitial && isRecursive) - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 55, """ - Invalid program definition. - """) - .WithSourceLine(ActiveUnits.Peek(), """ - Initial programs cannot be defined as recursive. - """) - .CloseError(); - } - - if (!isPrototype) Optional("PROGRAM"); - } - - if (!IsResolutionPass) - { - var signature = new CallableUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - ActiveNames.TryAdd(ActiveUnits.Peek(), signature); - - ActiveCallable = signature; - } - - if (IsResolutionPass) - { - ActiveCallable = ActiveNames.Fetch(ActiveUnits.Peek()); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Program definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every source unit definition must end with a separator period. - """) - .CloseError(); - - AnchorPoint("OPTION ENVIRONMENT DATA PROCEDURE"); - } - } - - private static void FunctionId() - { - Expected("FUNCTION-ID"); - Expected("."); - - SourceTypes.Push(UnitKind.Function); - - ActiveScope = SourceScope.FunctionId; - - References.Identifier(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - } - - if (CurrentEquals("IS PROTOTYPE")) - { - Optional("IS"); - Expected("PROTOTYPE"); - SourceTypes.Pop(); - SourceTypes.Push(UnitKind.FunctionPrototype); - } - - if (!IsResolutionPass) - { - var signature = new CallableUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - ActiveNames.TryAdd(ActiveUnits.Peek(), signature); - - ActiveCallable = signature; - } - - if (IsResolutionPass) - { - ActiveCallable = ActiveNames.Fetch(ActiveUnits.Peek()); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Function definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every source unit definition must end with a separator period. - """) - .CloseError(); - - AnchorPoint("OPTION ENVIRONMENT DATA PROCEDURE"); - } - } - - private static void ClassId() - { - Expected("CLASS-ID"); - Expected("."); - - ActiveUnits.Push(Current()); - - SourceTypes.Push(UnitKind.Class); - ActiveScope = SourceScope.ClassId; - - References.Identifier(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - } - - if (CurrentEquals("IS FINAL")) - { - Optional("IS"); - Expected("FINAL"); - } - - if (CurrentEquals("INHERITS")) - { - Expected("INHERITS"); - Optional("FROM"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 60, """ - Class definition, missing INHERITS class. - """) - .WithSourceLine(Peek(-1), """ - The INHERITS phrase must contain a class name. - """) - .CloseError(); - } - - References.Identifier(); - } - - if (CurrentEquals("USING")) - { - Expected("USING"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 60, """ - Class definition, missing using parameter. - """) - .WithSourceLine(Peek(-1), """ - The USING phrase must contain at least one parameter. - """) - .CloseError(); - } - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - } - - if (!IsResolutionPass) - { - var signature = new ClassUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - ActiveNames.TryAdd(ActiveUnits.Peek(), signature); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Class definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every source unit definition must end with a separator period. - """) - .CloseError(); - - AnchorPoint("OPTION ENVIRONMENT DATA FACTORY OBJECT"); - } - } - - private static void InterfaceId() - { - Expected("INTERFACE-ID"); - Expected("."); - - ActiveUnits.Push(Current()); - - SourceTypes.Push(UnitKind.Interface); - ActiveScope = SourceScope.InterfaceId; - - References.Identifier(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - } - - if (CurrentEquals("INHERITS")) - { - Expected("INHERITS"); - Optional("FROM"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 60, """ - Interface definition, missing INHERITS class. - """) - .WithSourceLine(Peek(-1), """ - The INHERITS phrase must contain at least one interface name. - """) - .CloseError(); - } - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - } - - if (CurrentEquals("USING")) - { - Expected("USING"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 60, """ - Interface definition, missing using parameter. - """) - .WithSourceLine(Peek(-1), """ - The USING phrase must contain at least one parameter. - """) - .CloseError(); - } - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - } - - if (!IsResolutionPass) - { - var signature = new InterfaceUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - ActiveNames.TryAdd(ActiveUnits.Peek(), signature); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Interface definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every source unit definition must end with a separator period. - """) - .CloseError(); - - AnchorPoint("OPTION ENVIRONMENT DATA PROCEDURE"); - } - } - - private static void MethodId() - { - if (SourceTypes.Peek() is not (UnitKind.Object or UnitKind.Factory or UnitKind.Interface)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 90, """ - Misplaced source unit definition. - """) - .WithSourceLine(Current(), """ - Method definitions can only be specified inside class or interface definitions. - """) - .CloseError(); - } - - Expected("METHOD-ID"); - Expected("."); - - ActiveScope = SourceScope.MethodId; - - if (SourceTypes.Peek() != UnitKind.Interface && CurrentEquals("GET")) - { - Expected("GET"); - Expected("PROPERTY"); - - ActiveUnits.Push(Current()); - SourceTypes.Push(UnitKind.MethodGetter); - - References.Identifier(); - - } - else if (SourceTypes.Peek() != UnitKind.Interface && CurrentEquals("SET")) - { - Expected("SET"); - Expected("PROPERTY"); - - ActiveUnits.Push(Current()); - SourceTypes.Push(UnitKind.MethodSetter); - - References.Identifier(); - } - else // If not a getter or a setter - { - ActiveUnits.Push(Current()); - - References.Identifier(); - - if (CurrentEquals("AS")) - { - Expected("AS"); - Literals.String(); - } - - if (SourceTypes.Peek() == UnitKind.Interface) - { - SourceTypes.Push(UnitKind.MethodPrototype); - } - else - { - SourceTypes.Push(UnitKind.Method); - } - } - - if (CurrentEquals("OVERRIDE")) Expected("OVERRIDE"); - - if (CurrentEquals("IS FINAL")) - { - Optional("IS"); - Expected("FINAL"); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Interface definition, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token. - """) - .WithNote(""" - Every source unit definition must end with a separator period. - """) - .CloseError(); - - AnchorPoint("OPTION ENVIRONMENT DATA PROCEDURE"); - } - - // We're returning during a resolution pass - if (IsResolutionPass) return; - - // Because we don't want to run this again during it: - if (SourceTypes.Peek() is UnitKind.Interface) - { - var parentInterface = ActiveNames.Fetch(ActiveUnits.Peek()); - - var methodPrototype = new CallableUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - parentInterface.Methods.Add(methodPrototype); - - ActiveCallable = methodPrototype; - } - - var parentClass = ActiveNames.Fetch(ActiveUnits.Peek()); - - var method = new CallableUnit(ActiveUnits.Peek(), SourceTypes.Peek()); - - if (SourceTypes.Peek() is UnitKind.Object) - { - parentClass.ObjectMethods.Add(method); - } - - if (SourceTypes.Peek() is UnitKind.Factory) - { - parentClass.FactoryMethods.Add(method); - } - - ActiveCallable = method; - } - - private static void Factory() - { - if (SourceTypes.Peek() is not UnitKind.Class) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 90, """ - Misplaced source unit definition. - """) - .WithSourceLine(Current(), """ - Factory definitions can only be specified inside class definitions. - """) - .CloseError(); - } - - Expected("FACTORY"); - Expected("."); - - SourceTypes.Push(UnitKind.Factory); - - if (CurrentEquals("IMPLEMENTS")) - { - Expected("IMPLEMENTS"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 95, """ - Missing implements interfaces. - """) - .WithSourceLine(Peek(-1), """ - The IMPLEMENTS phrase must contain at least one interface name. - """) - .CloseError(); - } - - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - Expected("."); - } - } - - private static void Object() - { - if (SourceTypes.Peek() is not UnitKind.Class) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 90, """ - Misplaced source unit definition. - """) - .WithSourceLine(Current(), """ - Object definitions can only be specified inside class definitions. - """) - .CloseError(); - } - - Expected("OBJECT"); - Expected("."); - - SourceTypes.Push(UnitKind.Object); - - if (CurrentEquals("IMPLEMENTS")) - { - Expected("IMPLEMENTS"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 95, """ - Missing implements interfaces. - """) - .WithSourceLine(Peek(-1), """ - The IMPLEMENTS phrase must contain at least one interface name. - """) - .CloseError(); - } - - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - Expected("."); - } - } -} diff --git a/Otterkit.Analyzers/src/Literals.cs b/Otterkit.Analyzers/src/Literals.cs deleted file mode 100644 index 72892159..00000000 --- a/Otterkit.Analyzers/src/Literals.cs +++ /dev/null @@ -1,162 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; -using System.Text; - -namespace Otterkit.Analyzers; - -public static class Literals -{ - public static bool IsAny() - { - return CurrentEquals(TokenType.Numeric | TokenType.String | TokenType.HexString | TokenType.Boolean | TokenType.HexBoolean | TokenType.National | TokenType.HexNational | TokenType.Figurative); - } - - public static bool PeekAny(int amount) - { - return PeekEquals(amount, TokenType.Numeric | TokenType.String | TokenType.HexString | TokenType.Boolean | TokenType.HexBoolean | TokenType.National | TokenType.HexNational | TokenType.Figurative); - } - - public static Option Any() - { - return Current().Type switch - { - TokenType.String or TokenType.HexString => String(), - TokenType.National or TokenType.HexNational => National(), - TokenType.Boolean or TokenType.HexBoolean => Boolean(), - TokenType.Numeric => Numeric(), - TokenType.Figurative => Figurative(), - - // Return empty Option if no literal is found. - _ => null - }; - } - - public static Option Numeric() - { - if (!CurrentEquals(TokenType.Numeric)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a numeric literal. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return Peek(-1); - } - - public static Option String() - { - if (!CurrentEquals(TokenType.String | TokenType.HexString)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected an alphanumeric literal. - """) - .CloseError(); - - Continue(); - - return null; - } - - var literal = Current(); - - // TODO: Also need to handle fixed continuation lines: - while (FloatingContinuationLine(Current().Value)) Continue(); - - Continue(); - - return literal; - } - - public static Option Boolean() - { - if (!CurrentEquals(TokenType.Boolean | TokenType.HexBoolean)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a boolean literal. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return Peek(-1); - } - - public static Option National() - { - if (!CurrentEquals(TokenType.National | TokenType.HexNational)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a national literal. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return Peek(-1); - } - - public static Option Figurative() - { - if (!CurrentEquals(TokenType.Figurative)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a figurative literal. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return Peek(-1); - } - - private static bool FloatingContinuationLine(ReadOnlySpan literal) - { - return literal switch - { - [.. _, '"' or '\'', '-'] => true, - [..] => false - }; - } -} diff --git a/Otterkit.Analyzers/src/PictureString.cs b/Otterkit.Analyzers/src/PictureString.cs deleted file mode 100644 index cd628aa0..00000000 --- a/Otterkit.Analyzers/src/PictureString.cs +++ /dev/null @@ -1,221 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static partial class DataDivision -{ - private static readonly HashSet SymbolsUsed = new(); - - public static int ParsePictureString(ReadOnlySpan picture) - { - const string invalidPictureMessage = "Invalid picture clause character string."; - - var isAfterDecimalPoint = false; - - var validPicture = true; - - var pictureLength = 0; - - for (var index = 0; index < picture.Length; index++) - { - var character = char.ToUpperInvariant(picture[index]); - - if (character is 'S' && !SymbolsUsed.IsEmpty()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbol 'S' must be the first symbol of the picture string. - """) - .CloseError(); - - validPicture = false; - } - - if(character is 'N' && SymbolsUsed.ContainsAny("9AXSVP1E")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbol 'N' must not follow any symbols other than 'N'. - """) - .CloseError(); - - validPicture = false; - } - - if(character is '1' && SymbolsUsed.ContainsAny("9AXSVPNE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbol '1' must not follow any symbols other than '1'. - """) - .CloseError(); - - validPicture = false; - } - - if(character is 'A' or 'X' && SymbolsUsed.ContainsAny("SVP1NE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbols 'A' and 'X' may only follow the symbols '9A' or 'X'. - """) - .CloseError(); - - validPicture = false; - } - - if (character is 'V' && SymbolsUsed.Contains('V')) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbol 'V' may only appear once in the same picture string. - """) - .CloseError(); - - validPicture = false; - } - - if (character is 'V' or 'P' && SymbolsUsed.ContainsAny("AX1NE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbols 'V' and 'P' must not follow the symbols 'AX1N' or 'E'. - """) - .CloseError(); - - validPicture = false; - } - - if (character is 'V' && !SymbolsUsed.Contains('V')) isAfterDecimalPoint = true; - - if (character is 'P' && SymbolsUsed.ContainsAny("9P") && isAfterDecimalPoint) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 20, invalidPictureMessage) - .WithSourceLine(Peek(-1)) - .WithNote(""" - Symbol 'P' or a string of 'P' may only appear once in a picture clause. - """) - .CloseError(); - - validPicture = false; - } - - if (character is 'P' && !SymbolsUsed.IsEmpty() && SymbolsUsed.Contains('9') && !isAfterDecimalPoint) - { - while (picture[index] is 'P' or 'p') - { - if (index >= picture.Length - 1) break; - - index++; - } - } - - if (character is 'P' && (SymbolsUsed.IsEmpty() || !SymbolsUsed.Contains('9') || isAfterDecimalPoint)) - { - while (picture[index] is 'P' or 'p') - { - if (index >= picture.Length - 1) break; - - index++; - } - - isAfterDecimalPoint = true; - } - - if (character is '(') - { - index++; - - var start = index; - - while (picture[index] != ')') - { - if (!picture[index].IsOneOf("0123456789")) - { - validPicture = false; - } - - index++; - } - - var end = index; - - var count = int.Parse(picture.Slice(start, end - start)); - - pictureLength += count - 1; - - continue; - } - - if (character.IsOneOf("9AXSVP1N")) - { - pictureLength++; - } - - SymbolsUsed.Add(character); - } - - if (validPicture) return pictureLength; - - return -1; - } - - private static (Classes, Categories) PictureType(bool validPicture) - { - if (!validPicture) - { - return (Classes.Invalid, Categories.Invalid); - } - - if (SymbolsUsed.Contains('N')) - { - return (Classes.National, Categories.National); - } - - if (SymbolsUsed.Contains('A') && !SymbolsUsed.ContainsAny("X9")) - { - return (Classes.Alphabetic, Categories.Alphabetic); - } - - if (SymbolsUsed.Contains('9') && !SymbolsUsed.ContainsAny("XA")) - { - return (Classes.Numeric, Categories.Numeric); - } - - if (SymbolsUsed.Contains('A') && SymbolsUsed.ContainsAny("X9")) - { - return (Classes.Alphanumeric, Categories.Alphanumeric); - } - - if (SymbolsUsed.Contains('X')) - { - return (Classes.Alphanumeric, Categories.Alphanumeric); - } - - if (SymbolsUsed.Contains('1')) - { - return (Classes.Boolean, Categories.Boolean); - } - - return (Classes.Invalid, Categories.Invalid); - } - - private static void ResetSymbols() - { - SymbolsUsed.Clear(); - } -} diff --git a/Otterkit.Analyzers/src/ProcedureDivision.cs b/Otterkit.Analyzers/src/ProcedureDivision.cs deleted file mode 100644 index 2d621416..00000000 --- a/Otterkit.Analyzers/src/ProcedureDivision.cs +++ /dev/null @@ -1,720 +0,0 @@ -using static Otterkit.Types.TokenHandling; - -using System.Diagnostics; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -/// -/// Otterkit COBOL Syntax and Semantic Analyzer -/// This parser was built to be easily extensible, with some reusable COBOL parts. -/// It requires a List of Tokens generated from the Lexer and the Token Classifier. -/// -public static class ProcedureDivision -{ - // Method responsible for parsing the PROCEDURE DIVISION. - // That includes the user-defined paragraphs, sections and declaratives - // or when parsing OOP COBOL code, it's responsible for parsing COBOL methods, objects and factories. - // It is also responsible for showing appropriate error messages when an error occurs in the PROCEDURE DIVISION. - public static void ParseProcedural() - { - Expected("PROCEDURE"); - Expected("DIVISION"); - - CompilerContext.ActiveScope = SourceScope.ProcedureDivision; - - var currentSource = CompilerContext.SourceTypes.Peek(); - - if (CurrentEquals("USING")) - { - Expected("USING"); - Using(); - } - - if (CompilerContext.SourceTypes.Peek() is UnitKind.Function or UnitKind.FunctionPrototype) - { - Expected("RETURNING"); - Returning(); - } - else if (CurrentEquals("RETURNING")) - { - Expected("RETURNING"); - Returning(); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Division header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every division header must end with a separator period - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - ProcedureBody(); - } - - // This method is part of the PROCEDURE DIVISION parsing. It's used to parse the "RETURNING" data item specified in - // the PROCEDURE DIVISION header. It's separate from the previous method because its code is needed more than once. - // COBOL user-defined functions should always return a data item. - - private static HashSet headerDataNames = new(); - - private static void Using() - { - while (CurrentEquals("BY REFERENCE VALUE") || CurrentEquals(TokenType.Identifier)) - { - while (CurrentEquals(TokenType.Identifier) || CurrentEquals("OPTIONAL")) - { - var isOptional = false; - - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - - isOptional = true; - } - - HandleHeaderDataName(true, isOptional, true); - } - - if (CurrentEquals("BY") && !PeekEquals(1, "VALUE REFERENCE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing word. - """) - .WithSourceLine(Current(), """ - Expected 'VALUE' or 'REFERENCE' after this token - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement, "RETURNING"); - } - - if (CurrentEquals("REFERENCE") || CurrentEquals("BY") && PeekEquals(1, "REFERENCE")) - { - Optional("BY"); - Expected("REFERENCE"); - - if (!CurrentEquals(TokenType.Identifier) && !PeekEquals(1, TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing identifier. - """) - .WithSourceLine(Peek(-1), """ - Must contain at least one data name. - """) - .CloseError(); - } - - while (CurrentEquals(TokenType.Identifier) || CurrentEquals("OPTIONAL")) - { - var isOptional = false; - - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - - isOptional = true; - } - - HandleHeaderDataName(true, isOptional, true); - } - } - - if (CurrentEquals("VALUE") || CurrentEquals("BY") && PeekEquals(1, "VALUE")) - { - Optional("BY"); - Expected("VALUE"); - - if (CurrentEquals("OPTIONAL")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase invalid optional. - """) - .WithSourceLine(Current(), """ - Items passed by value cannot be optional. - """) - .CloseError(); - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing identifier. - """) - .WithSourceLine(Peek(-1), """ - Must contain at least one data name. - """) - .CloseError(); - } - - while (CurrentEquals(TokenType.Identifier)) - { - HandleHeaderDataName(true, false, false); - } - } - } - } - - private static void Returning() - { - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 75, """ - Missing returning data item. - """) - .WithSourceLine(Peek(-1), $""" - Missing returning identifier after this token. - """) - .CloseError(); - return; - } - - HandleHeaderDataName(false); - } - - // The syntax, semantics and errors for the formal parameters and - // for the returning item are exactly the same, so we handle it - // in a sigle method to avoid code duplication. - private static void HandleHeaderDataName(bool isParameter, bool isOptional = false, bool isByRef = false) - { - var dataName = References.LocalName(); - - // Don't resolve if it's not a resolution pass. - if (!CompilerContext.IsResolutionPass) return; - - // Error has been handled in the above Name() call. - if (!dataName.Exists) return; - - var dataToken = dataName.Unwrap(); - - // Uniqueness has not been handled above, - // so we handle it here. - if (!dataName.Unique && !CurrentEquals("IN OF")) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to non-unique identifier. - """) - .WithSourceLine(dataToken, """ - Must have a unique name. - """) - .WithNote(""" - It must be a unique 77 or 01 level item. - """) - .CloseError(); - return; - } - - // COBOL standard requirement, data-name doesn't have - // a name qualification syntax. Only identifiers do. - if (CurrentEquals("IN OF")) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 1200, """ - Name qualification prohibited. - """) - .WithSourceLine(dataToken, """ - Must not require qualification. - """) - .WithNote(""" - It must be a unique 77 or 01 level item. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement, "RAISING"); - return; - } - - // COBOL standard requirement, data-name used for - // the returning item must not be the same of a parameter. - if (headerDataNames.Contains(dataToken.Value)) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 1210, """ - Name conflict with a formal parameter. - """) - .WithSourceLine(dataToken, - isParameter - ? "Must not be the same as a parameter name." - : "Must not be the same as another parameter name." - ) - .CloseError(); - return; - } - - var dataItem = References.FetchDataEntry(dataToken); - - // COBOL standard requirement, all parameters and returning items - // must be defined in the linkage section only. - if (dataItem.Section is not SourceScope.LinkageSection) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 2050, - isParameter - ? "Invalid parameter definition." - : "Invalid returning definition." - ) - .WithSourceLine(dataToken, """ - Must be defined in the linkage section. - """) - .CloseError(); - } - - // COBOL standard requirement, must be 01 or 77. - if (dataItem.LevelNumber is not (1 or 77)) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 2050, - isParameter - ? "Invalid parameter level number." - : "Invalid returning level number." - ) - .WithSourceLine(dataToken, """ - Must be a 77 or 01 level item. - """) - .CloseError(); - } - - // COBOL standard requirement, must not contain a BASED or REDEFINES clause. - if (dataItem[DataClause.Based] || dataItem[DataClause.Redefines]) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 2050, - isParameter - ? "Invalid parameter clauses." - : "Invalid returning clauses." - ) - .WithSourceLine(dataToken, """ - Must not contain a BASED or REDEFINES clause. - """) - .CloseError(); - } - - // COBOL standard requirement, parameters passed by value must - // have a class of numeric, message tag, object or pointer - if (isParameter && !isByRef && !CheckByValueClass(dataItem.Class)) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 2050, """ - Invalid by value parameter class. - """) - .WithSourceLine(dataToken, """ - Must be of class Numeric, Message Tag, Object or Pointer. - """) - .CloseError(); - } - - headerDataNames.Add(dataToken.Value); - - var activeCallable = CompilerContext.ActiveCallable; - - if (isParameter) - { - var parameter = (dataItem, isOptional, isByRef); - - activeCallable.Parameters.Add(parameter); - return; - } - - activeCallable.Returning = dataItem; - } - - private static bool CheckByValueClass(Classes _class) - { - return _class is Classes.Numeric or Classes.MessageTag or Classes.Object or Classes.Pointer; - } - - private static void ProcedureBody() - { - var currentSource = CompilerContext.SourceTypes.Peek(); - - bool isProcedureDeclarative = CurrentEquals("DECLARATIVES") - || CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION"); - - bool canContainStatements = currentSource switch - { - UnitKind.FunctionPrototype => false, - UnitKind.ProgramPrototype => false, - UnitKind.MethodPrototype => false, - _ => true - }; - - if (canContainStatements && !isProcedureDeclarative) Statements.WithoutSections(); - - if (canContainStatements && isProcedureDeclarative) Statements.WithSections(); - - if (!canContainStatements && (CurrentEquals(TokenContext.IsStatement) || CurrentEquals(TokenType.Identifier))) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 205, """ - Misplaced statement definition. - """) - .WithSourceLine(Current(), """ - A statement cannot be defined here. - """) - .WithNote(""" - Prototypes must not contain any statements, sections or paragraphs. - """) - .CloseError(); - - AnchorPoint("END IDENTIFICATION PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID"); - } - } - - public static void EndMarker() - { - var currentType = CompilerContext.SourceTypes.Peek(); - - if (currentType != UnitKind.Program && !CurrentEquals("END") || currentType == UnitKind.Program && (!CurrentEquals(TokenType.EOF) && !CurrentEquals("END"))) - { - string errorMessageChoice = currentType switch - { - UnitKind.Program or UnitKind.ProgramPrototype => """ - Missing END PROGRAM marker. - """, - - UnitKind.Function or UnitKind.FunctionPrototype => """ - Missing END FUNCTION marker. - """, - - UnitKind.Method or UnitKind.MethodPrototype or UnitKind.MethodGetter or UnitKind.MethodSetter => """ - Missing END METHOD marker. - """, - - UnitKind.Class => """ - Missing END CLASS marker. - """, - - UnitKind.Interface => """ - Missing END INTERFACE marker. - """, - - UnitKind.Factory => """ - Missing END FACTORY marker. - """, - - UnitKind.Object => """ - Missing END OBJECT marker. - """, - - _ => throw new UnreachableException() - }; - - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 27, $""" - End marker, {errorMessageChoice} - """) - .WithSourceLine(Peek(-1), """ - Expected a source unit end marker after this token - """) - .CloseError(); - - return; - } - - if (currentType == UnitKind.Program && CurrentEquals("EOF")) - { - CompilerContext.SourceTypes.Pop(); - return; - } - - CompilerContext.SourceTypes.Pop(); - - var endMarkerToken = CompilerContext.ActiveUnits.Pop(); - - switch (currentType) - { - case UnitKind.Program: - case UnitKind.ProgramPrototype: - - Expected("END"); - Expected("PROGRAM"); - - EndMarkerErrorHandling(endMarkerToken); - break; - - case UnitKind.Function: - case UnitKind.FunctionPrototype: - Expected("END"); - Expected("FUNCTION"); - - EndMarkerErrorHandling(endMarkerToken); - break; - - case UnitKind.Method: - case UnitKind.MethodPrototype: - case UnitKind.MethodGetter: - case UnitKind.MethodSetter: - Expected("END"); - Expected("METHOD"); - - if (currentType is UnitKind.Method or UnitKind.MethodPrototype) - { - References.Identifier(endMarkerToken); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - End marker, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every end marker must end with a separator period - """) - .CloseError(); - - AnchorPoint("IDENTIFICATION METHOD-ID PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID"); - } - - break; - - case UnitKind.Class: - Expected("END"); - Expected("CLASS"); - - EndMarkerErrorHandling(endMarkerToken); - break; - - case UnitKind.Interface: - Expected("END"); - Expected("INTERFACE"); - - EndMarkerErrorHandling(endMarkerToken); - break; - - case UnitKind.Factory: - Expected("END"); - Expected("FACTORY"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - End marker, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every end marker must end with a separator period - """) - .CloseError(); - - AnchorPoint("OBJECT IDENTIFICATION PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID"); - } - - break; - - case UnitKind.Object: - Expected("END"); - Expected("OBJECT"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 26, """ - End marker, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every end marker must end with a separator period - """) - .CloseError(); - - AnchorPoint("OBJECT IDENTIFICATION PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID"); - } - - break; - } - } - - private static void EndMarkerErrorHandling(Token token) - { - if (!References.Identifier(token, false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2, """ - Unexpected user-defined name. - """) - .WithSourceLine(Current(), $""" - Expected the following identifier: {token.Value}. - """) - .WithSourceNote(token) - .WithNote(""" - The end marker must match its source unit definition. - """) - .CloseError(); - - Continue(); - } - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - End marker, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every end marker must end with a separator period - """) - .CloseError(); - - AnchorPoint("IDENTIFICATION OBJECT METHOD-ID PROGRAM-ID FUNCTION-ID CLASS-ID INTERFACE-ID"); - } - } - - public static void ParseObjects() - { - if (CurrentEquals("FACTORY") || CurrentEquals("IDENTIFICATION") && PeekEquals(3, "FACTORY")) - { - IdentificationDivision.Parse(); - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - Expected("PROCEDURE"); - Expected("DIVISION"); - Expected("."); - - while (CurrentEquals("METHOD-ID") || CurrentEquals("IDENTIFICATION") && PeekEquals(3, "METHOD-ID")) - { - IdentificationDivision.Parse(); - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - ParseProcedural(); - - EndMarker(); - } - - EndMarker(); - } - - if (CurrentEquals("OBJECT") || CurrentEquals("IDENTIFICATION") && PeekEquals(3, "OBJECT")) - { - IdentificationDivision.Parse(); - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - Expected("PROCEDURE"); - Expected("DIVISION"); - Expected("."); - - while (CurrentEquals("METHOD-ID") || (CurrentEquals("IDENTIFICATION") && PeekEquals(3, "METHOD-ID"))) - { - IdentificationDivision.Parse(); - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - ParseProcedural(); - - EndMarker(); - } - - EndMarker(); - } - } - - public static void ParseInterface() - { - if (CurrentEquals("PROCEDURE")) - { - Expected("PROCEDURE"); - Expected("DIVISION"); - - if (!Expected(".", false)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 25, """ - Division header, missing separator period. - """) - .WithSourceLine(Peek(-1), """ - Expected a separator period '. ' after this token - """) - .WithNote(""" - Every division header must end with a separator period - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - while (CurrentEquals("METHOD-ID") || CurrentEquals("IDENTIFICATION") && PeekEquals(3, "METHOD-ID")) - { - IdentificationDivision.Parse(); - - if (CurrentEquals("ENVIRONMENT")) - { - EnvironmentDivision.Parse(); - } - - if (CurrentEquals("DATA")) - { - DataDivision.Parse(); - } - - if (CurrentEquals("PROCEDURE")) - { - ParseProcedural(); - } - - EndMarker(); - } - } - } -} diff --git a/Otterkit.Analyzers/src/References.cs b/Otterkit.Analyzers/src/References.cs deleted file mode 100644 index 553acaf5..00000000 --- a/Otterkit.Analyzers/src/References.cs +++ /dev/null @@ -1,856 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using static Otterkit.Types.CompilerContext; -using Otterkit.Types; -using System.Diagnostics; - -namespace Otterkit.Analyzers; - -public static partial class References -{ - private static Stack Qualification = new(); - - public static bool HasFlag(Enum type, Enum flag) - => type.HasFlag(flag); - - public static bool IsSameName(Token token) - { - var name = ActiveNames.Fetch(token); - - var originalToken = name.Identifier; - - return originalToken.SamePosition(token); - } - - private static bool CheckParent(Token entry, Token parent) - { - var entries = ActiveData.FetchList(entry); - - foreach (var item in entries) - { - if (!item.Parent.Exists) - { - continue; - } - - var parentEntry = item.Parent.Unwrap(); - - if (!parentEntry.Identifier.Exists) - { - continue; - } - - var parentToken = parentEntry.Identifier.Unwrap(); - - if (parentToken.Value == parent.Value) - { - Qualification.Push(parentToken); - - return true; - } - } - - return false; - } - - private static Token FindSubordinate(Token qualified, Token subordinate) - { - var entries = ActiveData.FetchList(subordinate); - - foreach (var item in entries) - { - if (!item.Parent.Exists) - { - continue; - } - - var parentEntry = item.Parent.Unwrap(); - - if (!parentEntry.Identifier.Exists) - { - continue; - } - - var parentToken = parentEntry.Identifier.Unwrap(); - - if (parentToken.Line == qualified.Line && parentToken.Column == qualified.Column) - { - return item.Identifier.Unwrap(); - } - } - - throw new UnreachableException($"Unable to find the subordinate token qualified by {qualified}."); - } - - private static Token FindFullyQualified() - { - var qualified = Qualification.Pop(); - - foreach (var subordinate in Qualification) - { - qualified = FindSubordinate(qualified, subordinate); - } - - return qualified; - } - - public static Option LocalDefinition() - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - return null; - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a user-defined word (an identifier). - """) - .CloseError(); - - Continue(); - - return null; - } - - var definition = Current(); - - Continue(); - - return definition; - } - - public static Name LocalName(bool shouldResolve = true) - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - return null; - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a user-defined word (an identifier). - """) - .CloseError(); - - Continue(); - - return null; - } - - if (!IsResolutionPass || !shouldResolve) - { - Continue(); - return null; - } - - var nameToken = Current(); - - var (exists, unique) = ActiveData.HasUnique(nameToken); - - if (!exists) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to undefined identifier. - """) - .WithSourceLine(Current(), $""" - Name does not exist in the current context. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return (nameToken, unique); - } - - public static Name Qualified(TokenContext anchorPoint = TokenContext.IsStatement) - { - if (!IsResolutionPass) - { - LocalName(); - - while (CurrentEquals("IN OF")) - { - Choice("IN OF"); - - LocalName(); - } - - return null; - } - - var name = LocalName(); - - if (!name.Exists) - { - AnchorPoint(anchorPoint); - - return null; - } - - var nameToken = name.Unwrap(); - - if (!name.Unique && !CurrentEquals("IN OF")) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to non-unique identifier. - """) - .WithSourceLine(nameToken, $""" - Name requires qualification. - """) - .CloseError(); - - return null; - } - - Qualification.Push(nameToken); - - while (CurrentEquals("IN OF")) - { - Choice("IN OF"); - - var parent = LocalName(); - - if (!parent.Exists) continue; - - var parentToken = parent.Unwrap(); - - var isParent = CheckParent(nameToken, parentToken); - - if (!isParent) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to incorrect superordinate. - """) - .WithSourceLine(parentToken, $""" - Name does not have a {nameToken.Value} field. - """) - .CloseError(); - } - - if (!parent.Unique && !CurrentEquals("IN OF")) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to non-unique identifier. - """) - .WithSourceLine(parentToken, $""" - Name requires qualification. - """) - .CloseError(); - - return null; - } - - nameToken = parentToken; - } - - var fullyQualified = FindFullyQualified(); - - Qualification.Clear(); - - return fullyQualified; - } - - public static DataEntry FetchDataEntry(Token qualifiedToken) - { - var entries = ActiveData.FetchList(qualifiedToken); - - foreach (var entry in entries) - { - if (entry.Identifier == qualifiedToken) - { - return entry; - } - } - - throw new ArgumentException("Token was not qualified. Could not resolve data item", nameof(qualifiedToken)); - } - - public static void Identifier(Identifiers allowed = Identifiers.None) - { - // TODO: - // All Identifiers here need a check from the symbol table. - // The symbol table itself needs to be refactored to accommodate this. - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - return; - } - - if (CurrentEquals("FUNCTION")) - { - Expected("FUNCTION"); - if (!HasFlag(allowed, Identifiers.Function)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected function identifier. - """) - .WithSourceLine(Current(), $""" - This function call should not be here. - """) - .WithNote(""" - Function calls must not be used as receiving operands - """) - .CloseError(); - } - - Continue(); - if (CurrentEquals("(")) - { - // TODO: - // This needs a check from the symbol table to verify the number and type - // of the function's parameters. - Expected("("); - while (!CurrentEquals(")")) Continue(); - Expected(")"); - } - - return; - } - - if (CurrentEquals("EXCEPTION-OBJECT")) - { - Expected("EXCEPTION-OBJECT"); - if (!HasFlag(allowed, Identifiers.ExceptionObject)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected EXCEPTION-OBJECT identifier. - """) - .WithSourceLine(Current(), $""" - This EXCEPTION-OBJECT should not be here. - """) - .WithNote(""" - EXCEPTION-OBJECT must not be used as receiving operand - """) - .CloseError(); - } - - return; - } - - if (CurrentEquals("SELF")) - { - Expected("SELF"); - if (!HasFlag(allowed, Identifiers.Self)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected SELF identifier. - """) - .WithSourceLine(Current(), $""" - This SELF should not be here. - """) - .WithNote(""" - SELF must not be used as receiving operand - """) - .CloseError(); - } - - return; - } - - if (CurrentEquals("NULL")) - { - Expected("NULL"); - if (!HasFlag(allowed, Identifiers.NullAddress) && !HasFlag(allowed, Identifiers.NullObject)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected NULL identifier. - """) - .WithSourceLine(Current(), $""" - This NULL reference should not be here. - """) - .WithNote(""" - NULL must not be used as receiving operand - """) - .CloseError(); - } - - return; - } - - if (CurrentEquals("ADDRESS") && !PeekEquals(1, "PROGRAM FUNCTION") && !PeekEquals(2, "PROGRAM FUNCTION")) - { - Expected("ADDRESS"); - Optional("OF"); - if (!HasFlag(allowed, Identifiers.DataAddress)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected ADDRESS OF identifier. - """) - .WithSourceLine(Current(), $""" - This ADDRESS OF reference should not be here. - """) - .WithNote(""" - ADDRESS OF must not be used as receiving operand - """) - .CloseError(); - } - - Continue(); - return; - } - - if (CurrentEquals("ADDRESS") && PeekEquals(1, "FUNCTION") || PeekEquals(2, "FUNCTION")) - { - Expected("ADDRESS"); - Optional("OF"); - Expected("FUNCTION"); - if (!HasFlag(allowed, Identifiers.FunctionAddress)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected ADDRESS OF FUNCTION identifier. - """) - .WithSourceLine(Current(), $""" - This ADDRESS OF FUNCTION should not be here. - """) - .WithNote(""" - ADDRESS OF FUNCTION must not be used as receiving operand - """) - .CloseError(); - } - - if (CurrentEquals(TokenType.Identifier)) - { - Continue(); - } - else - { - Literals.String(); - } - - return; - } - - if (CurrentEquals("ADDRESS") && PeekEquals(1, "PROGRAM") || PeekEquals(2, "PROGRAM")) - { - Expected("ADDRESS"); - Optional("OF"); - Expected("PROGRAM"); - if (!HasFlag(allowed, Identifiers.ProgramAddress)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected ADDRESS OF PROGRAM identifier. - """) - .WithSourceLine(Current(), $""" - This ADDRESS OF PROGRAM should not be here. - """) - .WithNote(""" - ADDRESS OF PROGRAM must not be used as receiving operand - """) - .CloseError(); - } - - if (CurrentEquals(TokenType.Identifier)) - { - Continue(); - } - else - { - Literals.String(); - } - - return; - } - - if (CurrentEquals("LINAGE-COUNTER")) - { - Expected("LINAGE-COUNTER"); - Choice("IN OF"); - if (!HasFlag(allowed, Identifiers.LinageCounter)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected LINAGE-COUNTER identifier. - """) - .WithSourceLine(Current(), $""" - This LINAGE-COUNTER should not be here. - """) - .WithNote(""" - LINAGE-COUNTER must not be used as receiving operand - """) - .CloseError(); - } - - Continue(); - return; - } - - if (CurrentEquals("PAGE-COUNTER LINE-COUNTER")) - { - var token = Current(); - - Choice("PAGE-COUNTER LINE-COUNTER"); - Choice("IN OF"); - - if (!HasFlag(allowed, Identifiers.ReportCounter)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, $""" - Unexpected {token.Value} identifier. - """) - .WithSourceLine(Current(), $""" - This {token.Value} should not be here. - """) - .WithNote($""" - {token.Value} must not be used as receiving operand - """) - .CloseError(); - } - - Continue(); - return; - } - - if (PeekEquals(1, "AS")) - { - // var isFactory = false; - // var isStronglyTyped = false; - - // Need to implement identifier resolution first - // To parse the rest of this identifier correctly - // and to add extra compile time checks - - Continue(); - Expected("AS"); - - if (!HasFlag(allowed, Identifiers.ObjectView)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected Object View identifier. - """) - .WithSourceLine(Current(), $""" - This Object View should not be here. - """) - .WithNote(""" - Object View must not be used as receiving operand - """) - .CloseError(); - } - - if (CurrentEquals("UNIVERSAL")) - { - Expected("UNIVERSAL"); - return; - } - - if (CurrentEquals("Factory")) - { - Expected("FACTORY"); - Optional("OF"); - // isFactory = true; - } - - Continue(); - - if (CurrentEquals("ONLY")) - { - Expected("ONLY"); - // isStronglyTyped = true - } - - return; - } - - if (PeekEquals(1, "::")) - { - - - if (!HasFlag(allowed, Identifiers.MethodInvocation)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 15, """ - Unexpected inline method call. - """) - .WithSourceLine(Current(), $""" - This method call should not be here. - """) - .WithNote(""" - Inline method calls must not be used as receiving operand - """) - .CloseError(); - } - - // TODO: Replace Continue with an identifier check for the method name - Continue(); - Expected("::"); - Literals.String(); - - if (CurrentEquals("(")) - { - // TODO: - // This needs a check from the symbol table to verify the number and type - // of the function's parameters. - Expected("("); - while (!CurrentEquals(")")) Continue(); - Expected(")"); - } - - return; - } - - Continue(); - - if (CurrentEquals("(")) - { - // TODO: - // This needs a check from the symbol table - // to verify the identifier type. - Expected("("); - while (!CurrentEquals(")")) Continue(); - Expected(")"); - } - } - - public static bool Identifier(Token identifierToken, bool useDefaultError = true) - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - // Error has already been handled above - return true; - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a user-defined word (an identifier). - """) - .CloseError(); - - Continue(); - - // Error has already been handled above - return true; - } - - var isExpectedToken = CurrentEquals(identifierToken.Value); - - if (!isExpectedToken && useDefaultError) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 2, """ - Unexpected user-defined name. - """) - .WithSourceLine(Current(), $""" - Expected the following identifier: {identifierToken.Value}. - """) - .CloseError(); - - // Error has already been handled above - // Handled using a default error message - return true; - } - - if (!isExpectedToken && !useDefaultError) - { - // Error has not been handled - // Expected to be handled by the consumer - // of this method using an if statement - return false; - } - - Continue(); - - return true; - } - - public static Option GlobalName(bool shouldExist, bool shouldResolve = true) - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - return null; - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected a user-defined word (an identifier). - """) - .CloseError(); - - Continue(); - - return null; - } - - if (!IsResolutionPass || !shouldResolve) - { - Continue(); - return null; - } - - var nameToken = Current(); - - var exists = ActiveNames.Exists(nameToken); - - if (!exists && shouldExist) - { - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Reference to undefined identifier. - """) - .WithSourceLine(Current(), $""" - Name does not exist in the current codebase. - """) - .CloseError(); - - Continue(); - - return null; - } - - if (exists && !shouldExist && IsSameName(nameToken)) - { - Continue(); - - return nameToken; - } - - if (exists && !shouldExist) - { - var original = ActiveNames.Fetch(nameToken); - - ErrorHandler - .Build(ErrorType.Resolution, ConsoleColor.Red, 15, """ - Duplicate global name definition. - """) - .WithSourceLine(Current(), $""" - Already defined in this codebase. - """) - .WithSourceNote(original.Identifier) - .WithNote(""" - The original name was defined here. - """) - .CloseError(); - - Continue(); - - return null; - } - - Continue(); - - return nameToken; - } - - public static Option IntrinsicName() - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected an identifier after this token. - """) - .CloseError(); - - return null; - } - - if (!CurrentEquals(TokenType.IntrinsicFunction) && !CurrentEquals("RANDOM")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 1, """ - Unexpected token type. - """) - .WithSourceLine(Current(), $""" - Expected an intrinsic function name. - """) - .CloseError(); - - Continue(); - - return null; - } - - if (!IsResolutionPass) - { - Continue(); - return null; - } - - var nameToken = Current(); - - Continue(); - - return nameToken; - } -} diff --git a/Otterkit.Analyzers/src/Statements.cs b/Otterkit.Analyzers/src/Statements.cs deleted file mode 100644 index 0c38af89..00000000 --- a/Otterkit.Analyzers/src/Statements.cs +++ /dev/null @@ -1,3514 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.Analyzers; - -public static class Statements -{ - // Analyzer Statement methods. - // These are the methods used to parse and analyze all Standard COBOL statements. - // All of these methods are responsible *ONLY* for statements, paragraphs and sections inside the procedure division. - // There shouldn't be any identification, environment or data division methods here. - public static void WithoutSections(bool isNested = false) - { - bool errorCheck = Current().Context != TokenContext.IsStatement - && !(CurrentEquals(TokenType.Identifier) && PeekEquals(1, ".") && !isNested) - && !(CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION") && !isNested); - - if (errorCheck) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected start of a statement. Instead found {Current().Value}. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - if (isNested) - { - NestedStatementLoop(); - - return; - } - - NonNestedStatementLoop(); - } - - private static void NestedStatementLoop() - { - while (CurrentEquals(TokenContext.IsStatement)) - { - Statement(true); - - ScopeTerminator(true); - - if (!CurrentEquals(TokenContext.IsStatement)) break; - - if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION")) break; - } - } - - private static void NonNestedStatementLoop() - { - while (!CurrentEquals("EOF END") && !(CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION"))) - { - Statement(false); - - ScopeTerminator(false); - - if (PeekEquals(-1, ".") && CurrentEquals(TokenType.Identifier) && PeekEquals(1, ".")) continue; - - if (!CurrentEquals(TokenContext.IsStatement)) break; - - if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION")) break; - } - } - - public static void WithSections() - { - if (CurrentEquals("DECLARATIVES")) - { - Expected("DECLARATIVES"); - Expected("."); - - References.Identifier(); - Expected("SECTION"); - Expected("."); - UseStatement(); - Statements.WithoutSections(); - - while (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION")) - { - References.Identifier(); - Expected("SECTION"); - Expected("."); - UseStatement(); - Statements.WithoutSections(); - } - - Expected("END"); - Expected("DECLARATIVES"); - Expected("."); - } - - while (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "SECTION")) - { - References.Identifier(); - Expected("SECTION"); - Expected("."); - Statements.WithoutSections(); - } - } - - private static void Statement(bool isNested = false) - { - if (CurrentEquals("ACCEPT")) - AcceptStatement(); - - else if (CurrentEquals("ADD")) - AddStatement(); - - else if (CurrentEquals("ALLOCATE")) - AllocateStatement(); - - else if (CurrentEquals("CALL")) - CallStatement(); - - else if (CurrentEquals("CANCEL")) - CancelStatement(); - - else if (CurrentEquals("CLOSE")) - CloseStatement(); - - else if (CurrentEquals("COMMIT")) - CommitStatement(); - - else if (CurrentEquals("CONTINUE")) - ContinueStatement(); - - else if (CurrentEquals("COMPUTE")) - ComputeStatement(); - - else if (CurrentEquals("DISPLAY")) - DisplayStatement(); - - else if (CurrentEquals("DIVIDE")) - DivideStatement(); - - else if (CurrentEquals("DELETE")) - DeleteStatement(); - - else if (CurrentEquals("IF")) - IfStatement(); - - else if (CurrentEquals("INITIALIZE")) - InitializeStatement(); - - else if (CurrentEquals("INITIATE")) - InitiateStatement(); - - else if (CurrentEquals("INSPECT")) - InspectStatement(); - - else if (CurrentEquals("INVOKE")) - InvokeStatement(); - - else if (CurrentEquals("MERGE")) - MergeStatement(); - - else if (CurrentEquals("MULTIPLY")) - MultiplyStatement(); - - else if (CurrentEquals("MOVE")) - MoveStatement(); - - else if (CurrentEquals("OPEN")) - OpenStatement(); - - else if (CurrentEquals("EXIT")) - ExitStatement(); - - else if (CurrentEquals("EVALUATE")) - EvaluateStatement(); - - else if (CurrentEquals("FREE")) - FreeStatement(); - - else if (CurrentEquals("GENERATE")) - GenerateStatement(); - - else if (CurrentEquals("GO")) - GoStatement(); - - else if (CurrentEquals("GOBACK")) - GobackStatement(); - - else if (CurrentEquals("SUBTRACT")) - SubtractStatement(); - - else if (CurrentEquals("PERFORM")) - PerformStatement(); - - else if (CurrentEquals("RELEASE")) - ReleaseStatement(); - - else if (CurrentEquals("RAISE")) - RaiseStatement(); - - else if (CurrentEquals("READ")) - ReadStatement(); - - else if (CurrentEquals("RECEIVE")) - ReceiveStatement(); - - else if (CurrentEquals("RESUME")) - ResumeStatement(); - - else if (CurrentEquals("RETURN")) - ReturnStatement(); - - else if (CurrentEquals("REWRITE")) - RewriteStatement(); - - else if (CurrentEquals("ROLLBACK")) - RollbackStatement(); - - else if (CurrentEquals("SEARCH")) - SearchStatement(); - - else if (CurrentEquals("SEND")) - SendStatement(); - - else if (CurrentEquals("SET")) - SetStatement(); - - else if (CurrentEquals("SORT")) - SortStatement(); - - else if (CurrentEquals("START")) - StartStatement(); - - else if (CurrentEquals("STOP")) - StopStatement(); - - else if (CurrentEquals("STRING")) - StringStatement(); - - else if (CurrentEquals("SUPPRESS")) - SuppressStatement(); - - else if (CurrentEquals("TERMINATE")) - TerminateStatement(); - - else if (CurrentEquals("UNLOCK")) - UnlockStatement(); - - else if (CurrentEquals("UNSTRING")) - UnstringStatement(); - - else if (CurrentEquals("VALIDATE")) - ValidateStatement(); - - else if (CurrentEquals("WRITE")) - WriteStatement(); - - else if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, ".") && !isNested) - ParseParagraph(); - } - - // Statement parsing methods - // All the following uppercased methods are responsible for parsing a single COBOL statement - // When a new method is added here to parse a new statement, we need to add it to the Statement() method as well. - // Adding extra statements to the parser only requires a new method here, and an if statement added to the Statement() method - private static void UseStatement() - { - Expected("USE"); - - bool exceptionObject = CurrentEquals("AFTER") && PeekEquals(1, "EXCEPTION") && PeekEquals(2, "OBJECT") - || CurrentEquals("AFTER") && PeekEquals(1, "EO") - || CurrentEquals("EXCEPTION") && PeekEquals(1, "OBJECT") - || CurrentEquals("EO"); - - bool exceptionCondition = CurrentEquals("AFTER") && PeekEquals(1, "EXCEPTION") && PeekEquals(2, "CONDITION") - || CurrentEquals("AFTER") && PeekEquals(1, "EC") - || CurrentEquals("EXCEPTION") && PeekEquals(1, "CONDITION") - || CurrentEquals("EC"); - - bool reporting = CurrentEquals("GLOBAL") && PeekEquals(1, "BEFORE") || CurrentEquals("BEFORE"); - - bool fileException = CurrentEquals("GLOBAL") && PeekEquals(1, "AFTER STANDARD EXCEPTION ERROR") - || CurrentEquals("AFTER STANDARD EXCEPTION ERROR"); - - if (exceptionObject) - { - Optional("AFTER"); - if (CurrentEquals("EO")) - { - Expected("EO"); - } - else - { - Expected("EXCEPTION"); - Expected("OBJECT"); - } - - References.Identifier(); - } - else if (exceptionCondition) - { - Optional("AFTER"); - if (CurrentEquals("EO")) - { - Expected("EO"); - } - else - { - Expected("EXCEPTION"); - Expected("OBJECT"); - } - - References.Identifier(); - } - else if (reporting) - { - if (CurrentEquals("GLOBAL")) Expected("GLOBAL"); - - Expected("BEFORE"); - Expected("REPORTING"); - References.Identifier(); - } - else if (fileException) - { - if (CurrentEquals("GLOBAL")) Expected("GLOBAL"); - - Optional("AFTER"); - Optional("STANDARD"); - Choice("EXCEPTION ERROR"); - Optional("PROCEDURE"); - Optional("ON"); - - if (CurrentEquals("INPUT OUTPUT I-O EXTEND")) - { - Choice("INPUT OUTPUT I-O EXTEND"); - } - else - { - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - } - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected AFTER EXCEPTION OBJECT, AFTER EXCEPTION CONDITION, BEFORE REPORTING or AFTER EXCEPTION/ERROR. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - ScopeTerminator(false); - } - - private static void DisplayStatement() - { - Expected("DISPLAY"); - - if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "AT LINE COLUMN COL")) - { - bool isConditional = false; - - References.Identifier(); - Optional("AT"); - Common.LineColumn(); - Common.OnException(ref isConditional); - - if (isConditional) Expected("END-COMPUTE"); - return; - } - - if (Common.NotIdentifierOrLiteral()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or a literal. - """) - .CloseError(); - - AnchorPoint("UPON WITH NO"); - } - - switch (Current().Type) - { - case TokenType.Identifier: References.Qualified(); break; - case TokenType.Numeric: Literals.Numeric(); break; - - case TokenType.String: - case TokenType.HexString: - case TokenType.Boolean: - case TokenType.HexBoolean: - case TokenType.National: - case TokenType.HexNational: - Literals.String(); break; - } - - while (Common.IdentifierOrLiteral()) - { - switch (Current().Type) - { - case TokenType.Identifier: References.Qualified(); break; - case TokenType.Numeric: Literals.Numeric(); break; - - case TokenType.String: - case TokenType.HexString: - case TokenType.Boolean: - case TokenType.HexBoolean: - case TokenType.National: - case TokenType.HexNational: - Literals.String(); break; - } - } - - if (CurrentEquals("UPON")) - { - Expected("UPON"); - Choice("STANDARD-OUTPUT STANDARD-ERROR"); - } - - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("ADVANCING"); - } - - Optional("END-DISPLAY"); - } - - private static void AcceptStatement() - { - bool isConditional = false; - - Expected("ACCEPT"); - References.Identifier(); - if (CurrentEquals("FROM")) - { - Expected("FROM"); - - if (CurrentEquals("STANDARD-INPUT COMMAND-LINE")) - { - Choice("STANDARD-INPUT COMMAND-LINE"); - } - else if (CurrentEquals("DATE")) - { - Expected("DATE"); - Optional("YYYYMMDD"); - } - else if (CurrentEquals("DAY")) - { - Expected("DAY"); - Optional("YYYYDDD"); - } - else if (CurrentEquals("DAY-OF-WEEK")) - { - Expected("DAY-OF-WEEK"); - } - else if (CurrentEquals("TIME")) - { - Expected("TIME"); - - } - } - else if (CurrentEquals("AT LINE COLUMN COL")) - { - Optional("AT"); - if (!CurrentEquals("LINE COLUMN COL")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Peek(-1).Type.Display(false)}. - """) - .WithSourceLine(Peek(-1), $""" - When specifying the AT keyword, it must be followed by a LINE NUMBER, COLUMN/COL NUMBER or both. - """) - .CloseError(); - } - - Common.LineColumn(); - - Common.OnException(ref isConditional); - } - - if (isConditional) Expected("END-ACCEPT"); - } - - private static void AllocateStatement() - { - Expected("ALLOCATE"); - if (CurrentEquals(TokenType.Identifier) && !PeekEquals(1, "CHARACTERS") && !PeekEquals(1, TokenType.Symbol)) - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - Common.Arithmetic("CHARACTERS"); - Expected("CHARACTERS"); - } - - if (CurrentEquals("INITIALIZED")) - Expected("INITIALIZED"); - - if (CurrentEquals("RETURNING")) - { - Expected("RETURNING"); - References.Identifier(); - } - } - - private static void ComputeStatement() - { - bool isConditional = false; - - Expected("COMPUTE"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - Expected("="); - if (Common.NotIdentifierOrLiteral()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a valid arithmetic expression. - """) - .CloseError(); - } - - Common.Arithmetic("."); - - if (CurrentEquals(".")) return; - - Common.SizeError(ref isConditional); - - if (isConditional) Expected("END-COMPUTE"); - } - - private static void CallStatement() - { - bool isConditional = false; - bool isPrototype = false; - - Expected("CALL"); - if (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("AS")) - { - isPrototype = true; - Expected("AS"); - } - } - else - { - isPrototype = true; - } - - if (isPrototype && CurrentEquals("NESTED")) - { - Expected("NESTED"); - } - else if (isPrototype && !CurrentEquals("NESTED")) - { - References.Identifier(); - } - - if (!isPrototype && CurrentEquals("USING")) - { - Expected("USING"); - - StatementUsing(false, true); - } - else if (isPrototype && CurrentEquals("USING")) - { - Expected("USING"); - - StatementUsing(true, true); - } - - if (CurrentEquals("RETURNING")) - { - Expected("RETURNING"); - References.Identifier(); - } - - Common.OnException(ref isConditional); - - if (isConditional) Expected("END-CALL"); - } - - private static void ContinueStatement() - { - Expected("CONTINUE"); - if (CurrentEquals("AFTER")) - { - Expected("AFTER"); - Common.Arithmetic("SECONDS"); - Expected("SECONDS"); - } - } - - private static void AddStatement() - { - bool isConditional = false; - - Expected("ADD"); - - if (CurrentEquals("CORRESPONDING CORR")) - { - Continue(); - References.Identifier(); - Expected("TO"); - References.Identifier(); - Common.SizeError(ref isConditional); - - if (isConditional) Expected("END-ADD"); - return; - } - - if (!CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - } - - while (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - if (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - - if (CurrentEquals(TokenType.Numeric)) - Literals.Numeric(); - } - - if (CurrentEquals("TO") && PeekEquals(2, "GIVING")) - { - Optional("TO"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - Expected("GIVING"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if (CurrentEquals("GIVING")) - { - Expected("GIVING"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if (CurrentEquals("TO")) - { - Expected("TO"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected TO or GIVING reserved words. - """) - .CloseError(); - } - - Common.SizeError(ref isConditional); - - if (isConditional) Expected("END-ADD"); - } - - private static void SubtractStatement() - { - bool isConditional = false; - - Expected("SUBTRACT"); - if (Current().Type != TokenType.Identifier && Current().Type != TokenType.Numeric) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier - || Current().Type == TokenType.Numeric - ) - { - if (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (Current().Type == TokenType.Numeric) - Literals.Numeric(); - } - - if (CurrentEquals("FROM") && PeekEquals(2, "GIVING")) - { - Optional("FROM"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - Expected("GIVING"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if (CurrentEquals("FROM")) - { - Expected("FROM"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected FROM reserved word. - """) - .CloseError(); - } - - Common.SizeError(ref isConditional); - - if (isConditional) - Expected("END-SUBTRACT"); - } - - private static void IfStatement() - { - Expected("IF"); - Common.Condition("THEN"); - Optional("THEN"); - if (CurrentEquals("NEXT") && PeekEquals(1, "SENTENCE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unsupported phrase: NEXT SENTENCE is an archaic feature. - """) - .WithSourceLine(Current(), $""" - The CONTINUE statement can be used to accomplish the same functionality. - """) - .CloseError(); - } - - Statements.WithoutSections(true); - - if (CurrentEquals("ELSE")) - { - Expected("ELSE"); - Statements.WithoutSections(true); - } - - Expected("END-IF"); - } - - private static void InitializeStatement() - { - Expected("INITIALIZE"); - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - - if (CurrentEquals("WITH FILLER")) - { - Optional("WITH"); - Expected("FILLER"); - } - - static bool IsCategoryName() - { - return CurrentEquals("ALPHABETIC ALPHANUMERIC ALPHANUMERIC-EDITED BOOLEAN DATA-POINTER FUNCTION-POINTER MESSAGE-TAG NATIONAL NATIONAL-EDITED NUMERIC NUMERIC-EDITED OBJECT-REFERENCE PROGRAM-POINTER"); - } - - if (IsCategoryName()) - { - Expected(Current().Value); - Optional("TO"); - Expected("VALUE"); - } - else if (CurrentEquals("ALL")) - { - Expected("ALL"); - Optional("TO"); - Expected("VALUE"); - } - - if (CurrentEquals("THEN REPLACING")) - { - Optional("THEN"); - Expected("REPLACING"); - if (IsCategoryName()) - { - Expected(Current().Value); - Optional("DATA"); - Expected("BY"); - - if (Common.NotIdentifierOrLiteral()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or literal. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else if (CurrentEquals(TokenType.String)) - { - Literals.String(); - } - else if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - - while (IsCategoryName()) - { - Expected(Current().Value); - Optional("DATA"); - Expected("BY"); - - if (Common.NotIdentifierOrLiteral()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or literal. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else if (CurrentEquals(TokenType.String)) - { - Literals.String(); - } - else if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - - } - - } - } - - if (CurrentEquals("THEN TO DEFAULT")) - { - Optional("THEN"); - Optional("TO"); - Expected("DEFAULT"); - } - } - - private static void InitiateStatement() - { - Expected("INITIATE"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a report entry identifier defined in the report section. - """) - .CloseError(); - } - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a report entry identifier defined in the report section. - """) - .CloseError(); - } - } - - private static void InspectStatement() - { - Expected("INSPECT"); - if (CurrentEquals("BACKWARD")) Expected("BACKWARD"); - - References.Identifier(); - - if (CurrentEquals("CONVERTING")) - { - Expected("CONVERTING"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Expected("TO"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - Common.AfterBeforePhrase(); - } - else if (CurrentEquals("REPLACING")) - { - Expected("REPLACING"); - Common.ReplacingPhrase(); - } - else if (CurrentEquals("TALLYING")) - { - Expected("TALLYING"); - Common.TallyingPhrase(); - if (CurrentEquals("REPLACING")) - { - Expected("REPLACING"); - Common.ReplacingPhrase(); - } - } - } - - private static void InvokeStatement() - { - Expected("INVOKE"); - References.Identifier(); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - if (CurrentEquals("USING")) - { - Expected("USING"); - - StatementUsing(true, true); - } - - if (CurrentEquals("RETURNING")) - { - Expected("RETURNING"); - References.Identifier(); - } - } - - private static void MergeStatement() - { - Expected("MERGE"); - References.Identifier(); - - Optional("ON"); - if (CurrentEquals("ASCENDING")) - { - Expected("ASCENDING"); - } - else - { - Expected("DESCENDING"); - } - - Optional("KEY"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - The ON ASCENDING / DESCENDING KEY phrase must only contain key names. - """) - .CloseError(); - } - - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - - while (CurrentEquals("ON ASCENDING DESCENDING")) - { - Optional("ON"); - if (CurrentEquals("ASCENDING")) - { - Expected("ASCENDING"); - } - else - { - Expected("DESCENDING"); - } - - Optional("KEY"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - The ON ASCENDING / DESCENDING KEY phrase must only contain key names. - """) - .CloseError(); - } - - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - - if (CurrentEquals("COLLATING SEQUENCE")) - { - Optional("COLLATING"); - Expected("SEQUENCE"); - if (CurrentEquals("IS") && PeekEquals(1, TokenType.Identifier) || CurrentEquals(TokenType.Identifier)) - { - Optional("IS"); - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - } - else - { - if (!CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an alphabet name or at least one FOR ALPHANUMERIC and FOR NATIONAL phrases. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement, "USING"); - } - - Common.ForAlphanumericForNational(); - } - } - - Expected("USING"); - References.Identifier(); - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (CurrentEquals("OUTPUT")) - { - Expected("OUTPUT"); - Expected("PROCEDURE"); - Optional("IS"); - References.Identifier(); - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - References.Identifier(); - } - } - else - { - Expected("GIVING"); - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - } - - private static void MultiplyStatement() - { - bool isConditional = false; - - Expected("MULTIPLY"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - if (CurrentEquals("BY") && PeekEquals(2, "GIVING")) - { - Optional("BY"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - Expected("GIVING"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if (CurrentEquals("BY")) - { - Expected("BY"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected BY reserved word. - """) - .CloseError(); - } - - Common.SizeError(ref isConditional); - - if (isConditional) - Expected("END-MULTIPLY"); - } - - private static void MoveStatement() - { - Expected("MOVE"); - if (CurrentEquals("CORRESPONDING") || CurrentEquals("CORR")) - { - Expected(Current().Value); - References.Identifier(); - Expected("TO"); - References.Identifier(); - return; - } - - if (Common.NotIdentifierOrLiteral()) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a single data item identifier, literal or a function. - """) - .CloseError(); - } - - if (Current().Type == TokenType.Identifier) - References.Identifier(); - - else if (Literals.IsAny()) - Literals.Any(); - - Expected("TO"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected only data item identifiers. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - - private static void OpenStatement() - { - Expected("OPEN"); - Choice("INPUT OUTPUT I-O EXTEND"); - - if (CurrentEquals("SHARING")) - { - Expected("SHARING"); - Optional("WITH"); - if (CurrentEquals("ALL")) - { - Expected("ALL"); - Optional("OTHER"); - } - else if (CurrentEquals("NO")) - { - Expected("NO"); - Optional("OTHER"); - } - else if (CurrentEquals("READ")) - { - Expected("READ"); - Expected("ONLY"); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected ALL OTHER, NO OTHER or READ ONLY. - """) - .WithNote(""" - One of them must be specified in the SHARING phrase. - """) - .CloseError(); - } - } - - if (CurrentEquals("RETRY")) - { - Common.RetryPhrase(); - } - - References.Identifier(); - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - } - - while (CurrentEquals("INPUT OUTPUT I-O EXTEND")) - { - Choice("INPUT OUTPUT I-O EXTEND"); - - if (CurrentEquals("SHARING")) - { - Expected("SHARING"); - Optional("WITH"); - if (CurrentEquals("ALL")) - { - Expected("ALL"); - Optional("OTHER"); - } - else if (CurrentEquals("NO")) - { - Expected("NO"); - Optional("OTHER"); - } - else if (CurrentEquals("READ")) - { - Expected("READ"); - Expected("ONLY"); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected ALL OTHER, NO OTHER or READ ONLY. - """) - .WithNote(""" - One of them must be specified in the SHARING phrase. - """) - .CloseError(); - } - } - - if (CurrentEquals("RETRY")) - { - Common.RetryPhrase(); - } - - References.Identifier(); - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - } - - } - } - - private static void DivideStatement() - { - bool isConditional = false; - - Expected("DIVIDE"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - if ((CurrentEquals("BY") || CurrentEquals("INTO")) && PeekEquals(2, "GIVING") && !PeekEquals(4, "REMAINDER")) - { - Choice("BY INTO"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - Expected("GIVING"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if ((CurrentEquals("BY") || CurrentEquals("INTO")) && PeekEquals(2, "GIVING") && PeekEquals(4, "REMAINDER")) - { - Choice("BY INTO"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - - case TokenType.Numeric: - Literals.Numeric(); - break; - - default: - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier or numeric literal. - """) - .CloseError(); - break; - } - - Expected("GIVING"); - References.Identifier(); - Expected("REMAINDER"); - References.Identifier(); - } - else if (CurrentEquals("INTO")) - { - Expected("INTO"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected BY or INTO reserved words. - """) - .CloseError(); - } - - Common.SizeError(ref isConditional); - - if (isConditional) - Expected("END-MULTIPLY"); - } - - private static void DeleteStatement() - { - bool isConditional = false; - bool isFile = false; - - Expected("DELETE"); - if (CurrentEquals("FILE")) - { - isFile = true; - Expected("FILE"); - Optional("OVERRIDE"); - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - else if (Current().Type == TokenType.Identifier) - { - References.Identifier(); - Expected("RECORD"); - } - - if (CurrentEquals("RETRY")) - Common.RetryPhrase(); - - if (!isFile) - Common.InvalidKey(ref isConditional); - - if (isFile) - Common.OnException(ref isConditional); - - if (isConditional) - Expected("END-DELETE"); - } - - private static void EvaluateStatement() - { - var conditions = new List(); - var conditionsIndex = 0; - Expected("EVALUATE"); - - conditions.Add(Common.SelectionSubject()); - while (CurrentEquals("ALSO")) - { - Expected("ALSO"); - conditions.Add(Common.SelectionSubject()); - } - - Expected("WHEN"); - Common.SelectionObject(conditions[conditionsIndex]); - conditionsIndex++; - - while (CurrentEquals("ALSO")) - { - Expected("ALSO"); - Common.SelectionObject(conditions[conditionsIndex]); - conditionsIndex++; - } - conditionsIndex = 0; - - Statements.WithoutSections(true); - - while (CurrentEquals("WHEN") && !PeekEquals(1, "OTHER")) - { - Expected("WHEN"); - Common.SelectionObject(conditions[conditionsIndex]); - conditionsIndex++; - - while (CurrentEquals("ALSO")) - { - Expected("ALSO"); - Common.SelectionObject(conditions[conditionsIndex]); - conditionsIndex++; - } - conditionsIndex = 0; - - Statements.WithoutSections(true); - } - - if (CurrentEquals("WHEN") && PeekEquals(1, "OTHER")) - { - Expected("WHEN"); - Expected("OTHER"); - Statements.WithoutSections(true); - } - - Expected("END-EVALUATE"); - } - - private static void ExitStatement() - { - Expected("EXIT"); - if (CurrentEquals("PERFORM")) - { - Expected("PERFORM"); - Optional("CYCLE"); - } - else if (CurrentEquals("PARAGRAPH")) - Expected("PARAGRAPH"); - - else if (CurrentEquals("SECTION")) - Expected("SECTION"); - - else if (CurrentEquals("PROGRAM")) - { - Expected("PROGRAM"); - if (CurrentEquals("RAISING")) - { - Expected("RAISING"); - if (CurrentEquals("EXCEPTION")) - { - Expected("EXCEPTION"); - References.Identifier(); - } - else if (CurrentEquals("LAST")) - { - Expected("LAST"); - Optional("EXCEPTION"); - } - else - References.Identifier(); - } - } - } - - private static void FreeStatement() - { - Expected("FREE"); - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a data item defined with the BASED clause. - """) - .CloseError(); - } - - } - - private static void GenerateStatement() - { - Expected("GENERATE"); - References.Identifier(); - } - - private static void GoStatement() - { - Expected("GO"); - Optional("TO"); - - References.Identifier(); - - if (CurrentEquals("DEPENDING") || Current().Type == TokenType.Identifier) - { - while (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - Expected("DEPENDING"); - Optional("ON"); - - References.Identifier(); - } - } - - private static void GobackStatement() - { - Expected("GOBACK"); - Common.RaisingStatus(); - } - - private static void CommitStatement() - { - Expected("COMMIT"); - } - - private static void CloseStatement() - { - Expected("CLOSE"); - if (Current().Type == TokenType.Identifier) - { - References.Identifier(); - if (CurrentEquals("REEL") || CurrentEquals("UNIT")) - { - Expected(Current().Value); - - if (CurrentEquals("FOR") || CurrentEquals("REMOVAL")) - { - Optional("FOR"); - Expected("REMOVAL"); - } - } - else if (CurrentEquals("WITH") || CurrentEquals("NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - } - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a file connector name. - """) - .CloseError(); - } - - while (Current().Type == TokenType.Identifier) - { - References.Identifier(); - if (CurrentEquals("REEL UNIT")) - { - Expected(Current().Value); - - if (CurrentEquals("FOR REMOVAL")) - { - Optional("FOR"); - Expected("REMOVAL"); - } - } - else if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("REWIND"); - } - } - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a file connector name. - """) - .CloseError(); - } - } - - private static void CancelStatement() - { - Expected("CANCEL"); - if (Current().Type == TokenType.Identifier) - References.Identifier(); - - else if (Current().Type == TokenType.String) - Literals.String(); - - else - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an alphanumeric or national literal, or a REPOSITORY paragraph program name. - """) - .CloseError(); - - Continue(); - } - - while (Current().Type == TokenType.Identifier || Current().Type == TokenType.String) - { - if (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (Current().Type == TokenType.String) - Literals.String(); - } - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an alphanumeric or national literal, or a REPOSITORY paragraph program name. - """) - .CloseError(); - } - } - - private static void PerformStatement() - { - bool isExceptionChecking = false; - bool isInline = false; - - Expected("PERFORM"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - References.Identifier(); - } - - if (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - Common.TimesPhrase(); - } - else if (CurrentEquals("WITH TEST VARYING UNTIL")) - { - Common.WithTest(); - if (CurrentEquals("VARYING")) - { - Common.VaryingPhrase(); - } - else if (CurrentEquals("UNTIL")) - { - Common.UntilPhrase(); - } - } - } - else - { - if (CurrentEquals("LOCATION") || CurrentEquals("WITH") && PeekEquals(1, "LOCATION")) - { - isExceptionChecking = true; - Optional("WITH"); - Expected("LOCATION"); - } - else if (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - isInline = true; - - Common.TimesPhrase(); - } - else if (CurrentEquals("TEST VARYING UNTIL") || CurrentEquals("WITH") && PeekEquals(1, "TEST")) - { - isInline = true; - - Common.WithTest(); - if (CurrentEquals("VARYING")) - { - Common.VaryingPhrase(); - } - else if (CurrentEquals("UNTIL")) - { - Common.UntilPhrase(); - } - } - - Statements.WithoutSections(true); - - if (isInline && CurrentEquals("WHEN")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - An inline PERFORM cannot contain an exception checking WHEN phrase. - """) - .CloseError(); - - AnchorPoint("END-PERFORM"); - } - - if (isExceptionChecking || !isInline && CurrentEquals("WHEN")) - { - isExceptionChecking = true; - - Expected("WHEN"); - if (CurrentEquals("EXCEPTION") && PeekEquals(1, TokenType.Identifier)) - { - Expected("EXCEPTION"); - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - - Statements.WithoutSections(true); - } - else if (CurrentEquals("EXCEPTION")) - { - Expected("EXCEPTION"); - - Choice("INPUT OUTPUT IO EXTEND"); - - Statements.WithoutSections(true); - } - else if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "FILE")) - { - References.Identifier(); - Expected("FILE"); - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - } - else if (CurrentEquals(TokenType.Identifier) && !PeekEquals(1, "FILE")) - { - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - } - - while (CurrentEquals("WHEN")) - { - Expected("WHEN"); - if (CurrentEquals("EXCEPTION") && PeekEquals(1, TokenType.Identifier)) - { - Expected("EXCEPTION"); - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - - Statements.WithoutSections(true); - } - else if (CurrentEquals("EXCEPTION")) - { - Expected("EXCEPTION"); - - Choice("INPUT OUTPUT IO EXTEND"); - - Statements.WithoutSections(true); - } - else if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "FILE")) - { - References.Identifier(); - Expected("FILE"); - References.Identifier(); - - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - } - else if (CurrentEquals(TokenType.Identifier) && !PeekEquals(1, "FILE")) - { - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - } - } - } - - if (isExceptionChecking && CurrentEquals("WHEN") && PeekEquals(1, "OTHER")) - { - Expected("WHEN"); - Expected("OTHER"); - Optional("EXCEPTION"); - - Statements.WithoutSections(true); - } - - if (isExceptionChecking && CurrentEquals("WHEN COMMON")) - { - Optional("WHEN"); - Expected("COMMON"); - Optional("EXCEPTION"); - - Statements.WithoutSections(true); - } - - if (isExceptionChecking && CurrentEquals("FINALLY")) - { - Expected("FINALLY"); - - Statements.WithoutSections(true); - } - - Expected("END-PERFORM"); - } - } - - private static void RaiseStatement() - { - Expected("RAISE"); - if (CurrentEquals("EXCEPTION")) - { - Expected("EXCEPTION"); - References.Identifier(); - } - else - References.Identifier(); - } - - private static void ReadStatement() - { - bool isSequential = false; - bool isConditional = false; - - Expected("READ"); - References.Identifier(); - if (CurrentEquals("NEXT PREVIOUS")) - { - Expected(Current().Value); - isSequential = true; - } - - Expected("RECORD"); - if (CurrentEquals("INTO")) - { - Expected("INTO"); - References.Identifier(); - } - - if (CurrentEquals("ADVANCING")) - { - Expected("ADVANCING"); - Optional("ON"); - Expected("LOCK"); - isSequential = true; - } - else if (CurrentEquals("IGNORING")) - { - Expected("IGNORING"); - Expected("LOCK"); - } - else if (CurrentEquals("RETRY")) - { - Common.RetryPhrase(); - } - - if (CurrentEquals("WITH LOCK")) - { - Optional("WITH"); - Expected("LOCK"); - } - else if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("LOCK"); - } - - if (!isSequential && CurrentEquals("KEY")) - { - Expected("KEY"); - Optional("IS"); - References.Identifier(); - } - - if (!isSequential && CurrentEquals("INVALID NOT")) - { - Common.InvalidKey(ref isConditional); - } - else if (isSequential && CurrentEquals("AT END NOT")) - { - Common.AtEnd(ref isConditional); - } - - if (isConditional) Expected("END-READ"); - } - - private static void ReceiveStatement() - { - bool isConditional = false; - - Expected("RECEIVE"); - Optional("FROM"); - References.Identifier(); - Expected("GIVING"); - References.Identifier(); - References.Identifier(); - - if (CurrentEquals("CONTINUE")) - { - Expected("CONTINUE"); - Optional("AFTER"); - if (CurrentEquals("MESSAGE")) - { - Expected("MESSAGE"); - Expected("RECEIVED"); - } - else - { - Common.Arithmetic("SECONDS"); - Optional("SECONDS"); - } - } - - Common.OnException(ref isConditional); - - if (isConditional) Expected("END-RECEIVE"); - - } - - private static void ReleaseStatement() - { - Expected("RELEASE"); - References.Identifier(); - - if (CurrentEquals("FROM")) - { - Expected("FROM"); - if (Current().Type == TokenType.String) - Literals.String(); - - else if (Current().Type == TokenType.Numeric) - Literals.Numeric(); - - else - References.Identifier(); - } - } - - private static void ReturnStatement() - { - bool isConditional = false; - - Expected("RETURN"); - References.Identifier(); - Expected("RECORD"); - if (CurrentEquals("INTO")) - { - Expected("INTO"); - References.Identifier(); - } - - Common.AtEnd(ref isConditional); - - if (isConditional) - Expected("END-RETURN"); - } - - private static void RewriteStatement() - { - bool isConditional = false; - bool isFile = false; - - Expected("REWRITE"); - if (CurrentEquals("FILE")) - { - isFile = true; - Expected("FILE"); - References.Identifier(); - } - else - References.Identifier(); - - Expected("RECORD"); - if (CurrentEquals("FROM") || isFile) - { - Expected("FROM"); - - if (Current().Type == TokenType.Identifier) - References.Identifier(); - - else if (Current().Type == TokenType.Numeric) - Literals.Numeric(); - - else - Literals.String(); - } - - Common.RetryPhrase(); - if (CurrentEquals("WITH") || CurrentEquals("LOCK") || CurrentEquals("NO")) - { - Optional("WITH"); - if (CurrentEquals("LOCK")) - { - Expected("LOCK"); - } - else - { - Expected("NO"); - Expected("LOCK"); - } - } - - Common.InvalidKey(ref isConditional); - - if (isConditional) - Expected("END-REWRITE"); - } - - private static void ResumeStatement() - { - Expected("RESUME"); - Optional("AT"); - if (CurrentEquals("NEXT")) - { - Expected("NEXT"); - Expected("STATEMENT"); - } - else - { - References.Identifier(); - } - } - - private static void RollbackStatement() - { - Expected("ROLLBACK"); - } - - private static void SearchStatement() - { - Expected("SEARCH"); - if (!CurrentEquals("ALL")) - { - References.Identifier(); - if (CurrentEquals("VARYING")) - { - Expected("VARYING"); - References.Identifier(); - } - - if (CurrentEquals("AT END")) - { - Optional("AT"); - Expected("END"); - Statements.WithoutSections(true); - } - - if (!CurrentEquals("WHEN")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected at least one WHEN condition phrase. - """) - .CloseError(); - } - - while (CurrentEquals("WHEN")) - { - Expected("WHEN"); - - Common.Condition(" "); - - if (CurrentEquals("NEXT") && PeekEquals(1, "SENTENCE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unsupported phrase: NEXT SENTENCE is an archaic feature. - """) - .WithSourceLine(Current(), $""" - The CONTINUE statement can be used to accomplish the same functionality. - """) - .CloseError(); - - AnchorPoint("WHEN END-SEARCH"); - } - - Statements.WithoutSections(true); - } - - Expected("END-SEARCH"); - return; - } - - Expected("ALL"); - References.Identifier(); - if (CurrentEquals("AT END")) - { - Optional("AT"); - Expected("END"); - Statements.WithoutSections(true); - } - - Expected("WHEN"); - References.Identifier(); - if (CurrentEquals("IS EQUAL =")) - { - Optional("IS"); - if (CurrentEquals("EQUAL")) - { - Expected("EQUAL"); - Optional("TO"); - } - else - { - Expected("="); - } - } - - if (CurrentEquals(TokenType.Identifier | TokenType.String | TokenType.Numeric) && PeekEquals(1, TokenType.Symbol)) - { - Common.Arithmetic(" "); - } - else if (CurrentEquals(TokenType.Identifier) && !PeekEquals(1, TokenType.Symbol)) - { - References.Identifier(); - } - else if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - Literals.String(); - } - - while (CurrentEquals("AND")) - { - Expected("AND"); - References.Identifier(); - if (CurrentEquals("IS EQUAL =")) - { - Optional("IS"); - if (CurrentEquals("EQUAL")) - { - Expected("EQUAL"); - Optional("TO"); - } - else - { - Expected("="); - } - } - - if (CurrentEquals(TokenType.Identifier | TokenType.String | TokenType.Numeric) && PeekEquals(1, TokenType.Symbol)) - { - Common.Arithmetic(" "); - } - else if (CurrentEquals(TokenType.Identifier) && !PeekEquals(1, TokenType.Symbol)) - { - References.Identifier(); - } - else if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - Literals.String(); - } - - } - - if (CurrentEquals("NEXT") && PeekEquals(1, "SENTENCE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unsupported phrase: NEXT SENTENCE is an archaic feature. - """) - .WithSourceLine(Current(), $""" - The CONTINUE statement can be used to accomplish the same functionality. - """) - .CloseError(); - - AnchorPoint("END-SEARCH"); - } - - Statements.WithoutSections(true); - Expected("END-SEARCH"); - } - - private static void SendStatement() - { - bool isConditional = false; - Expected("SEND"); - Optional("TO"); - - if (PeekEquals(3, "RETURNING")) - { - if (CurrentEquals(TokenType.String)) - { - Literals.String(); - } - else - { - References.Identifier(); - } - - Expected("FROM"); - References.Identifier(); - Expected("RETURNING"); - References.Identifier(); - } - else - { - References.Identifier(); - Expected("FROM"); - References.Identifier(); - - if (CurrentEquals("RAISING")) - { - Expected("RAISING"); - if (CurrentEquals("LAST")) - { - Expected("LAST"); - Optional("EXCEPTION"); - } - else - { - Expected("EXCEPTION"); - References.Identifier(); - } - } - } - - Common.OnException(ref isConditional); - - if (isConditional) Expected("END-SEND"); - } - - private static void SetStatement() - { - Expected("SET"); - - if (CurrentEquals(TokenType.Identifier) || CurrentEquals("SIZE ADDRESS")) - { - // TODO: This needs to be fixed to lookup a qualified reference - DataEntry dataItem = new(Current(), EntryKind.DataDescription); - - if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "UP DOWN TO")) - { - References.Identifier(); - if (CurrentEquals("UP")) - { - Expected("UP"); - Expected("BY"); - } - else if (CurrentEquals("DOWN")) - { - Expected("DOWN"); - Expected("BY"); - } - else - { - Expected("TO"); - } - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Common.Arithmetic(" "); - } - } - else if (CurrentEquals(TokenType.Identifier) && PeekEquals(1, "TO") && PeekEquals(2, "LOCALE")) - { - References.Identifier(); - Expected("TO"); - Expected("LOCALE"); - Choice("LC_ALL LOCALE"); - } - else if (dataItem.Usage == Usages.MessageTag) - { - References.Identifier(); - Expected("TO"); - if (CurrentEquals("NULL")) - { - Expected("NULL"); - } - else - { - References.Identifier(); - } - } - else if (dataItem[DataClause.DynamicLength] || CurrentEquals("SIZE")) - { - if (CurrentEquals("SIZE")) - { - Expected("SIZE"); - Optional("OF"); - } - - References.Identifier(); - Expected("TO"); - if (CurrentEquals(TokenType.Numeric)) - { - Literals.Numeric(); - } - else - { - Common.Arithmetic(" "); - } - } - else if (dataItem.Usage == Usages.DataPointer || CurrentEquals("ADDRESS")) - { - bool hasAddress = false; - - if (CurrentEquals("ADDRESS")) - { - hasAddress = true; - Expected("ADDRESS"); - Optional("OF"); - References.Identifier(); - } - else - { - References.Identifier(); - } - - while (CurrentEquals(TokenType.Identifier) || CurrentEquals("ADDRESS")) - { - if (CurrentEquals("ADDRESS")) - { - hasAddress = true; - Expected("ADDRESS"); - Optional("OF"); - References.Identifier(); - } - else - { - References.Identifier(); - } - } - - if (hasAddress || CurrentEquals("TO")) - { - Expected("TO"); - References.Identifier(); - } - else if (!hasAddress && CurrentEquals("UP DOWN")) - { - Choice("UP DOWN"); - Expected("BY"); - Common.Arithmetic(" "); - } - } - else if (dataItem.Usage is Usages.Index) - { - - References.Identifier(); - bool checkUsage = true; - - while (CurrentEquals(TokenType.Identifier)) - References.Identifier(); - - if (CurrentEquals("TO")) - { - Expected("TO"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Common.Arithmetic(" "); - } - } - else if (checkUsage && CurrentEquals("UP DOWN")) - { - Choice("UP DOWN"); - Expected("BY"); - Common.Arithmetic(" "); - } - - } - } - else if (CurrentEquals("LAST")) - { - Expected("LAST"); - Expected("EXCEPTION"); - Expected("TO"); - Expected("OFF"); - } - else if (CurrentEquals("LOCALE")) - { - Expected("LOCALE"); - if (CurrentEquals("USER-DEFAULT")) - { - Expected("USER-DEFAULT"); - } - else - { - Common.SetLocale(); - } - - Expected("TO"); - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Choice("USER-DEFAULT SYSTEM-DEFAULT"); - } - } - - } - - private static void SortStatement() - { - Expected("SORT"); - References.Identifier(); - - Optional("ON"); - if (CurrentEquals("ASCENDING")) - { - Expected("ASCENDING"); - } - else - { - Expected("DESCENDING"); - } - - Optional("KEY"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - The ON ASCENDING / DESCENDING KEY phrase must only contain key names. - """) - .CloseError(); - } - - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - - while (CurrentEquals("ON ASCENDING DESCENDING")) - { - Optional("ON"); - if (CurrentEquals("ASCENDING")) - { - Expected("ASCENDING"); - } - else - { - Expected("DESCENDING"); - } - - Optional("KEY"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - The ON ASCENDING / DESCENDING KEY phrase must only contain key names. - """) - .CloseError(); - } - - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - - if (CurrentEquals("WITH DUPLICATES")) - { - Optional("WITH"); - Expected("DUPLICATES"); - Optional("IN"); - Optional("ORDER"); - } - - if (CurrentEquals("COLLATING SEQUENCE")) - { - Optional("COLLATING"); - Expected("SEQUENCE"); - if (CurrentEquals("IS") && PeekEquals(1, TokenType.Identifier) || CurrentEquals(TokenType.Identifier)) - { - Optional("IS"); - References.Identifier(); - - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - } - else - { - if (!CurrentEquals("FOR ALPHANUMERIC NATIONAL")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an alphabet name or at least one FOR ALPHANUMERIC and FOR NATIONAL phrases. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement, "USING"); - } - - Common.ForAlphanumericForNational(); - } - } - - if (CurrentEquals("INPUT")) - { - Expected("INPUT"); - Expected("PROCEDURE"); - Optional("IS"); - References.Identifier(); - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - References.Identifier(); - } - } - else - { - Expected("USING"); - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - - if (CurrentEquals("OUTPUT")) - { - Expected("OUTPUT"); - Expected("PROCEDURE"); - Optional("IS"); - References.Identifier(); - - if (CurrentEquals("THROUGH THRU")) - { - Choice("THROUGH THRU"); - References.Identifier(); - } - } - else - { - Expected("GIVING"); - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - } - } - - private static void StartStatement() - { - bool isConditional = false; - - Expected("START"); - References.Identifier(); - - if (CurrentEquals("FIRST")) - { - Expected("FIRST"); - } - else if (CurrentEquals("LAST")) - { - Expected("LAST"); - } - else if (CurrentEquals("KEY")) - { - Expected("KEY"); - Common.StartRelationalOperator(); - References.Identifier(); - - if (CurrentEquals("WITH LENGTH")) - { - Optional("WITH"); - Expected("LENGTH"); - Common.Arithmetic("."); - } - - } - - Common.InvalidKey(ref isConditional); - - if (isConditional) Expected("END-START"); - } - - private static void StopStatement() - { - Expected("STOP"); - Expected("RUN"); - if (CurrentEquals("WITH") || CurrentEquals("NORMAL") || CurrentEquals("ERROR")) - { - Optional("WITH"); - Choice("NORMAL ERROR"); - Optional("STATUS"); - switch (Current().Type) - { - case TokenType.Identifier: - References.Identifier(); - break; - case TokenType.Numeric: - Literals.Numeric(); - break; - case TokenType.String: - Literals.String(); - break; - } - } - } - - private static void StringStatement() - { - bool isConditional = false; - - Expected("STRING"); - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else Literals.String(); - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else Literals.String(); - } - - Expected("DELIMITED"); - Optional("BY"); - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else if (CurrentEquals("SIZE")) Expected("SIZE"); - - else Literals.String(); - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else Literals.String(); - - while (CurrentEquals(TokenType.Identifier | TokenType.String)) - { - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else Literals.String(); - } - - Expected("DELIMITED"); - Optional("BY"); - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else if (CurrentEquals("SIZE")) Expected("SIZE"); - - else Literals.String(); - } - - Expected("INTO"); - References.Identifier(); - - if (CurrentEquals("WITH POINTER")) - { - Optional("WITH"); - Expected("POINTER"); - References.Identifier(); - } - - Common.OnOverflow(ref isConditional); - - if (isConditional) Expected("END-STRING"); - } - - private static void SuppressStatement() - { - Expected("SUPPRESS"); - Optional("PRINTING"); - } - - private static void TerminateStatement() - { - Expected("TERMINATE"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a report entry identifier defined in the report section. - """) - .CloseError(); - } - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected a report entry identifier defined in the report section. - """) - .CloseError(); - } - } - - private static void UnlockStatement() - { - Expected("UNLOCK"); - References.Identifier(); - Choice("RECORD RECORDS"); - } - - private static void UnstringStatement() - { - bool isConditional = false; - - Expected("UNSTRING"); - References.Identifier(); - - if (CurrentEquals("DELIMITED")) - { - Expected("DELIMITED"); - Optional("BY"); - if (CurrentEquals("ALL")) Expected("ALL"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - - while (CurrentEquals("OR")) - { - Expected("OR"); - if (CurrentEquals("ALL")) Expected("ALL"); - - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - } - } - - Expected("INTO"); - References.Identifier(); - - if (CurrentEquals("DELIMITER")) - { - Expected("DELIMITER"); - Optional("IN"); - References.Identifier(); - } - if (CurrentEquals("COUNT")) - { - Expected("COUNT"); - Optional("IN"); - References.Identifier(); - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - - if (CurrentEquals("DELIMITER")) - { - Expected("DELIMITER"); - Optional("IN"); - References.Identifier(); - } - if (CurrentEquals("COUNT")) - { - Expected("COUNT"); - Optional("IN"); - References.Identifier(); - } - } - - if (CurrentEquals("WITH POINTER")) - { - Optional("WITH"); - Expected("POINTER"); - References.Identifier(); - } - - if (CurrentEquals("TALLYING")) - { - Expected("TALLYING"); - Optional("IN"); - References.Identifier(); - } - - Common.OnOverflow(ref isConditional); - - if (isConditional) Expected("END-UNSTRING"); - } - - private static void ValidateStatement() - { - Expected("VALIDATE"); - if (Current().Type != TokenType.Identifier) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - References.Identifier(); - while (Current().Type == TokenType.Identifier) - References.Identifier(); - - if (!CurrentEquals(".")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, $""" - Unexpected {Current().Type.Display(false)}. - """) - .WithSourceLine(Current(), $""" - Expected an identifier. - """) - .CloseError(); - } - } - - private static void WriteStatement() - { - bool isSequential = false; - bool isConditional = false; - - Expected("WRITE"); - if (CurrentEquals("FILE")) - { - Expected("FILE"); - References.Identifier(); - } - else - { - References.Identifier(); - } - - if (CurrentEquals("FROM")) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - } - else - { - Literals.String(); - } - } - - if (CurrentEquals("BEFORE AFTER")) - { - isSequential = true; - - Common.WriteBeforeAfter(); - Optional("ADVANCING"); - if (CurrentEquals("PAGE")) - { - Expected("PAGE"); - // Missing mnemonic-name handling - } - else if (CurrentEquals(TokenType.Identifier | TokenType.Numeric)) - { - if (CurrentEquals(TokenType.Identifier)) References.Identifier(); - - else Literals.Numeric(); - - if (CurrentEquals("LINE LINES")) - { - Expected(Current().Value); - } - } - } - - Common.RetryPhrase(); - - if (CurrentEquals("WITH LOCK")) - { - Optional("WITH"); - Expected("LOCK"); - } - else if (CurrentEquals("WITH NO")) - { - Optional("WITH"); - Expected("NO"); - Expected("LOCK"); - } - - if (isSequential && CurrentEquals("AT NOT END-OF-PAGE EOP")) - { - Common.AtEndOfPage(ref isConditional); - } - else if (!isSequential && CurrentEquals("INVALID NOT")) - { - Common.InvalidKey(ref isConditional); - } - - if (isConditional) Expected("END-WRITE"); - } - - private static void ParseParagraph() - { - References.Identifier(Current()); - } - - // Different from Using(), this one is for the CALL and INVOKE only. - private static void StatementUsing(bool byValue, bool byContent) - { - while (CurrentEquals("BY REFERENCE VALUE") || CurrentEquals(TokenType.Identifier)) - { - if (CurrentEquals(TokenType.Identifier)) - { - References.Identifier(); - while (CurrentEquals(TokenType.Identifier) || CurrentEquals("OPTIONAL")) - { - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - } - // TODO: Reimplement parameter item resolution - References.Identifier(); - } - } - - if (CurrentEquals("BY") && !PeekEquals(1, "VALUE REFERENCE CONTENT")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128,""" - Using phrase, missing keyword. - """) - .WithSourceLine(Current(), """ - Expected REFERENCE, VALUE or CONTENT after this token - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement, "RETURNING"); - } - - if (CurrentEquals("REFERENCE") || CurrentEquals("BY") && PeekEquals(1, "REFERENCE")) - { - Optional("BY"); - Expected("REFERENCE"); - - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - } - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128,""" - Using phrase, missing identifier. - """) - .WithSourceLine(Current(), """ - BY REFERENCE phrase must contain at least one data item name. - """) - .CloseError(); - } - - // TODO: Reimplement parameter item resolution - - References.Identifier(); - while (CurrentEquals(TokenType.Identifier) || CurrentEquals("OPTIONAL")) - { - if (CurrentEquals("OPTIONAL")) - { - Expected("OPTIONAL"); - } - // TODO: Reimplement parameter item resolution - References.Identifier(); - } - } - - if (byValue && CurrentEquals("VALUE") || CurrentEquals("BY") && PeekEquals(1, "VALUE")) - { - Optional("BY"); - Expected("VALUE"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128,""" - Using phrase, missing identifier. - """) - .WithSourceLine(Current(), """ - BY VALUE phrase must contain at least one data item name. - """) - .CloseError(); - } - - // TODO: Reimplement parameter item resolution - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - { - // TODO: Reimplement parameter item resolution - References.Identifier(); - } - } - - if (byContent && CurrentEquals("CONTENT") || CurrentEquals("BY") && PeekEquals(1, "CONTENT")) - { - Optional("BY"); - Expected("CONTENT"); - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128,""" - Using phrase, missing identifier. - """) - .WithSourceLine(Current(), """ - BY CONTENT phrase must contain at least one data item name. - """) - .CloseError(); - } - - // TODO: Reimplement parameter item resolution - References.Identifier(); - while (CurrentEquals(TokenType.Identifier)) - { - // TODO: Reimplement parameter item resolution - References.Identifier(); - } - } - } - } - - private static void Using(bool isPrototypeOrMethod) - { - while (CurrentEquals("BY REFERENCE CONTENT VALUE") || CurrentEquals(TokenType.Identifier)) - { - if (CurrentEquals("BY") && !PeekEquals(1, "REFERENCE CONTENT VALUE")) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing word. - """) - .WithSourceLine(Current(), """ - Expected 'REFERENCE', 'CONTENT' or 'VALUE' after this token. - """) - .CloseError(); - - AnchorPoint(TokenContext.IsStatement); - } - - ByReference(isPrototypeOrMethod); - - ByContent(isPrototypeOrMethod); - - ByValue(isPrototypeOrMethod); - } - } - - private static void ByReference(bool isPrototypeOrMethod) - { - if (!CurrentEquals(TokenType.Identifier) && !CurrentEquals("REFERENCE") && !PeekEquals(1, "REFERENCE")) return; - - Optional("BY"); - Optional("REFERENCE"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing identifier. - """) - .WithSourceLine(Peek(-1), """ - Must contain at least one data name. - """) - .CloseError(); - } - - if (isPrototypeOrMethod) - { - References.LocalName(); - - return; - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Qualified(); - } - } - - private static void ByContent(bool isPrototypeOrMethod) - { - if (!CurrentEquals("CONTENT") && !PeekEquals(1, "CONTENT")) return; - - Optional("BY"); - Expected("CONTENT"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing identifier. - """) - .WithSourceLine(Peek(-1), """ - Must contain at least one data name. - """) - .CloseError(); - } - - if (isPrototypeOrMethod) - { - References.LocalName(); - - return; - } - - while (CurrentEquals(TokenType.Identifier)) - { - References.Qualified(); - } - } - - private static void ByValue(bool isPrototypeOrMethod) - { - if (!CurrentEquals("VALUE") && !PeekEquals(1, "VALUE")) return; - - Optional("BY"); - Expected("VALUE"); - - if (!CurrentEquals(TokenType.Identifier)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 128, """ - Using phrase missing identifier. - """) - .WithSourceLine(Peek(-1), """ - Must contain at least one data name. - """) - .CloseError(); - } - - References.Qualified(); - } - - // This method handles COBOL's slightly inconsistent separator period rules. - // Statements that are nested inside another statement cannot end with a separator period, - // since that separator period would mean the end of the containing statement and not the contained statement. - private static void ScopeTerminator(bool isNested) - { - if (isNested) return; - - if (CurrentEquals(".")) - { - Expected("."); - return; - } - - if (!CurrentEquals(TokenContext.IsStatement)) - { - Expected("."); - } - } - -} diff --git a/Otterkit.CodeGenerators/Otterkit.CodeGenerators.csproj b/Otterkit.CodeGenerators/Otterkit.CodeGenerators.csproj deleted file mode 100644 index 991da159..00000000 --- a/Otterkit.CodeGenerators/Otterkit.CodeGenerators.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - - - - - true - Otterkit.CodeGenerators - ./nupkg - Apache-2.0 - 1.0.70 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Compiler;Generators - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains the Standard COBOL code generators for the Otterkit compiler. - - - - - - - - - - - - - - diff --git a/Otterkit.CodeGenerators/README.md b/Otterkit.CodeGenerators/README.md deleted file mode 100644 index e2b5667e..00000000 --- a/Otterkit.CodeGenerators/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Otterkit.CodeGenerators namespace - -This namespace contains the Standard COBOL code generators -for the Otterkit compiler. - diff --git a/Otterkit.CodeGenerators/src/Builders/ProgramBuilder.cs b/Otterkit.CodeGenerators/src/Builders/ProgramBuilder.cs deleted file mode 100644 index 9eb89622..00000000 --- a/Otterkit.CodeGenerators/src/Builders/ProgramBuilder.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Text; -using Otterkit.Types; - -namespace Otterkit.CodeGenerators; - -public class ProgramBuilder -{ - private StringBuilder Compiled = new(); - public Option Identification; - public Option Name; - - public string ExportCompiled() - { - return Compiled.ToString(); - } - - public void FormatIdentification(Token token) - { - var identification = token.Value; - - Name = token; - - Identification = string.Create(identification.Length + 1, identification, (span, value) => - { - span[0] = '_'; - - for (int i = 0; i < value.Length; i++) - { - span[i + 1] = value[i] switch - { - '-' => '_', - _ => value[i], - }; - } - }); - } - - public void Append(StringBuilder snippet) - { - Compiled.Append(snippet); - } - - public void AppendHeader() - { - Compiled.Append("using Otterkit.Runtime;namespace OtterkitExport;"); - } - - public void AppendIdentification() - { - Compiled.Append($$"""public static class {{Identification.Unwrap()}}{"""); - } - - public void InitializeProcedure() - { - Compiled.Append("public static void Procedure(){"); - } - - public void FinalizeProcedure() - { - Compiled.Append("}}"); - } -} diff --git a/Otterkit.CodeGenerators/src/Builders/StatementBuilder.cs b/Otterkit.CodeGenerators/src/Builders/StatementBuilder.cs deleted file mode 100644 index 63e5160d..00000000 --- a/Otterkit.CodeGenerators/src/Builders/StatementBuilder.cs +++ /dev/null @@ -1,252 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Analyzers; -using Otterkit.Types; -using System.Text; - -namespace Otterkit.CodeGenerators; - -public readonly struct StatementBuilder -{ - private readonly ProgramBuilder Builder; - private readonly StringBuilder Compiled = new(); - - - public StatementBuilder(ProgramBuilder builder) - { - Builder = builder; - } - - public void ExportStatement() - { - Builder.Append(Compiled); - } - - public void BuildStatement() - { - Statement(); - } - - private void Statement() - { - if (CurrentEquals("DISPLAY")) - { - DISPLAY(); - } - else if (CurrentEquals("CALL")) - { - CALL(); - } - else if (CurrentEquals("ACCEPT")) - { - ACCEPT(); - } - else if (CurrentEquals("STOP")) - { - STOP(); - } - else if (CurrentEquals("IF")) - { - IF(); - } - } - - private void DISPLAY() - { - Compiled.Append("Statement.DISPLAY("); - - Continue(1); - - while (Literals.IsAny() || CurrentEquals(TokenType.Identifier)) - { - if (Current().Type == TokenType.Identifier) - { - var identifier = FormatIdentifier(Current().Value); - Compiled.Append($"{identifier}.Bytes, "); - } - - if (Current().Type == TokenType.Numeric) - { - Compiled.Append($"\"{Current().Value}\"u8, "); - } - - if (Current().Type == TokenType.String) - { - Compiled.Append($"{Current().Value}u8, "); - } - - Continue(1); - } - - if (CurrentEquals("UPON")) - { - Continue(1); - if (CurrentEquals("STANDARD-OUTPUT")) - Compiled.Append($"\"{Current().Value}\", "); - - if (CurrentEquals("STANDARD-ERROR")) - Compiled.Append($"\"{Current().Value}\", "); - - Continue(1); - } - else if (!CurrentEquals("UPON")) - { - Compiled.Append("\"\", "); - } - - if (CurrentEquals("WITH") || CurrentEquals("NO")) - Compiled.Append("false);"); - - if (!CurrentEquals("WITH") && !CurrentEquals("NO")) - Compiled.Append("true);"); - - ExportStatement(); - } - - private void CALL() - { - Continue(1); - string ProgramName = $"{FormatIdentifier(Current().Value[1..^1])}"; - - Compiled.Append($"{ProgramName} {ProgramName} = new();"); - Compiled.Append("Statement.CALL("); - Compiled.Append($"() => {ProgramName}.Procedure());"); - - ExportStatement(); - } - - private void ACCEPT() - { - Compiled.Append("Statement.ACCEPT("); - // Statement.ACCEPT(dataItem, from, format) - Continue(1); - Compiled.Append($"{FormatIdentifier(Current().Value)}, "); - Continue(1); - - if (!CurrentEquals("FROM")) - Compiled.Append("\"STANDARD-INPUT\", \"\");"); - - if (CurrentEquals("FROM")) - { - Continue(1); - - switch (Current().Value.ToUpperInvariant()) - { - case "STANDARD-INPUT": - case "COMMAND-LINE": - Compiled.Append($"\"{Current().Value}\", \"\");"); - break; - - case "DATE": - Compiled.Append($"\"{Current().Value}\""); - if (PeekEquals(1, "YYYYMMDD")) - Compiled.Append($", \"{Peek(1).Value}\");"); - - if (!PeekEquals(1, "YYYYMMDD")) - Compiled.Append(", \"\");"); - break; - - case "DAY": - Compiled.Append($"\"{Current().Value}\""); - if (PeekEquals(1, "YYYYDDD")) - Compiled.Append($", \"{Peek(1).Value}\");"); - - if (!PeekEquals(1, "YYYYDDD")) - Compiled.Append(", \"\");"); - break; - - case "DAY-OF-WEEK": - Compiled.Append($"\"{Current().Value}\", \"\"););"); - break; - - case "TIME": - Compiled.Append($"\"{Current().Value}\", \"\"););"); - break; - } - } - - ExportStatement(); - } - - private void IF() - { - List expression = new(); - Continue(1); - while (!CurrentEquals("THEN") && !CurrentEquals(TokenContext.IsStatement)) - { - expression.Add(Current()); - Continue(1); - } - - expression = Expressions.ShuntingYard(expression, Expressions.ConditionalPrecedence); - - foreach (var item in expression) - { - Console.WriteLine(item); - } - - var compiledExpression = Expressions.PostfixToCSharpInfix(expression, Expressions.ConditionalPrecedence); - - Compiled.Append($"if ({compiledExpression}) {{"); - - ExportStatement(); - } - - private void STOP() - { - // Statement.STOP(); - // Statement.STOP(error, status); - Compiled.Append("Statement.STOP("); - Continue(2); - - if (CurrentEquals(".")) - { - Compiled.Append(");"); - ExportStatement(); - return; - } - - if (CurrentEquals("WITH")) - Continue(1); - - if (CurrentEquals("NORMAL")) - Compiled.Append("false, "); - - if (CurrentEquals("ERROR")) - Compiled.Append("true, "); - - Continue(1); - if (CurrentEquals(".")) - { - Compiled.Append("\"0\");"); - ExportStatement(); - return; - } - - if (CurrentEquals("STATUS")) - { - Continue(1); - } - - switch (Current().Type) - { - case TokenType.Identifier: - Compiled.Append($"{FormatIdentifier(Current().Value)}.Display);"); - break; - case TokenType.Numeric: - Compiled.Append($"\"{Current().Value}\");"); - break; - case TokenType.String: - Compiled.Append($"{Current().Value});"); - break; - } - ExportStatement(); - } - - // Statement builder helper methods. - private static string FormatIdentifier(string Identifier) - { - string FormattedIdentifier = Identifier; - FormattedIdentifier = "_" + FormattedIdentifier.Replace("-", "_"); - return FormattedIdentifier; - } -} diff --git a/Otterkit.CodeGenerators/src/Builders/VariableBuilder.cs b/Otterkit.CodeGenerators/src/Builders/VariableBuilder.cs deleted file mode 100644 index 0f070037..00000000 --- a/Otterkit.CodeGenerators/src/Builders/VariableBuilder.cs +++ /dev/null @@ -1,297 +0,0 @@ -using static Otterkit.Types.CompilerContext; -using static Otterkit.Types.TokenHandling; -using Otterkit.Analyzers; -using Otterkit.Types; -using System.Text; - -namespace Otterkit.CodeGenerators; - -public class VariableBuilder -{ - private readonly StringBuilder Compiled = new(); - private string Identifier = string.Empty; - private string DataType = string.Empty; - private int Length = 0; - private int FractionalLength = 0; - private SourceScope Section; - private readonly ProgramBuilder Builder; - - public VariableBuilder(ProgramBuilder builder) - { - Builder = builder; - } - - public void ExportVariable() - { - if (Section == SourceScope.WorkingStorage) - Builder.Append(Compiled); - - if (Section == SourceScope.LocalStorage) - Builder.Append(Compiled); - } - - public void BuildVariable(SourceScope section = SourceScope.WorkingStorage) - { - Section = section; - - var token = Peek(1); - - var id = Builder.Name.Unwrap(); - - var callable = ActiveNames.Fetch(id); - - var variable = callable.DataNames.FetchUnique(token); - - if (variable.LevelNumber is 77 or > 0 and < 50) - { - BuildVariable(variable, token); - ExportVariable(); - return; - } - - if (variable.IsConstant) - { - BuildConstant(); - ExportVariable(); - return; - } - } - - private void BuildConstant() - { - string sectionAccessModifier = string.Empty; - - if (Section == SourceScope.WorkingStorage) - Compiled.Append($"private static readonly Constant {FormatIdentifier(Identifier)} = "); - - if (Section == SourceScope.LocalStorage) - Compiled.Append($"private readonly Constant {FormatIdentifier(Identifier)} = "); - - while (!CurrentEquals("AS")) Continue(1); - - Continue(1); - - if (CurrentEquals("LENGTH")) - { - Continue(1); - if (CurrentEquals("OF")) Continue(1); - - string FormattedValue = FormatIdentifier(Current().Value); - Compiled.Append($"new(Encoding.UTF8.GetBytes({FormattedValue}.Length.ToString()));"); - } - - if (CurrentEquals("BYTE-LENGTH")) - { - Continue(1); - if (CurrentEquals("OF")) Continue(1); - - string FormattedValue = FormatIdentifier(Current().Value); - Compiled.Append($"new(Encoding.UTF8.GetBytes({FormattedValue}.Bytes.Length.ToString()));"); - } - - if (Current().Type == TokenType.String) - Compiled.Append($"new({Current().Value}u8);"); - - if (Current().Type == TokenType.Numeric) - Compiled.Append($"new(\"{Current().Value}\"u8);"); - - Continue(1); - - if (!CurrentEquals(".")) - throw new ArgumentException("Unexpected Input: Constant must end with a separator period"); - - } - - private static int Offset = 0; - private static string GroupName = string.Empty; - - private void BuildVariable(DataEntry variable, Token token) - { - bool isSigned = false; - - var type = variable.Class switch - { - Classes.Alphabetic => "Alphabetic", - Classes.Alphanumeric => "Alphanumeric", - Classes.Boolean => "Bit", - Classes.Index => "Index", - Classes.MessageTag => "MessageTag", - Classes.National => "National", - Classes.Numeric => "Numeric", - Classes.Object => "ObjectReference", - Classes.Pointer => "Pointer", - _ => "Alphanumeric", - }; - - while (!CurrentEquals(".")) Continue(); - - var length = variable.Length; - - var formatted = FormatIdentifier(token.Value); - - if (variable.LevelNumber is 1) Offset = 0; - - if (variable.LevelNumber is 1 && variable.IsGroup) - { - Compiled.Append($"public static OtterMemory _{formatted} = new({length});"); - - GroupName = formatted; - } - - if (Section == SourceScope.WorkingStorage) - { - Compiled.Append($"private static {type} {formatted} = "); - } - - if (Section == SourceScope.LocalStorage) - { - Compiled.Append($"private {DataType} {formatted} = "); - } - - var hasValue = variable[DataClause.Value]; - - if (hasValue) - { - ReadOnlySpan value = variable.FetchValue().Value; - - if (type is "Alphabetic" or "Alphanumeric" or "National" or "Bit" && !variable.IsGroup) - { - Compiled.Append($"new({value}u8, new({length}), {Offset}, {length});"); - - Offset += length; - - return; - } - - if (type is "Alphanumeric" or "National" or "Bit" && variable.IsGroup) - { - Compiled.Append($"new(_{formatted}, {Offset}, {length});"); - - return; - } - - if (type is "Numeric") - { - int TotalLength = FractionalLength == 0 ? Length : Length + FractionalLength + 1; - - if (isSigned) - { - if (value.IndexOfAny("+-") != 1) { }; - - TotalLength = FractionalLength == 0 ? Length : Length + FractionalLength + 2; - - Compiled.Append($"new({value}u8, 0, {Length}, {FractionalLength}, new byte[{TotalLength}]);"); - return; - } - - Compiled.Append($"new({value}u8, 0, {Length}, {FractionalLength}, new byte[{TotalLength}]);"); - return; - } - - if (type is "ObjectReference") - { - Compiled.Append($"new({value}u8, new({Length}), 0, {Length});"); - return; - } - - if (type is "Index") - { - Compiled.Append($"new({value}u8, 0, {Length}, new byte[{Length}]);"); - return; - } - - if (type is "MessageTag") - { - Compiled.Append($"new({value}u8, 0, {Length}, new byte[{Length}]);"); - return; - } - - if (type is "Pointer") - { - Compiled.Append($"new({value}u8, 0, {Length}, new byte[{Length}]);"); - return; - } - } - else - { - if (type is "Alphabetic" or "Alphanumeric" or "National" or "Bit" && !variable.IsGroup && variable.LevelNumber is 1) - { - Compiled.Append($"new(\" \"u8, new({length}), {Offset}, {length});"); - return; - } - - if (type is "Alphabetic" or "Alphanumeric" or "National" or "Bit" && !variable.IsGroup) - { - Compiled.Append($"new(\" \"u8, _{GroupName}, {Offset}, {length});"); - - Offset += length; - - return; - } - - if (type is "Alphanumeric" or "National" or "Bit" && variable.IsGroup) - { - Compiled.Append($"new(_{GroupName}, {Offset}, {length});"); - - return; - } - - if (type is "Numeric") - { - int TotalLength = FractionalLength == 0 ? Length : Length + FractionalLength + 1; - - if (isSigned) - { - TotalLength = FractionalLength == 0 ? Length : Length + FractionalLength + 2; - - Compiled.Append($"new(\" \"u8, 0, {Length}, {FractionalLength}, new byte[{TotalLength}]);"); - return; - } - - Compiled.Append($"new(\" \"u8, 0, {Length}, {FractionalLength}, new byte[{TotalLength}]);"); - return; - } - - if (type is "ObjectReference") - { - Compiled.Append($"new(\" \"u8, new({Length}), 0, {Length});"); - return; - } - - if (type is "Index") - { - Compiled.Append($"new(\" \"u8, 0, {Length}, new byte[{Length}]);"); - return; - } - - if (type is "MessageTag") - { - Compiled.Append($"new(\" \"u8, 0, {Length}, new byte[{Length}]);"); - return; - } - - if (type is "Pointer") - { - Compiled.Append($"new(\" \"u8, 0, {Length}, new byte[{Length}]);"); - return; - } - } - } - - public string FormatIdentifier(string Identification) - { - return string.Create(Identification.Length + 1, Identification, (span, value) => - { - span[0] = '_'; - - for (int i = 0; i < value.Length; i++) - { - span[i + 1] = value[i] switch - { - '-' => '_', - _ => value[i], - }; - } - }); - } -} diff --git a/Otterkit.CodeGenerators/src/CodeGenerator.cs b/Otterkit.CodeGenerators/src/CodeGenerator.cs deleted file mode 100644 index c3144e2b..00000000 --- a/Otterkit.CodeGenerators/src/CodeGenerator.cs +++ /dev/null @@ -1,84 +0,0 @@ -using static Otterkit.Types.TokenHandling; -using Otterkit.Types; - -namespace Otterkit.CodeGenerators; - -public static class CodeGenerator -{ - private static string Main = string.Empty; - private static bool HasHeader = false; - - public static void Generate(List tokens, string fileName) - { - ProgramBuilder compiled = new(); - - if (!HasHeader) - { - compiled.AppendHeader(); - - HasHeader = true; - } - - while (Current().Scope is not TokenScope.EnvironmentDivision and not TokenScope.DataDivision and not TokenScope.ProcedureDivision) - { - if (CurrentEquals("PROGRAM-ID")) - { - compiled.FormatIdentification(Peek(2)); - - if (Main == string.Empty) Main = compiled.Identification.Unwrap(); - } - - if (CurrentEquals("FUNCTION-ID")) - { - compiled.FormatIdentification(Peek(2)); - } - - Continue(); - } - - compiled.AppendIdentification(); - - SourceScope scope = SourceScope.WorkingStorage; - - while (Current().Scope is not TokenScope.ProcedureDivision) - { - if (CurrentEquals("WORKING-STORAGE")) - scope = SourceScope.WorkingStorage; - - if (CurrentEquals("LOCAL-STORAGE")) - scope = SourceScope.LocalStorage; - - if (Current().Type == TokenType.Numeric) - { - VariableBuilder variable = new(compiled); - - variable.BuildVariable(scope); - } - - Continue(); - } - - compiled.InitializeProcedure(); - - while (Current().Scope == TokenScope.ProcedureDivision && !CurrentEquals(TokenContext.IsEOF)) - { - if (CurrentEquals(TokenContext.IsStatement)) - { - StatementBuilder statement = new(compiled); - - statement.BuildStatement(); - } - - Continue(); - } - - compiled.FinalizeProcedure(); - - File.WriteAllText($".otterkit/Artifacts/Source.cs", compiled.ExportCompiled()); - - string startupCode = $"using Otterkit.Runtime;using OtterkitExport;{Main}.Procedure();"; - - File.WriteAllText(".otterkit/Artifacts/Main.cs", startupCode); - } - -} \ No newline at end of file diff --git a/Otterkit.Tokenizers/Otterkit.Tokenizers.csproj b/Otterkit.Tokenizers/Otterkit.Tokenizers.csproj deleted file mode 100644 index be7b7f60..00000000 --- a/Otterkit.Tokenizers/Otterkit.Tokenizers.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - - - - - true - Otterkit.Tokenizers - ./nupkg - Apache-2.0 - 1.0.70 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Compiler;Tokenizers - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains the Standard COBOL tokenizer for the Otterkit compiler. - - - - - - - - - - - - - - diff --git a/Otterkit.Tokenizers/README.md b/Otterkit.Tokenizers/README.md deleted file mode 100644 index f245000a..00000000 --- a/Otterkit.Tokenizers/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Otterkit.Tokenizers namespace - -This namespace contains the Standard COBOL tokenizer -for the Otterkit compiler. - diff --git a/Otterkit.Tokenizers/src/Tokenizer.Lexer.cs b/Otterkit.Tokenizers/src/Tokenizer.Lexer.cs deleted file mode 100644 index 7d24a933..00000000 --- a/Otterkit.Tokenizers/src/Tokenizer.Lexer.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System.Text; -using System.Text.RegularExpressions; -using Otterkit.Types; - -namespace Otterkit.Tokenizers; - -public static partial class Tokenizer -{ - /* - ** Explaining the big regex pattern: - ** - ** < wordsPattern > : Matches all COBOL reserved keywords, - ** intrinsic function names and identifiers - ** - ** < stringPattern > : - ** Matches all strings including fixed format continuation lines, - ** where the string ends without closing the quote and continues - ** with a -" on the next line. Useful for preserving string formatting - ** - ** < symbolPattern > : Matches all COBOL special characters and their valid - ** combinations - ** - ** < numberPattern > : Matches signed and unsigned number literals, including - ** decimal numbers that might start with 0. or just . - */ - private const string StringPattern = "(X|B|BX|N|NX)*(\"|\')(.*?)(\"-?|\'-?|$)"; - private const string WordsPattern = @"|[a-zA-Z]+([-|_]*[\w0-9]+)*|[0-9]+([-|_][\w0-9]+)+"; - private const string NumberPattern = @"|(\+|-)?\.?[0-9]\d*(\.\d+)?"; - private const string DirectivesPattern = "|^.*(>>[A-Z]*(-[A-Z0-9]*)*).*$"; - private const string SymbolPattern = @"|(\+|\-|\*\*|\*|=|\/|\$|,|;|::|\.|\(|\)|>>|<>|>=|<=|>|<|&|_)"; - private const string AllPatterns = StringPattern + WordsPattern + NumberPattern + DirectivesPattern + SymbolPattern; - - private static bool IsPictureNext; - - private static void TokenizeLine(List sourceTokens, ReadOnlySpan bytes, int lineIndex) - { - var charCount = Encoding.UTF8.GetCharCount(bytes); - var maxStackLimit = 256; - - Span sourceChars = charCount <= maxStackLimit - ? stackalloc char[charCount] - : new char[charCount]; - - PreprocessSourceFormat(bytes, sourceChars); - - var pictureEndIndex = 0; - - var fileIndex = CompilerContext.FileNames.Count - 1; - - foreach (var token in LexerRegex().EnumerateMatches(sourceChars)) - { - ReadOnlySpan current = sourceChars.Slice(token.Index, token.Length); - - if (token.Index < pictureEndIndex) continue; - - if (current.Contains(">>", StringComparison.OrdinalIgnoreCase)) - { - PreprocessDirective(current, lineIndex); - continue; - } - - if (IsPictureNext && !current.Equals("IS", StringComparison.OrdinalIgnoreCase)) - { - var temporary = sourceChars.Slice(token.Index, sourceChars.Length - token.Index); - - var regex = PictureEndRegex().EnumerateMatches(temporary); - - regex.MoveNext(); - - var matchIndex = regex.Current.Index; - - var pictureChars = temporary.Slice(0, matchIndex); - - if (matchIndex is 0) - { - pictureChars = temporary; - } - - Token picture = new(new string(pictureChars), TokenType.Picture) - { - Line = lineIndex, - Column = token.Index + 1, - FileIndex = fileIndex - }; - - sourceTokens.Add(picture); - - pictureEndIndex = pictureChars.Length + token.Index; - - IsPictureNext = false; - - continue; - } - - IsPictureNext = IsPictureNext || current[0] is 'P' or 'p' && (CurrentEquals(current, "PIC") || CurrentEquals(current, "PICTURE")); - - TokenType type = current switch - { - ['"' or '\'', .. _, '"' or '\'', '-'] or - ['"' or '\'', .. _, '"' or '\''] or - ['"' or '\'', .. _] => TokenType.String, - - ['X' or 'x', '"' or '\'', .. _, '"' or '\'', '-'] or - ['X' or 'x', '"' or '\'', .. _, '"' or '\''] or - ['X' or 'x', '"' or '\'', .. _] => TokenType.HexString, - - ['B' or 'b', '"' or '\'', .. _, '"' or '\'', '-'] or - ['B' or 'b', '"' or '\'', .. _, '"' or '\''] or - ['B' or 'b', '"' or '\'', .. _] => TokenType.Boolean, - - ['B' or 'B', 'X' or 'x', '"' or '\'', .. _, '"' or '\'', '-'] or - ['B' or 'B', 'X' or 'x', '"' or '\'', .. _, '"' or '\''] or - ['B' or 'B', 'X' or 'x', '"' or '\'', .. _] => TokenType.HexBoolean, - - ['N' or 'n', '"' or '\'', .. _, '"' or '\'',] => TokenType.National, - - ['N' or 'n', 'X' or 'x', '"' or '\'', .. _, '"' or '\'',] => TokenType.HexNational, - - [..] => TokenType.None - }; - - if (type is not TokenType.None) - { - Token stringLiteral = new(new string(current), type) - { - Line = lineIndex, - Column = token.Index + 1, - FileIndex = fileIndex - }; - - sourceTokens.Add(stringLiteral); - - continue; - } - - Token tokenized = new(new string(current), type) - { - Line = lineIndex, - Column = token.Index + 1, - FileIndex = fileIndex - }; - - sourceTokens.Add(tokenized); - } - } - - private static bool CurrentEquals(ReadOnlySpan match, ReadOnlySpan value) - { - return match.Equals(value, StringComparison.OrdinalIgnoreCase); - } - - [GeneratedRegex(AllPatterns, RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] - private static partial Regex LexerRegex(); - - [GeneratedRegex("""(\s|\.\s)""", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] - private static partial Regex PictureEndRegex(); -} diff --git a/Otterkit.Tokenizers/src/Tokenizer.Pipelines.cs b/Otterkit.Tokenizers/src/Tokenizer.Pipelines.cs deleted file mode 100644 index bee21571..00000000 --- a/Otterkit.Tokenizers/src/Tokenizer.Pipelines.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System.Buffers; -using System.IO.Pipelines; -using System.Text; -using Otterkit.Types; - -namespace Otterkit.Tokenizers; - -public static partial class Tokenizer -{ - private static readonly ArrayPool ArrayPool = ArrayPool.Shared; - - private static async ValueTask> ReadSourceFile(string sourceFile) - { - using var stream = File.OpenRead(sourceFile); - - var reader = PipeReader.Create(stream); - - var read = await reader.ReadAsync(); - - while (!read.IsCompleted) - { - read = await reader.ReadAsync(); - - reader.AdvanceTo(read.Buffer.Start, read.Buffer.End); - } - - var buffer = read.Buffer; - - var lineIndex = 1; - - var tokens = CompilerContext.SourceTokens; - - while (SourceLineExists(ref buffer, out ReadOnlySequence line)) - { - var length = (int)line.Length; - var array = ArrayPool.Rent(length + 1); - - line.CopyTo(array); - - ProcessLinebreak(array, length); - - TokenizeLine(tokens, array.AsSpan(0, length + 1), lineIndex); - - ArrayPool.Return(array); - - lineIndex++; - } - - reader.AdvanceTo(buffer.End); - - tokens.Add(new Token("EOF", TokenType.EOF, -5, -5) { Context = TokenContext.IsEOF }); - - return tokens; - } - - private static async ValueTask> ReadCopybook(string copybookFile) - { - using var stream = File.OpenRead(copybookFile); - - var reader = PipeReader.Create(stream); - - var read = await reader.ReadAsync(); - - while (!read.IsCompleted) - { - read = await reader.ReadAsync(); - - reader.AdvanceTo(read.Buffer.Start, read.Buffer.End); - } - - var buffer = read.Buffer; - - var lineIndex = 1; - - List tokens = new(); - - while (SourceLineExists(ref buffer, out ReadOnlySequence line)) - { - var length = (int)line.Length; - var array = ArrayPool.Rent(length + 1); - - line.CopyTo(array); - - ProcessLinebreak(array, length); - - TokenizeLine(tokens, array.AsSpan(0, length + 1), lineIndex); - - ArrayPool.Return(array); - - lineIndex++; - } - - reader.AdvanceTo(buffer.End); - - return tokens; - } - - private static bool SourceLineExists(ref ReadOnlySequence buffer, out ReadOnlySequence line) - { - // UTF-8 LINE FEED (LF) has value 10 (0x0A). - var lineFeed = buffer.PositionOf(10); - - if (lineFeed is not null) - { - var length = lineFeed.Value; - - line = buffer.Slice(0, length); - - buffer = buffer.Slice(buffer.GetPosition(1, length)); - - return true; - } - - if (!buffer.IsEmpty) - { - line = buffer.Slice(0, buffer.Length); - - buffer = buffer.Slice(buffer.End); - - return true; - } - - line = ReadOnlySequence.Empty; - - return false; - } - - private static void ProcessLinebreak(Span line, int length) - { - if (length == 0) - { - line[length] = 32; - return; - } - - // We want to remove the CARRIAGE RETURN (CR) if present. - var carriageReturn = line[length - 1]; - - // We'll replace it with a space. - // UTF-8 SPACE has value 32 (0x20). - - // UTF-8 CARRIAGE RETURN (CR) has value 13 (0x0D). - if (carriageReturn == 13) line[length - 1] = 32; - - line[length] = 32; - } -} diff --git a/Otterkit.Tokenizers/src/Tokenizer.Preprocessor.cs b/Otterkit.Tokenizers/src/Tokenizer.Preprocessor.cs deleted file mode 100644 index e00caae4..00000000 --- a/Otterkit.Tokenizers/src/Tokenizer.Preprocessor.cs +++ /dev/null @@ -1,220 +0,0 @@ -using System.Text.RegularExpressions; -using System.Text; -using Otterkit.Types; - -namespace Otterkit.Tokenizers; - -public static partial class Tokenizer -{ - private static void PreprocessSourceFormat(ReadOnlySpan bytes, Span chars) - { - var charCount = Encoding.UTF8.GetCharCount(bytes); - var maxStackLimit = 256; - - Span sourceChars = charCount <= maxStackLimit - ? stackalloc char[charCount] - : new char[charCount]; - - Encoding.UTF8.GetChars(bytes, sourceChars); - - if (CompilerOptions.Format is not SourceFormat.Auto) - { - HasDetectedSourceFormat = true; - } - - if (!HasDetectedSourceFormat && CompilerOptions.Format is SourceFormat.Auto) - { - if (sourceChars.Length >= 15 && sourceChars.Slice(7, 8).StartsWith(">>SOURCE")) - { - CompilerOptions.Format = SourceFormat.Fixed; - HasDetectedSourceFormat = true; - } - - if (sourceChars.Length >= 7 && sourceChars[6] is '*' or '-' or '/' or ' ') - { - CompilerOptions.Format = SourceFormat.Fixed; - HasDetectedSourceFormat = true; - } - else - { - CompilerOptions.Format = SourceFormat.Free; - HasDetectedSourceFormat = true; - } - - if (sourceChars.Slice(0, 7).Trim().StartsWith("*>")) - { - CompilerOptions.Format = SourceFormat.Free; - HasDetectedSourceFormat = true; - } - - if (sourceChars.Slice(0, 7).Trim().StartsWith(">>")) - { - CompilerOptions.Format = SourceFormat.Free; - HasDetectedSourceFormat = true; - } - - if (sourceChars.Trim().Length == 0) - { - CompilerOptions.Format = SourceFormat.Auto; - HasDetectedSourceFormat = false; - } - } - - if (CompilerOptions.Format is SourceFormat.Fixed || !HasDetectedSourceFormat) - { - if (sourceChars.Length >= CompilerOptions.Columns) - { - // Removes everything after the max column length - sourceChars.Slice(CompilerOptions.Columns).Fill(' '); - } - - // Removes the sequence number area - if (sourceChars.Length >= 7) - { - sourceChars.Slice(0, 6).Fill(' '); - } - else - { - sourceChars.Fill(' '); - } - - if (sourceChars.Length >= 7 && sourceChars[6].Equals('*')) - { - // Removes all fixed format comment lines - sourceChars.Fill(' '); - } - - int commentIndex = sourceChars.IndexOf("*>"); - if (commentIndex > -1) - { - // Removes all floating comments - sourceChars = sourceChars.Slice(0, commentIndex); - } - - if (sourceChars.Length >= 1) - { - sourceChars[0] = ' '; - } - } - - if (CompilerOptions.Format is SourceFormat.Free) - { - int commentIndex = sourceChars.IndexOf("*>"); - if (commentIndex > -1) - { - // Removes all floating comments - sourceChars = sourceChars.Slice(0, commentIndex); - } - } - - sourceChars.CopyTo(chars); - } - - private static void PreprocessDirective(ReadOnlySpan directiveChars, int lineNumber) - { - List directiveTokens = new(); - var index = 0; - - foreach (var token in PreprocessorRegex().EnumerateMatches(directiveChars)) - { - ReadOnlySpan currentMatch = directiveChars.Slice(token.Index, token.Length); - - DirectiveToken tokenized = new(new string(currentMatch), lineNumber); - directiveTokens.Add(tokenized); - } - - if (CurrentEquals(">>SOURCE")) - { - Continue(); - - LastDirective = DirectiveType.SourceFormat; - - if (CurrentEquals("FORMAT")) Continue(); - - if (CurrentEquals("IS")) Continue(); - - if (CurrentEquals("FREE")) - { - CompilerOptions.Format = SourceFormat.Free; - } - - if (CurrentEquals("FIXED")) - { - CompilerOptions.Format = SourceFormat.Fixed; - } - } - - DirectiveToken Current() - { - return directiveTokens[index]; - } - - bool CurrentEquals(string stringToCompare) - { - return Current().value.Equals(stringToCompare, StringComparison.OrdinalIgnoreCase); - } - - void Continue() - { - if (index >= directiveTokens.Count - 1) return; - - index += 1; - } - } - - private static void PreprocessCopybooks(List sourceTokens) - { - var tokenIndex = 0; - - while (!(tokenIndex >= sourceTokens.Count - 1)) - { - if (!CurrentEquals("COPY")) - { - Continue(); - continue; - } - - if (CurrentEquals("COPY")) - { - var statementIndex = tokenIndex; - - Continue(); - - var copybookName = Current().Value; - - CompilerContext.FileNames.Add(copybookName); - - var copybookTokens = ReadCopybook(copybookName).Result; - - Continue(); - - var currentIndex = tokenIndex; - - CompilerContext.SourceTokens.RemoveRange(statementIndex, currentIndex - statementIndex); - - CompilerContext.SourceTokens.InsertRange(statementIndex, copybookTokens); - - } - } - - Token Current() - { - return sourceTokens[tokenIndex]; - } - - bool CurrentEquals(string stringToCompare) - { - return Current().Value.Equals(stringToCompare, StringComparison.OrdinalIgnoreCase); - } - - void Continue() - { - if (tokenIndex >= sourceTokens.Count - 1) return; - - tokenIndex += 1; - } - } - - [GeneratedRegex("""(>>[A-Z]*(-[A-Z0-9]*)*)|[a-zA-Z]+([-|_]*[a-zA-Z0-9]+)*""", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] - private static partial Regex PreprocessorRegex(); -} diff --git a/Otterkit.Tokenizers/src/Tokenizer.cs b/Otterkit.Tokenizers/src/Tokenizer.cs deleted file mode 100644 index e056ab03..00000000 --- a/Otterkit.Tokenizers/src/Tokenizer.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit.Tokenizers; - -public static partial class Tokenizer -{ - internal static DirectiveType LastDirective; - internal static bool HasDetectedSourceFormat; - internal static string Workspace => Directory.GetCurrentDirectory(); - - public static List Tokenize(string entryPoint) - { - if (!File.Exists(entryPoint)) - { - ErrorHandler - .Build(ErrorType.Compilation, ConsoleColor.Red, 950, """ - Entry point file not found. - """) - .WithStartingError($""" - Unable to find the entry point file specified: {entryPoint} - """) - .CloseError(); - - Environment.Exit(1); - } - - var relativeEntryPoint = Path.GetRelativePath(Workspace, entryPoint); - - CompilerOptions.Main = relativeEntryPoint; - - var allSourceFiles = Directory.EnumerateFiles(Workspace, "*.cob", SearchOption.AllDirectories) - .Select(static path => Path.GetRelativePath(Workspace, path)); - - CompilerContext.FileNames.Add(relativeEntryPoint); - - var tokens = ReadSourceFile(relativeEntryPoint).Result; - - foreach (var file in allSourceFiles) - { - if (file.Equals(relativeEntryPoint)) continue; - - CompilerContext.FileNames.Add(file); - - tokens = ReadSourceFile(file).Result; - } - - PreprocessCopybooks(CompilerContext.SourceTokens); - - return CompilerContext.SourceTokens; - } -} diff --git a/Otterkit.Types/Otterkit.Types.csproj b/Otterkit.Types/Otterkit.Types.csproj deleted file mode 100644 index 4a86b98c..00000000 --- a/Otterkit.Types/Otterkit.Types.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - true - - - - - true - Otterkit.Types - ./nupkg - Apache-2.0 - 1.0.70 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Compiler;Types - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains internal types for the Otterkit compiler. - - - - - - - - - diff --git a/Otterkit.Types/README.md b/Otterkit.Types/README.md deleted file mode 100644 index a07da028..00000000 --- a/Otterkit.Types/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Otterkit.Types namespace - -This namespace contains internal compiler types for Otterkit, -as well as some utility and helper classes. - diff --git a/Otterkit.Types/src/Compact.cs b/Otterkit.Types/src/Compact.cs deleted file mode 100644 index 16521cea..00000000 --- a/Otterkit.Types/src/Compact.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections; - -namespace Otterkit.Types; - -public sealed class Compact : - IEnumerable - where TValue : notnull -{ - private readonly TValue[] CompactArray; - public int Length => CompactArray.Length; - - public Compact() - { - CompactArray = new TValue[1]; - } - - public Compact(int capacity) - { - CompactArray = new TValue[capacity]; - } - - public TValue this[int index] - { - get => CompactArray[index]; - - set => CompactArray[index] = value; - } - - public IEnumerable GetEnumerable() - { - return CompactArray; - } - - public IEnumerator GetEnumerator() - { - return GetEnumerable().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return CompactArray.GetEnumerator(); - } -} diff --git a/Otterkit.Types/src/CompilerContext.cs b/Otterkit.Types/src/CompilerContext.cs deleted file mode 100644 index 30d704b4..00000000 --- a/Otterkit.Types/src/CompilerContext.cs +++ /dev/null @@ -1,65 +0,0 @@ -namespace Otterkit.Types; - -public static class CompilerContext -{ - /// - /// Used for storing the file names of all current compilation units. - /// It also includes the names of all copybook files. - /// - public static readonly List FileNames = new(); - - /// - /// Used for storing the tokens of all current compilation units. - /// Each of them is separated by an EOF token. - /// - public static readonly List SourceTokens = new(); - - /// - /// Used for keeping track of which scope is being parsed. - /// Scope meaning the current division, section or paragragh. - /// - public static SourceScope ActiveScope { get; set; } - - /// - /// Used for keeping track of where the current source unit was defined, including its containing parent. - /// We store the token itself, because it already stores where it was written. - /// - public static readonly Stack ActiveUnits = new(); - - /// - /// Used for keeping track of the source unit types, including the type of its containing parent. - /// - public static readonly Stack SourceTypes = new(); - - /// - /// Used for storing the current source unit signature. - /// - private static Option StoredCallable; - - /// - /// Used for storing all the active global names (AKA the global symbol table). - /// - public static readonly GlobalNames ActiveNames = new(); - - /// - /// Used for getting and setting the signature of the source unit currently being parsed. - /// - public static CallableUnit ActiveCallable - { - get => (CallableUnit)StoredCallable; - - set => StoredCallable = value; - } - - public static DataNames ActiveData - { - get => ActiveCallable.DataNames; - } - - public static bool IsResolutionPass { get; set; } - - /// - /// Used for checking if third-party COBOL extensions are enabled. - /// - public static bool ExtensionsEnabled { get; set; } -} diff --git a/Otterkit.Types/src/CompilerEnums.cs b/Otterkit.Types/src/CompilerEnums.cs deleted file mode 100644 index da5fc23f..00000000 --- a/Otterkit.Types/src/CompilerEnums.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Otterkit.Types; - -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum SourceFormat -{ - Auto, - Fixed, - Free, -} - -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum BuildType -{ - LexOnly, - ParseOnly, - PrintTokens, - PrintSymbols, - BuildOnly, - BuildAndRun, - GenerateOnly, -} - -[JsonConverter(typeof(JsonStringEnumConverter))] -public enum OutputType -{ - Application, - Library, -} diff --git a/Otterkit.Types/src/CompilerOptions.cs b/Otterkit.Types/src/CompilerOptions.cs deleted file mode 100644 index abf78acc..00000000 --- a/Otterkit.Types/src/CompilerOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Otterkit.Types; - -public static class CompilerOptions -{ - public static string Name = "OtterkitExport"; - public static string Main = "main.cob"; - public static OutputType Output = OutputType.Application; - public static SourceFormat Format = SourceFormat.Auto; - public static BuildType Mode = BuildType.BuildOnly; - public static int Columns = 80; - - public static void Initialize(string name, string main) - { - Name = name; - Main = main; - } - - public static void SetOptions(OutputType output, SourceFormat format, int columns) - { - Output = output; - Format = format; - Columns = columns; - } -} diff --git a/Otterkit.Types/src/DirectiveToken/DirectiveToken.Methods.cs b/Otterkit.Types/src/DirectiveToken/DirectiveToken.Methods.cs deleted file mode 100644 index 7936523e..00000000 --- a/Otterkit.Types/src/DirectiveToken/DirectiveToken.Methods.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Text; - -namespace Otterkit.Types; - -public sealed partial record DirectiveToken -{ - public override sealed string ToString() - { - StringBuilder stringBuilder = new(); - stringBuilder.Append("DirectiveToken"); - stringBuilder.Append(" { "); - - stringBuilder.Append($"Ln: {line, -6},"); - stringBuilder.Append($"Value: {value}"); - - stringBuilder.Append(" }"); - return stringBuilder.ToString(); - } -} diff --git a/Otterkit.Types/src/DirectiveToken/DirectiveToken.cs b/Otterkit.Types/src/DirectiveToken/DirectiveToken.cs deleted file mode 100644 index 5941dcd9..00000000 --- a/Otterkit.Types/src/DirectiveToken/DirectiveToken.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Otterkit.Types; - -public sealed partial record DirectiveToken -{ - public int line; - public string value; - - public DirectiveToken(string value, int line) - { - this.value = value; - this.line = line; - } -} diff --git a/Otterkit.Types/src/DirectiveToken/DirectiveType.cs b/Otterkit.Types/src/DirectiveToken/DirectiveType.cs deleted file mode 100644 index b4580c3e..00000000 --- a/Otterkit.Types/src/DirectiveToken/DirectiveType.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Otterkit.Types; - -public enum DirectiveType -{ - None, - SourceFormat, -} diff --git a/Otterkit.Types/src/EntryTypes/AbstractEntry.cs b/Otterkit.Types/src/EntryTypes/AbstractEntry.cs deleted file mode 100644 index f2663acf..00000000 --- a/Otterkit.Types/src/EntryTypes/AbstractEntry.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Otterkit.Types; - -public abstract class AbstractEntry -{ - public Option Identifier; - public EntryKind EntryKind; - - protected ulong BitField; - public int DeclarationIndex; - - protected AbstractEntry(Token identifier, EntryKind entryKind) - { - Identifier = identifier; - EntryKind = entryKind; - } - - protected void SetBit(int position, bool bit) - { - var mask = 1UL << position - 1; - - if (bit) - { - BitField |= mask; - return; - } - - BitField &= ~mask; - } - - protected bool GetBit(int position) - { - var bit = (BitField >> (position - 1)) & 1; - - return bit == 1UL; - } -} diff --git a/Otterkit.Types/src/EntryTypes/DataEntry.cs b/Otterkit.Types/src/EntryTypes/DataEntry.cs deleted file mode 100644 index a123847f..00000000 --- a/Otterkit.Types/src/EntryTypes/DataEntry.cs +++ /dev/null @@ -1,199 +0,0 @@ -using static Otterkit.Types.TokenHandling; - -namespace Otterkit.Types; - -public partial class DataEntry : AbstractEntry -{ - public Option Parent; - public Option ExternalizedName; - - public SourceScope Section; - public int LevelNumber; - public int Length; - - public Classes Class; - public Categories Category; - public Usages Usage; - - public bool IsGroup; - public bool IsConstant; - - public DataEntry(Token identifier, EntryKind entryKind) - : base (identifier, entryKind) { } - - public bool this[DataClause clauseName] - { - get => GetBit((int)clauseName); - - set => SetBit((int)clauseName, value); - } - - public bool FetchTypedef() - { - var storedIndex = SetupClauseFetch(DataClause.Type); - - var isStrong = false; - - while (CurrentEquals(TokenContext.IsClause)) - { - if (CurrentEquals("TYPEDEF") && PeekEquals(1, "STRONG")) - { - isStrong = true; - break; - } - - Continue(); - } - - TokenHandling.Index = storedIndex; - - return isStrong; - } - - public Token FetchType() - { - var storedIndex = SetupClauseFetch(DataClause.Type); - - while (CurrentEquals(TokenContext.IsClause)) - { - if (CurrentEquals("TYPE") && PeekEquals(1, TokenType.Identifier)) - { - Continue(); - break; - } - - Continue(); - } - - var type = Current(); - - TokenHandling.Index = storedIndex; - - return type; - } - - public Token FetchGroupUsage() - { - var storedIndex = SetupClauseFetch(DataClause.GroupUsage); - - while (CurrentEquals(TokenContext.IsClause)) - { - if (CurrentEquals("GROUP-USAGE")) - { - Continue(); - Optional("IS"); - break; - } - - Continue(); - } - - var groupUsage = Current(); - - TokenHandling.Index = storedIndex; - - return groupUsage; - } - - public (Option, bool, bool) FetchObjectReference() - { - var storedIndex = SetupClauseFetch(DataClause.Usage); - - Option objectType = new(); - var isFactory = false; - var isOnly = false; - - while (CurrentEquals(TokenContext.IsClause)) - { - if (CurrentEquals("USAGE")) - { - Continue(); - Optional("IS"); - Continue(); - Continue(); - - if (CurrentEquals("FACTORY")) - { - Continue(); - Optional("OF"); - isFactory = true; - } - - if (CurrentEquals(TokenType.Identifier)) - { - objectType = Current(); - Continue(); - } - - if (CurrentEquals("ONLY")) - { - isOnly = true; - } - - break; - } - - Continue(); - } - - TokenHandling.Index = storedIndex; - - return (objectType, isFactory, isOnly); - } - - public Token FetchPicture() - { - var storedIndex = SetupClauseFetch(DataClause.Picture); - - while (CurrentEquals(TokenContext.IsClause)) - { - if (CurrentEquals("PICTURE PIC")) - { - Continue(); - Optional("IS"); - break; - } - - Continue(); - } - - var picture = Current(); - - TokenHandling.Index = storedIndex; - - return picture; - } - - public Token FetchValue() - { - var storedIndex = SetupClauseFetch(DataClause.Value); - - while (!CurrentEquals("VALUE VALUES")) - { - Continue(); - } - - Continue(); - Optional("IS"); - - var value = Current(); - - TokenHandling.Index = storedIndex; - - return value; - } - - private int SetupClauseFetch(DataClause clauseType) - { - if (!this[clauseType]) - { - throw new NullReferenceException("NOTE: Always check if clause is present before running this method."); - } - - var currentIndex = TokenHandling.Index; - - TokenHandling.Index = DeclarationIndex; - - return currentIndex; - } -} diff --git a/Otterkit.Types/src/EntryTypes/FileControlEntry.cs b/Otterkit.Types/src/EntryTypes/FileControlEntry.cs deleted file mode 100644 index fd581838..00000000 --- a/Otterkit.Types/src/EntryTypes/FileControlEntry.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit; - -public class FileControlEntry : AbstractEntry -{ - public Option ExternalizedName; - - public FileControlEntry(Token identifier, EntryKind entryKind) - : base (identifier, entryKind) { } -} diff --git a/Otterkit.Types/src/EntryTypes/RepositoryEntry.cs b/Otterkit.Types/src/EntryTypes/RepositoryEntry.cs deleted file mode 100644 index 6d8c4e92..00000000 --- a/Otterkit.Types/src/EntryTypes/RepositoryEntry.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit; - -public class RepositoryEntry : AbstractEntry -{ - public UnitKind SourceType; - - public RepositoryEntry(Token identifier, EntryKind entryKind) - : base (identifier, entryKind) { } - - public bool this[RepositoryClause clauseName] - { - get => GetBit((int)clauseName); - - set => SetBit((int)clauseName, value); - } -} diff --git a/Otterkit.Types/src/Enums/Categories.cs b/Otterkit.Types/src/Enums/Categories.cs deleted file mode 100644 index af62d8c5..00000000 --- a/Otterkit.Types/src/Enums/Categories.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum Categories -{ - Invalid, - Alphabetic, - Alphanumeric = 1 << 1, - AlphanumericEdited = 1 << 2, - Boolean = 1 << 3, - Index = 1 << 4, - MessageTag = 1 << 5, - National = 1 << 6, - NationalEdited = 1 << 7, - Numeric = 1 << 8, - NumericEdited = 1 << 9, - ObjectReference = 1 << 10, - DataPointer = 1 << 11, - FunctionPointer = 1 << 12, - ProgramPointer = 1 << 13 -} diff --git a/Otterkit.Types/src/Enums/Classes.cs b/Otterkit.Types/src/Enums/Classes.cs deleted file mode 100644 index 3202cf61..00000000 --- a/Otterkit.Types/src/Enums/Classes.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum Classes -{ - Invalid, - Alphabetic, - Alphanumeric = 1 << 1, - Boolean = 1 << 2, - Index = 1 << 3, - MessageTag = 1 << 4, - National = 1 << 5, - Numeric = 1 << 6, - Object = 1 << 7, - Pointer = 1 << 8 -} diff --git a/Otterkit.Types/src/Enums/DataClause.cs b/Otterkit.Types/src/Enums/DataClause.cs deleted file mode 100644 index 1cc5b823..00000000 --- a/Otterkit.Types/src/Enums/DataClause.cs +++ /dev/null @@ -1,70 +0,0 @@ -namespace Otterkit.Types; - -public enum DataClause -{ - None, - Aligned, - AnyLength, - Auto, - BackgroundColor, - Based, - Bell, - Blank, - BlankWhenZero, - Blink, - BlockContains, - Class, - Code, - CodeSet, - Column, - ConstantRecord, - Control, - Default, - Destination, - DynamicLength, - EntryName, - Erase, - External, - ForegroundColor, - Format, - From, - Full, - Global, - GroupIndicate, - GroupUsage, - Highlight, - Invalid, - Justified, - LevelNumber, - Linage, - Line, - Lowlight, - NextGroup, - Occurs, - Page, - Picture, - PresentWhen, - Property, - Record, - Redefines, - Renames, - Report, - Required, - ReverseVideo, - SameAs, - Secure, - SelectWhen, - Sign, - Source, - Sum, - Synchronized, - To, - Type, - Typedef, - Underline, - Usage, - Using, - ValidateStatus, - Value, - Varying -} diff --git a/Otterkit.Types/src/Enums/EntryKind.cs b/Otterkit.Types/src/Enums/EntryKind.cs deleted file mode 100644 index 6c430d2c..00000000 --- a/Otterkit.Types/src/Enums/EntryKind.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Otterkit.Types; - -public enum EntryKind -{ - None, - FileControl, - FileDescription, - ScreenDescription, - DataDescription, - ReportGroupDescription, - RepositoryEntry -} diff --git a/Otterkit.Types/src/Enums/EvaluateOperand.cs b/Otterkit.Types/src/Enums/EvaluateOperand.cs deleted file mode 100644 index 74fb873f..00000000 --- a/Otterkit.Types/src/Enums/EvaluateOperand.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Otterkit.Types; - -public enum EvaluateOperand -{ - Identifier, - Literal, - Arithmetic, - Boolean, - Range, - Condition, - TrueOrFalse, - Any, - Invalid -} diff --git a/Otterkit.Types/src/Enums/Identifiers.cs b/Otterkit.Types/src/Enums/Identifiers.cs deleted file mode 100644 index 1a1a9570..00000000 --- a/Otterkit.Types/src/Enums/Identifiers.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum Identifiers -{ - None, - Self, - Super = 1 << 1, - Function = 1 << 2, - NullObject = 1 << 3, - ObjectView = 1 << 4, - DataAddress = 1 << 5, - NullAddress = 1 << 6, - ReferenceMod = 1 << 7, - LinageCounter = 1 << 8, - ReportCounter = 1 << 9, - ProgramAddress = 1 << 10, - FunctionAddress = 1 << 11, - ExceptionObject = 1 << 12, - MethodInvocation = 1 << 13, -} diff --git a/Otterkit.Types/src/Enums/Names.cs b/Otterkit.Types/src/Enums/Names.cs deleted file mode 100644 index 0d427c22..00000000 --- a/Otterkit.Types/src/Enums/Names.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum Names -{ - None, - Alphabet, - Class = 1 << 1, - CompilationVariable = 1 << 2, - Condition = 1 << 3, - Constant = 1 << 4, - Data = 1 << 5, - Directive = 1 << 6, - DynamicLengthStructure = 1 << 7, - File = 1 << 8, - FunctionPrototype = 1 << 9, - Index = 1 << 10, - Interface = 1 << 11, - LevelNumber = 1 << 12, - Locale = 1 << 13, - Method = 1 << 14, - Mnemonic = 1 << 15, - ObjectClass = 1 << 16, - Ordering = 1 << 17, - Paragraph = 1 << 18, - Parameter = 1 << 19, - Program = 1 << 20, - ProgramPrototype = 1 << 21, - Property = 1 << 22, - RecordKey = 1 << 23, - Record = 1 << 24, - Report = 1 << 25, - Screen = 1 << 26, - Section = 1 << 27, - SymbolicCharacter = 1 << 28, - Type = 1 << 29, - UserFunction = 1 << 30, -} diff --git a/Otterkit.Types/src/Enums/RepositoryClause.cs b/Otterkit.Types/src/Enums/RepositoryClause.cs deleted file mode 100644 index cd3b9a47..00000000 --- a/Otterkit.Types/src/Enums/RepositoryClause.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Otterkit.Types; - -public enum RepositoryClause -{ - None, - External, - Expands, - Intrinsic -} diff --git a/Otterkit.Types/src/Enums/SourceScope.cs b/Otterkit.Types/src/Enums/SourceScope.cs deleted file mode 100644 index cf0f8dda..00000000 --- a/Otterkit.Types/src/Enums/SourceScope.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Otterkit.Types; - -public enum SourceScope -{ - ProgramId, - FunctionId, - InterfaceId, - ClassId, - MethodId, - EnvironmentDivision, - Repository, - FileControl, - DataDivision, - FileSection, - ReportSection, - ScreenSection, - WorkingStorage, - LocalStorage, - LinkageSection, - ProcedureDivision, - Factory, - Object, -} diff --git a/Otterkit.Types/src/Enums/UnitKind.cs b/Otterkit.Types/src/Enums/UnitKind.cs deleted file mode 100644 index 02bf05a7..00000000 --- a/Otterkit.Types/src/Enums/UnitKind.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Otterkit.Types; - -public enum UnitKind -{ - Program, - ProgramPrototype, - Function, - FunctionPrototype, - Interface, - MethodPrototype, - Class, - Factory, - Object, - Method, - MethodGetter, - MethodSetter, - Intrinsic -} diff --git a/Otterkit.Types/src/Enums/Usages.cs b/Otterkit.Types/src/Enums/Usages.cs deleted file mode 100644 index 7fc19309..00000000 --- a/Otterkit.Types/src/Enums/Usages.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum Usages -{ - None, - Binary, - BinaryChar = 1 << 1, - BinaryShort = 1 << 2, - BinaryLong = 1 << 3, - BinaryDouble = 1 << 4, - Bit = 1 << 5, - Computational = 1 << 6, - Display = 1 << 7, - FloatBinary32 = 1 << 8, - FloatBinary64 = 1 << 9, - FloatBinary128 = 1 << 10, - FloatDecimal16 = 1 << 11, - FloatDecimal32 = 1 << 12, - FloatExtended = 1 << 13, - FloatLong = 1 << 14, - FloatShort = 1 << 15, - Index = 1 << 16, - MessageTag = 1 << 17, - National = 1 << 18, - ObjectReference = 1 << 19, - PackedDecimal = 1 << 20, - DataPointer = 1 << 21, - FunctionPointer = 1 << 22, - ProgramPointer = 1 << 23 -} diff --git a/Otterkit.Types/src/ErrorHandler/ErrorHandler.Helpers.cs b/Otterkit.Types/src/ErrorHandler/ErrorHandler.Helpers.cs deleted file mode 100644 index 3c3b40c5..00000000 --- a/Otterkit.Types/src/ErrorHandler/ErrorHandler.Helpers.cs +++ /dev/null @@ -1,87 +0,0 @@ -namespace Otterkit.Types; - -public readonly ref partial struct ErrorHandler -{ - private readonly static ConsoleColor Green = ConsoleColor.Green; - private readonly static ConsoleColor DarkGray = ConsoleColor.DarkGray; - - private static void ColoredWrite(ConsoleColor consoleColor, string text) - { - Console.ForegroundColor = consoleColor; - Console.Write(text); - } - - private static ConsoleColor ResetColor() - { - Console.ResetColor(); - - return Console.ForegroundColor; - } - - private static void Separator() - { - ColoredWrite(DarkGray, " │\n"); - } - - private static void StartingSeparator(char joiningChar, char extraChar) - { - // ╭ - ColoredWrite(DarkGray, $" {joiningChar}─/> {extraChar}"); - } - - private static void ShowFileInformation(char joiningChar, Token token) - { - StartingSeparator(joiningChar, '['); - ColoredWrite(ResetColor() , $"{token.FetchFile}:{token.Line}:{token.Column}"); - ColoredWrite(DarkGray , "]\n"); - } - - private static void ShowSourceLine(int lineNumber, string sourceLine) - { - ColoredWrite(DarkGray , $"{lineNumber,4} │ "); - ColoredWrite(ResetColor() , $"{sourceLine.TrimStart()}\n"); - } - - private static void ShowErrorPosition(ConsoleColor errorColor, string errorLine) - { - ColoredWrite(DarkGray , " │"); - ColoredWrite(errorColor , $" {errorLine.TrimEnd()}"); - } - - private static void ShowNotePosition(ConsoleColor errorColor, string errorLine) - { - ColoredWrite(DarkGray , " │"); - ColoredWrite(errorColor , $" {errorLine.TrimEnd()}\n"); - } - - private static void ShowErrorHelp(ConsoleColor errorColor, string errorHelp) - { - ColoredWrite(errorColor, "/> "); - Console.WriteLine(errorHelp); - } - - private static void ShowNote(ConsoleColor noteColor, string noteMessage) - { - ColoredWrite(DarkGray , " │ "); - ColoredWrite(noteColor , "Note"); - ColoredWrite(ResetColor() , $": {noteMessage}\n"); - } - - private static void ShowException(ConsoleColor exceptionColor, string exceptionMessage) - { - ColoredWrite(DarkGray , " │ "); - ColoredWrite(exceptionColor, "Exception"); - ColoredWrite(ResetColor() , $": {exceptionMessage}\n"); - } - - private static (string, string) FetchSourceLine(Token token) - { - string line = File.ReadLines(token.FetchFile).Skip(token.Line - 1).Take(token.Line).First(); - int whiteSpace = line.TakeWhile(char.IsWhiteSpace).Count() + 1; - - string error = new string(' ', line.Length - token.Value.Length) - .Insert(token.Column - whiteSpace, new string('~', token.Value.Length)); - - return (line, error); - } -} \ No newline at end of file diff --git a/Otterkit.Types/src/ErrorHandler/ErrorHandler.Methods.cs b/Otterkit.Types/src/ErrorHandler/ErrorHandler.Methods.cs deleted file mode 100644 index cdba7280..00000000 --- a/Otterkit.Types/src/ErrorHandler/ErrorHandler.Methods.cs +++ /dev/null @@ -1,175 +0,0 @@ -namespace Otterkit.Types; - -public readonly ref partial struct ErrorHandler -{ - public static void SuccessfulParse() - { - var filesCount = CompilerContext.FileNames.Count; - var isPlural = filesCount > 1 ? "s" : ""; - - Console.ForegroundColor = ConsoleColor.Blue; - Console.WriteLine($"Analyzed {filesCount} file{isPlural}, no errors found! \n"); - Console.ResetColor(); - } - - public static void StopCompilation(string errorType) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine($"Compilation process cancelled due to {errorType} error"); - Console.ResetColor(); - Environment.Exit(1); - } - - public static ErrorHandler Build(ErrorType errorType, ConsoleColor consoleColor, int errorCode, string errorMessage) - { - // Return early, don't display the initial message: - if (SuppressedError == errorType) return new (errorType, consoleColor); - - Console.OutputEncoding = System.Text.Encoding.UTF8; - - ColoredWrite(consoleColor, $"\n {errorType} Error [COB{errorCode:D4}]"); - - ColoredWrite(ResetColor(), $": {errorMessage}\n"); - - ErrorHandler.HasOccurred = true; - - if (CrashOnError) - { - throw new Exception($"{errorType} Error [COB{errorCode:D4}]: {errorMessage}"); - } - - return new(errorType, consoleColor); - } - - public ErrorHandler WithSourceLine(Token token, string? errorHelp = null) - { - // Return early, don't display any further messages: - if (SuppressedError == ErrorType) return this; - - var (line, error) = FetchSourceLine(token); - - // ╭─/> [file.cob:5:25] - ShowFileInformation('╭', token); - - // │ - Separator(); - - if (token.Value is "[FILLER]") - { - // 7 | 01 [FILLER] PIC X(10). - line = line.Insert(token.Column - 1, "[FILLER] "); - } - - // 7 │ END PROGRAM HELLO. - ShowSourceLine(token.Line, line); - - // │ ~~~~~ - ShowErrorPosition(ConsoleColor, error); - - if (errorHelp is not null) - { - // ~~/> Expected the following identifier: HELLO-WORLD. - ShowErrorHelp(ConsoleColor, errorHelp); - } - - if (errorHelp is null) - { - // Move to next line if no error help message was provided - Console.WriteLine(); - } - - // │ - Separator(); - - return this; - } - - public ErrorHandler WithSourceNote(Token token) - { - // Return early, don't display any further messages: - if (SuppressedError == ErrorType) return this; - - var (line, note) = FetchSourceLine(token); - - // ├─/> [file.cob:5:25] - ShowFileInformation('├', token); - - // │ - Separator(); - - // 7 │ END PROGRAM HELLO. - ShowSourceLine(token.Line, line); - - // │ ~~~~~ - ShowNotePosition(Green, note); - - // │ - Separator(); - - return this; - } - - public ErrorHandler WithNote(string noteMessage) - { - // Return early, don't display any further messages: - if (SuppressedError == ErrorType) return this; - - // │ Note: {noteMessage} - ShowNote(Green, noteMessage); - - // │ - Separator(); - - return this; - } - - public ErrorHandler WithStartingError(string errorNote) - { - // Return early, don't display any further messages: - if (SuppressedError == ErrorType) return this; - - // ╭─/> - StartingSeparator('╭', '\n'); - - // │ - Separator(); - - // │ Note: {noteMessage} - ShowNote(ConsoleColor.Red, errorNote); - - // │ - Separator(); - - return this; - } - - public ErrorHandler WithStartingException(string exceptionError) - { - // Return early, don't display any further messages: - if (SuppressedError == ErrorType) return this; - - // ╭─/> - StartingSeparator('╭', '\n'); - - // │ - Separator(); - - // │ Exception: {exceptionMessage} - ShowException(ConsoleColor.Red, exceptionError); - - // │ - Separator(); - - return this; - } - - public void CloseError() - { - // Return early, don't display the closing message: - if (SuppressedError == ErrorType) return; - - // ────╯ - ColoredWrite(DarkGray, " ────╯\n"); - Console.ResetColor(); - } -} diff --git a/Otterkit.Types/src/ErrorHandler/ErrorHandler.cs b/Otterkit.Types/src/ErrorHandler/ErrorHandler.cs deleted file mode 100644 index 632e1e17..00000000 --- a/Otterkit.Types/src/ErrorHandler/ErrorHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Otterkit.Types; - -public readonly ref partial struct ErrorHandler -{ - public static ErrorType SuppressedError { private get; set; } - public static bool HasOccurred = false; - public static bool CrashOnError = false; - - private readonly ErrorType ErrorType; - private readonly ConsoleColor ConsoleColor; - - - public ErrorHandler(ErrorType errorType, ConsoleColor consoleColor) - { - ErrorType = errorType; - ConsoleColor = consoleColor; - } -} diff --git a/Otterkit.Types/src/ErrorHandler/ErrorType.cs b/Otterkit.Types/src/ErrorHandler/ErrorType.cs deleted file mode 100644 index c558acaa..00000000 --- a/Otterkit.Types/src/ErrorHandler/ErrorType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Otterkit.Types; - -public enum ErrorType -{ - None, - Syntax, - Analyzer, - Resolution, - Compilation -} diff --git a/Otterkit.Types/src/ExtensionMethods.cs b/Otterkit.Types/src/ExtensionMethods.cs deleted file mode 100644 index 72d5871e..00000000 --- a/Otterkit.Types/src/ExtensionMethods.cs +++ /dev/null @@ -1,34 +0,0 @@ -namespace Otterkit.Types; - -public static class ExtensionMethods -{ - public static T AwaitResult(this ValueTask valueTask) - { - return valueTask.GetAwaiter().GetResult(); - } - - public static bool IsEmpty(this HashSet hashSet) - { - return hashSet.Count == 0; - } - - public static bool IsOneOf(this char value, ReadOnlySpan span) - { - foreach (var item in span) - { - if (value == item) return true; - } - - return false; - } - - public static bool ContainsAny(this HashSet hashSet, ReadOnlySpan span) - { - foreach (var item in span) - { - if (hashSet.Contains(item)) return true; - } - - return false; - } -} diff --git a/Otterkit.Types/src/Name.cs b/Otterkit.Types/src/Name.cs deleted file mode 100644 index 37517d66..00000000 --- a/Otterkit.Types/src/Name.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Otterkit.Types; - -public readonly struct Name : - IEquatable> - where TValue : notnull -{ - internal readonly TValue Value; - public readonly bool Exists; - public readonly bool Unique; - - public static Name Null => new(); - - public Name(TValue value) - { - Value = value; - Exists = true; - } - - public Name(TValue value, bool unique) - { - Value = value; - Exists = true; - Unique = unique; - } - - public void Deconstruct(out TValue? value, out bool exists) - { - value = Value; - exists = Exists; - } - - public bool TryUnwrap([NotNullWhen(true)] out TValue? value) - { - if (Exists) - { - value = Value; - return true; - } - - value = default; - return false; - } - - public TValue Unwrap() - { - if (Exists) return Value; - - throw new NullReferenceException("Instance of Name did not have a value"); - } - - public static implicit operator Name(TValue? value) - { - if (value is null) return Null; - - return new(value); - } - - public static explicit operator TValue(Name option) - { - if (option.Exists) return option.Value; - - throw new NullReferenceException("Instance of Name did not have a value"); - } - - public static implicit operator bool(Name option) - { - return option.Exists; - } - - public static implicit operator Name((TValue value, bool unique) tuple) - { - if (tuple.value is null) return Null; - - return new(tuple.value, tuple.unique); - } - - public static bool operator ==(Name left, Name right) - { - return left.Equals(right); - } - - public static bool operator !=(Name left, Name right) - { - return !left.Equals(right); - } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is Name value && Equals(value); - } - - public bool Equals(Name other) - { - if (Exists && other.Exists) - { - return EqualityComparer.Default.Equals(Value, other.Value); - } - - if (!Exists && !other.Exists) - { - return true; - } - - return false; - } - - public override int GetHashCode() - { - if (!Exists) return 0; - - return HashCode.Combine(Value, Exists, Unique); - } -} \ No newline at end of file diff --git a/Otterkit.Types/src/NameTables/DataNames.cs b/Otterkit.Types/src/NameTables/DataNames.cs deleted file mode 100644 index 22752fa8..00000000 --- a/Otterkit.Types/src/NameTables/DataNames.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; - -namespace Otterkit.Types; - -public sealed class DataNames where TValue: notnull -{ - private readonly Dictionary> NameLookup = new(StringComparer.OrdinalIgnoreCase); - - public void Add(Token entry, TValue localEntry) - { - ref var entries = ref CollectionsMarshal.GetValueRefOrAddDefault(NameLookup, entry.Value, out var exists); - - if (!exists) - { - entries = new(1); - entries.Add(localEntry); - } - - if (exists && entries is not null) entries.Add(localEntry); - - if (exists && entries is null) - { - throw new ArgumentException("Local entry exists but value was null in the NameLookup dictionary", nameof(entry)); - } - } - - public bool Exists(Token entry) - { - ref var entries = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, entry.Value); - - if (!Unsafe.IsNullRef(ref entries)) return true; - - return false; - } - - public (bool, bool) HasUnique(Token entry) - { - ref var entries = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, entry.Value); - - if (!Unsafe.IsNullRef(ref entries) && entries is not null) - { - return (true, entries.Count == 1); - } - - return (false, false); - } - - public List FetchList(Token entry) - { - ref var entries = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, entry.Value); - - if (!Unsafe.IsNullRef(ref entries) && entries is not null) - { - return entries; - } - - throw new ArgumentOutOfRangeException(nameof(entry), "Local entry does not exist in the NameLookup dictionary"); - } - - public TValue FetchUnique(Token entry) - { - ref var entries = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, entry.Value); - - if (!Unsafe.IsNullRef(ref entries) && entries is not null) - { - return entries[0]; - } - - throw new ArgumentOutOfRangeException(nameof(entry), "Local entry does not exist in the NameLookup dictionary"); - } -} diff --git a/Otterkit.Types/src/NameTables/GlobalNames.cs b/Otterkit.Types/src/NameTables/GlobalNames.cs deleted file mode 100644 index d6142fda..00000000 --- a/Otterkit.Types/src/NameTables/GlobalNames.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; - -namespace Otterkit.Types; - -public sealed class GlobalNames -{ - private readonly Dictionary NameLookup = new(StringComparer.OrdinalIgnoreCase); - - public bool TryAdd(Token nameToken, AbstractUnit prototype) - { - ref var prototypeRef = ref CollectionsMarshal.GetValueRefOrAddDefault(NameLookup, nameToken.Value, out var exists); - - if (!exists) - { - prototypeRef = prototype; - return true; - } - - return false; - } - - public bool Exists(Token nameToken) - { - ref var prototypeRef = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, nameToken.Value); - - if (!Unsafe.IsNullRef(ref prototypeRef)) return true; - - return false; - } - - public bool Exists(Token nameToken) - where TPrototype : AbstractUnit - { - ref var prototypeRef = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, nameToken.Value); - - if (!Unsafe.IsNullRef(ref prototypeRef)) return prototypeRef is TPrototype; - - return false; - } - - public AbstractUnit Fetch(Token nameToken) - { - ref var prototypeRef = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, nameToken.Value); - - if (!Unsafe.IsNullRef(ref prototypeRef)) - { - return prototypeRef; - } - - throw new ArgumentNullException(nameof(nameToken), "Global prototype does not exist in the NameLookup Dictionary"); - } - - public TPrototype Fetch(Token nameToken) - where TPrototype : AbstractUnit - { - ref var prototypeRef = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, nameToken.Value); - - if (!Unsafe.IsNullRef(ref prototypeRef)) - { - return (TPrototype)prototypeRef; - } - - throw new ArgumentNullException(nameof(nameToken), "Global prototype does not exist in the NameLookup Dictionary"); - } -} diff --git a/Otterkit.Types/src/NameTables/LocalNames.cs b/Otterkit.Types/src/NameTables/LocalNames.cs deleted file mode 100644 index af5cc0a1..00000000 --- a/Otterkit.Types/src/NameTables/LocalNames.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; - -namespace Otterkit.Types; - -public sealed class LocalNames where TValue: notnull -{ - private readonly Dictionary NameLookup = new(StringComparer.OrdinalIgnoreCase); - - public bool TryAdd(Token name, TValue localName) - { - ref var names = ref CollectionsMarshal.GetValueRefOrAddDefault(NameLookup, name.Value, out var exists); - - if (!exists) - { - names = localName; - - return true; - } - - return false; - } - - public bool Exists(Token name) - { - ref var names = ref CollectionsMarshal.GetValueRefOrNullRef(NameLookup, name.Value); - - if (!Unsafe.IsNullRef(ref names)) return true; - - return false; - } -} diff --git a/Otterkit.Types/src/Optimization.cs b/Otterkit.Types/src/Optimization.cs deleted file mode 100644 index 270aeaeb..00000000 --- a/Otterkit.Types/src/Optimization.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Otterkit.Types; - -public static class Optimization -{ - public static bool SpaceSeparatedSearch(ReadOnlySpan words, ReadOnlySpan word) - { - Span buffer = stackalloc char[64]; - - var length = words.Length; - - var parsed = 0; - - for (var index = 0; index < length; index++) - { - var character = words[index]; - - if (character is ' ') - { - if (word.Equals(buffer[..parsed], StringComparison.OrdinalIgnoreCase)) return true; - - parsed = 0; - - continue; - } - - if (index + 1 == length) - { - buffer[parsed] = character; - - return word.Equals(buffer[..(parsed + 1)], StringComparison.OrdinalIgnoreCase); - } - - buffer[parsed] = character; - - parsed++; - } - - return false; - } -} diff --git a/Otterkit.Types/src/Option.cs b/Otterkit.Types/src/Option.cs deleted file mode 100644 index 9af719bd..00000000 --- a/Otterkit.Types/src/Option.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Otterkit.Types; - -public readonly struct Option : - IEquatable> - where TValue : notnull -{ - internal readonly TValue Value; - public readonly bool Exists; - - public static Option Null - { - get => new Option(); - } - - public Option(TValue value) - { - Value = value; - Exists = true; - } - - public void Deconstruct(out TValue? value, out bool exists) - { - value = Value; - exists = Exists; - } - - public bool TryUnwrap([NotNullWhen(true)] out TValue? value) - { - if (Exists) - { - value = Value; - return true; - } - - value = default; - return false; - } - - public TValue Unwrap() - { - if (Exists) return Value; - - throw new NullReferenceException("Instance of Option did not have a value"); - } - - public static implicit operator Option(TValue? value) - { - if (value is null) return Null; - - return new Option(value); - } - - public static explicit operator TValue(Option option) - { - if (option.Exists) return option.Value; - - throw new NullReferenceException("Instance of Option did not have a value"); - } - - public static implicit operator bool(Option option) - { - return option.Exists; - } - - public static bool operator ==(Option left, Option right) - { - return left.Equals(right); - } - - public static bool operator !=(Option left, Option right) - { - return !left.Equals(right); - } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is Option value && Equals(value); - } - - public bool Equals(Option other) - { - if (Exists && other.Exists) - { - return EqualityComparer.Default.Equals(Value, other.Value); - } - - if (!Exists && !other.Exists) - { - return true; - } - - return false; - } - - public override int GetHashCode() - { - if (!Exists) return 0; - - return HashCode.Combine(Value, Exists); - } -} diff --git a/Otterkit.Types/src/Token/Token.Lookup.cs b/Otterkit.Types/src/Token/Token.Lookup.cs deleted file mode 100644 index 4ebc9c96..00000000 --- a/Otterkit.Types/src/Token/Token.Lookup.cs +++ /dev/null @@ -1,748 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Otterkit.Types; - -public sealed partial record Token -{ - private static bool IsReservedWord(string value) - { - ref var reserved = ref CollectionsMarshal.GetValueRefOrNullRef(ReservedLookup, value); - - return !Unsafe.IsNullRef(ref reserved); - } - - private static bool IsStandardClause(string value) - { - ref var context = ref CollectionsMarshal.GetValueRefOrNullRef(ContextLookup, value); - - return !Unsafe.IsNullRef(ref context) && context is 1; - } - - private static bool IsStandardStatement(string value) - { - ref var context = ref CollectionsMarshal.GetValueRefOrNullRef(ContextLookup, value); - - return !Unsafe.IsNullRef(ref context) && context is 2; - } - - private static bool IsOtterkitDevice(string value) - { - ref var context = ref CollectionsMarshal.GetValueRefOrNullRef(ContextLookup, value); - - return !Unsafe.IsNullRef(ref context) && context is 3; - } - - private static bool IsFigurativeLiteral(string value) - { - ref var context = ref CollectionsMarshal.GetValueRefOrNullRef(ContextLookup, value); - - return !Unsafe.IsNullRef(ref context) && context is 4; - } - - private static bool IsStandardSymbol(string value) - { - ref var context = ref CollectionsMarshal.GetValueRefOrNullRef(ContextLookup, value); - - return !Unsafe.IsNullRef(ref context) && context is 5; - } - - private static bool IsStandardIntrinsic(string value) - { - ref var intrinsics = ref CollectionsMarshal.GetValueRefOrNullRef(IntrinsicLookup, value); - - return !Unsafe.IsNullRef(ref intrinsics); - } - - private static readonly Dictionary ReservedLookup = new(400, StringComparer.OrdinalIgnoreCase) - { - {"ACCEPT", 0}, - {"ACCESS", 0}, - {"ACTIVE-CLASS", 0}, - {"ADD", 0}, - {"ADDRESS", 0}, - {"ADVANCING", 0}, - {"AFTER", 0}, - {"ALIGNED", 0}, - {"ALLOCATE", 0}, - {"ALPHABET", 0}, - {"ALPHABETIC", 0}, - {"ALPHABETIC-LOWER", 0}, - {"ALPHABETIC-UPPER", 0}, - {"ALPHANUMERIC", 0}, - {"ALPHANUMERIC-EDITED", 0}, - {"ALSO", 0}, - {"ALTERNATE", 0}, - {"AND", 0}, - {"ANY", 0}, - {"ANYCASE", 0}, - {"ARE", 0}, - {"AREA", 0}, - {"AREAS", 0}, - {"AS", 0}, - {"ASCENDING", 0}, - {"ASSIGN", 0}, - {"AT", 0}, - {"B-AND", 0}, - {"B-NOT", 0}, - {"B-OR", 0}, - {"B-SHIFT", 0}, - {"B-SHIFT-LC", 0}, - {"B-SHIFT-RC", 0}, - {"BY", 0}, - {"B-XOR", 0}, - {"BASED", 0}, - {"BEFORE", 0}, - {"BINARY", 0}, - {"BINARY-CHAR", 0}, - {"BINARY-DOUBLE", 0}, - {"BINARY-LONG", 0}, - {"BINARY-SHORT", 0}, - {"BIT", 0}, - {"BLANK", 0}, - {"BLOCK", 0}, - {"BOOLEAN", 0}, - {"BOTTOM", 0}, - {"CALL", 0}, - {"CANCEL", 0}, - {"CF", 0}, - {"CH", 0}, - {"CHARACTER", 0}, - {"CHARACTERS", 0}, - {"CLASS", 0}, - {"CLASS-ID", 0}, - {"CLOSE", 0}, - {"CODE", 0}, - {"CODE-SET", 0}, - {"COL", 0}, - {"COLLATING", 0}, - {"COLS", 0}, - {"COLUMN", 0}, - {"COLUMNS", 0}, - {"COMMA", 0}, - {"COMMIT", 0}, - {"COMMON", 0}, - {"COMP", 0}, - {"COMPUTATIONAL", 0}, - {"COMPUTE", 0}, - {"CONFIGURATION", 0}, - {"CONSTANT", 0}, - {"CONTAINS", 0}, - {"CONTENT", 0}, - {"CONTINUE", 0}, - {"CONTROL", 0}, - {"CONTROLS", 0}, - {"CONVERTING", 0}, - {"COPY", 0}, - {"CORR", 0}, - {"CORRESPONDING", 0}, - {"COUNT", 0}, - {"CRT", 0}, - {"CURRENCY", 0}, - {"CURSOR", 0}, - {"DATA", 0}, - {"DATA-POINTER", 0}, - {"DATE", 0}, - {"DAY", 0}, - {"DAY-OF-WEEK", 0}, - {"DE", 0}, - {"DECIMAL-POINT", 0}, - {"DECLARATIVES", 0}, - {"DEFAULT", 0}, - {"DELETE", 0}, - {"DELIMITED", 0}, - {"DELIMITER", 0}, - {"DEPENDING", 0}, - {"DESCENDING", 0}, - {"DESTINATION", 0}, - {"DETAIL", 0}, - {"DISPLAY", 0}, - {"DIVIDE", 0}, - {"DIVISION", 0}, - {"DOWN", 0}, - {"DUPLICATES", 0}, - {"DYNAMIC", 0}, - {"EC", 0}, - {"EDITING", 0}, - {"ELSE", 0}, - {"EMI", 0}, - {"END", 0}, - {"END-ACCEPT", 0}, - {"END-ADD", 0}, - {"END-CALL", 0}, - {"END-COMPUTE", 0}, - {"END-DELETE", 0}, - {"END-DISPLAY", 0}, - {"END-DIVIDE", 0}, - {"END-EVALUATE", 0}, - {"END-IF", 0}, - {"END-MULTIPLY", 0}, - {"END-OF-PAGE", 0}, - {"END-PERFORM", 0}, - {"END-RECEIVE", 0}, - {"END-READ", 0}, - {"END-RETURN", 0}, - {"END-REWRITE", 0}, - {"END-SEARCH", 0}, - {"END-SEND", 0}, - {"END-START", 0}, - {"END-STRING", 0}, - {"END-SUBTRACT", 0}, - {"END-UNSTRING", 0}, - {"END-WRITE", 0}, - {"ENVIRONMENT", 0}, - {"EOL", 0}, - {"EOP", 0}, - {"EQUAL", 0}, - {"ERROR", 0}, - {"EVALUATE", 0}, - {"EXCEPTION", 0}, - {"EXCEPTION-OBJECT", 0}, - {"EXCLUSIVE-OR", 0}, - {"EXIT", 0}, - {"EXTEND", 0}, - {"EXTERNAL", 0}, - {"FACTORY", 0}, - {"FARTHEST-FROM-ZERO", 0}, - {"FALSE", 0}, - {"FD", 0}, - {"FILE", 0}, - {"FILE-CONTROL", 0}, - {"FILLER", 0}, - {"FINAL", 0}, - {"FINALLY", 0}, - {"FIRST", 0}, - {"FLOAT-BINARY-32", 0}, - {"FLOAT-BINARY-64", 0}, - {"FLOAT-BINARY-128", 0}, - {"FLOAT-DECIMAL-16", 0}, - {"FLOAT-DECIMAL-34", 0}, - {"FLOAT-EXTENDED", 0}, - {"FLOAT-INFINITY", 0}, - {"FLOAT-LONG", 0}, - {"FLOAT-NOT-A-NUMBER", 0}, - {"FLOAT-NOT-A-NUMBER-QUIET", 0}, - {"FLOAT-NOT-A-NUMBER-SIGNALING", 0}, - {"FOOTING", 0}, - {"FOR", 0}, - {"FORMAT", 0}, - {"FREE", 0}, - {"FROM", 0}, - {"FUNCTION", 0}, - {"FUNCTION-ID", 0}, - {"FUNCTION-POINTER", 0}, - {"GENERATE", 0}, - {"GET", 0}, - {"GIVING", 0}, - {"GLOBAL", 0}, - {"GO", 0}, - {"GOBACK", 0}, - {"GREATER", 0}, - {"GROUP", 0}, - {"GROUP-USAGE", 0}, - {"HEADING", 0}, - {"I-O", 0}, - {"I-O-CONTROL", 0}, - {"IDENTIFICATION", 0}, - {"IF", 0}, - {"IN", 0}, - {"IN-ARITHMETIC-RANGE", 0}, - {"INDEX", 0}, - {"INDEXED", 0}, - {"INDICATE", 0}, - {"INHERITS", 0}, - {"INITIAL", 0}, - {"INITIALIZE", 0}, - {"INITIALIZED", 0}, - {"INITIATE", 0}, - {"INPUT", 0}, - {"INPUT-OUTPUT", 0}, - {"INSPECT", 0}, - {"INTERFACE", 0}, - {"INTERFACE-ID", 0}, - {"INTO", 0}, - {"INVALID", 0}, - {"INVOKE", 0}, - {"IS", 0}, - {"JUST", 0}, - {"JUSTIFIED", 0}, - {"KEY", 0}, - {"LAST", 0}, - {"LEADING", 0}, - {"LEFT", 0}, - {"LENGTH", 0}, - {"LESS", 0}, - {"LIMIT", 0}, - {"LIMITS", 0}, - {"LINAGE", 0}, - {"LINAGE-COUNTER", 0}, - {"LINE", 0}, - {"LINE-COUNTER", 0}, - {"LINES", 0}, - {"LINKAGE", 0}, - {"LOCAL-STORAGE", 0}, - {"LOCALE", 0}, - {"LOCATION", 0}, - {"LOCK", 0}, - {"MERGE", 0}, - {"MESSAGE-TAG", 0}, - {"METHOD", 0}, - {"METHOD-ID", 0}, - {"MINUS", 0}, - {"MODE", 0}, - {"MOVE", 0}, - {"MULTIPLY", 0}, - {"NATIONAL", 0}, - {"NATIONAL-EDITED", 0}, - {"NATIVE", 0}, - {"NEAREST-TO-ZERO", 0}, - {"NESTED", 0}, - {"NEXT", 0}, - {"NO", 0}, - {"NOT", 0}, - {"NULL", 0}, - {"NUMBER", 0}, - {"NUMERIC", 0}, - {"NUMERIC-EDITED", 0}, - {"OBJECT", 0}, - {"OBJECT-COMPUTER", 0}, - {"OBJECT-REFERENCE", 0}, - {"OCCURS", 0}, - {"OF", 0}, - {"OFF", 0}, - {"OMITTED", 0}, - {"ON", 0}, - {"OPEN", 0}, - {"OPTIONAL", 0}, - {"OPTIONS", 0}, - {"OR", 0}, - {"ORDER", 0}, - {"ORGANIZATION", 0}, - {"OTHER", 0}, - {"OUTPUT", 0}, - {"OVERFLOW", 0}, - {"OVERRIDE", 0}, - {"PACKED-DECIMAL", 0}, - {"PAGE", 0}, - {"PAGE-COUNTER", 0}, - {"PERFORM", 0}, - {"PF", 0}, - {"PH", 0}, - {"PIC", 0}, - {"PICTURE", 0}, - {"PLUS", 0}, - {"POINTER", 0}, - {"POSITIVE", 0}, - {"PRESENT", 0}, - {"PRINTING", 0}, - {"PROCEDURE", 0}, - {"PROGRAM", 0}, - {"PROGRAM-ID", 0}, - {"PROGRAM-POINTER", 0}, - {"PROPERTY", 0}, - {"PROTOTYPE", 0}, - {"RAISE", 0}, - {"RAISING", 0}, - {"RANDOM", 0}, - {"RD", 0}, - {"READ", 0}, - {"RECEIVE", 0}, - {"RECORD", 0}, - {"RECORDS", 0}, - {"REDEFINES", 0}, - {"REEL", 0}, - {"REF", 0}, - {"REFERENCE", 0}, - {"RELATIVE", 0}, - {"RELEASE", 0}, - {"REMAINDER", 0}, - {"REMOVAL", 0}, - {"RENAMES", 0}, - {"REPLACE", 0}, - {"REPLACING", 0}, - {"REPORT", 0}, - {"REPORTING", 0}, - {"REPORTS", 0}, - {"REPOSITORY", 0}, - {"RESERVE", 0}, - {"RESET", 0}, - {"RESUME", 0}, - {"RETRY", 0}, - {"RETURN", 0}, - {"RETURNING", 0}, - {"REWIND", 0}, - {"REWRITE", 0}, - {"RF", 0}, - {"RH", 0}, - {"RIGHT", 0}, - {"ROLLBACK", 0}, - {"ROUNDED", 0}, - {"RUN", 0}, - {"SAME", 0}, - {"SCREEN", 0}, - {"SD", 0}, - {"SEARCH", 0}, - {"SECONDS", 0}, - {"SECTION", 0}, - {"SELECT", 0}, - {"SEND", 0}, - {"SELF", 0}, - {"SENTENCE", 0}, - {"SEPARATE", 0}, - {"SEQUENCE", 0}, - {"SEQUENTIAL", 0}, - {"SET", 0}, - {"SHARING", 0}, - {"SIGN", 0}, - {"SIZE", 0}, - {"SORT", 0}, - {"SORT-MERGE", 0}, - {"SOURCE", 0}, - {"SOURCE-COMPUTER", 0}, - {"SOURCES", 0}, - {"SPECIAL-NAMES", 0}, - {"STANDARD", 0}, - {"STANDARD-1", 0}, - {"STANDARD-2", 0}, - {"START", 0}, - {"STATUS", 0}, - {"STOP", 0}, - {"STRING", 0}, - {"SUBTRACT", 0}, - {"SUM", 0}, - {"SUPER", 0}, - {"SUPPRESS", 0}, - {"SYMBOLIC", 0}, - {"SYNC", 0}, - {"SYNCHRONIZED", 0}, - {"SYSTEM-DEFAULT", 0}, - {"TABLE", 0}, - {"TALLYING", 0}, - {"TERMINATE", 0}, - {"TEST", 0}, - {"THAN", 0}, - {"THEN", 0}, - {"THROUGH", 0}, - {"THRU", 0}, - {"TIME", 0}, - {"TIMES", 0}, - {"TO", 0}, - {"TOP", 0}, - {"TRAILING", 0}, - {"TRUE", 0}, - {"TYPE", 0}, - {"TYPEDEF", 0}, - {"UNIT", 0}, - {"UNIVERSAL", 0}, - {"UNLOCK", 0}, - {"UNSTRING", 0}, - {"UNTIL", 0}, - {"UP", 0}, - {"UPON", 0}, - {"USAGE", 0}, - {"USE", 0}, - {"USER-DEFAULT", 0}, - {"USING", 0}, - {"VAL-STATUS", 0}, - {"VALID", 0}, - {"VALIDATE", 0}, - {"VALIDATE-STATUS", 0}, - {"VALUE", 0}, - {"VALUES", 0}, - {"VARYING", 0}, - {"WHEN", 0}, - {"WITH", 0}, - {"WORKING-STORAGE", 0}, - {"WRITE", 0}, - {"XOR", 0}, - }; - - private static readonly Dictionary ContextLookup = new(168, StringComparer.OrdinalIgnoreCase) - { - // TokenContext - // None = 0 - // IsClause = 1 - // IsStatement = 2 - // IsDevice = 3 - // IsFigurative = 4 - // IsSymbol = 5 - // IsEOF = 6 - - // DATA DIVISION CLAUSES - {"ALIGNED", 1}, - {"ANY", 1}, - {"LENGTH", 1}, - {"AUTO", 1}, - {"BACKGROUND-COLOR", 1}, - {"BASED", 1}, - {"BELL", 1}, - {"BLANK", 1}, - {"WHEN", 1}, - {"BLINK", 1}, - {"BLOCK", 1}, - {"CONTAINS", 1}, - {"CLASS", 1}, - {"CODE", 1}, - {"CODE-SET", 1}, - {"COLUMN", 1}, - {"CONSTANT", 1}, - {"CONTROL", 1}, - {"DEFAULT", 1}, - {"DESTINATION", 1}, - {"DYNAMIC", 1}, - {"ERASE", 1}, - {"EXTERNAL", 1}, - {"FOREGROUND-COLOR", 1}, - {"FORMAT", 1}, - {"FROM", 1}, - {"FULL", 1}, - {"GLOBAL", 1}, - {"GROUP", 1}, - {"INDICATE", 1}, - {"GROUP-USAGE", 1}, - {"HIGHLIGHT", 1}, - {"INVALID", 1}, - {"JUSTIFIED", 1}, - {"LINAGE", 1}, - {"LINE", 1}, - {"LOWLIGHT", 1}, - {"NEXT", 1}, - {"OCCURS", 1}, - {"PAGE", 1}, - {"PICTURE", 1}, - {"PIC", 1}, - {"IS", 1}, - {"PRESENT", 1}, - {"PROPERTY", 1}, - {"RECORD", 1}, - {"REDEFINES", 1}, - {"RENAMES", 1}, - {"REPORT", 1}, - {"REQUIRED", 1}, - {"REVERSE-VIDEO", 1}, - {"SAME", 1}, - {"AS", 1}, - {"SECURE", 1}, - {"SELECT", 1}, - {"SIGN", 1}, - {"SOURCE", 1}, - {"SUM", 1}, - {"SYNCHRONIZED", 1}, - {"TO", 1}, - {"TYPE", 1}, - {"TYPEDEF", 1}, - {"UNDERLINE", 1}, - {"USAGE", 1}, - {"USING", 1}, - {"VALIDATE-STATUS", 1}, - {"VALUE", 1}, - {"VARYING", 1}, - - // FILE-CONTROL CLAUSES - {"ACCESS", 1}, - {"ALTERNATE", 1}, - {"FILE", 1}, - {"STATUS", 1}, - {"LOCK", 1}, - {"ORGANIZATION", 1}, - {"RELATIVE", 1}, - {"RESERVE", 1}, - {"SHARING", 1}, - {"COLLATING", 1}, - {"SEQUENCE", 1}, - - // PROCEDURE DIVISION STATEMENTS - {"ACCEPT", 2}, - {"ADD", 2}, - {"ALLOCATE", 2}, - {"CALL", 2}, - {"CANCEL", 2}, - {"CLOSE", 2}, - {"COMMIT", 2}, - {"COMPUTE", 2}, - {"CONTINUE", 2}, - {"DELETE", 2}, - {"DISPLAY", 2}, - {"DIVIDE", 2}, - {"EVALUATE", 2}, - {"EXIT", 2}, - {"FREE", 2}, - {"GENERATE", 2}, - {"GOBACK", 2}, - {"GO", 2}, - {"IF", 2}, - {"INITIALIZE", 2}, - {"INITIATE", 2}, - {"INSPECT", 2}, - {"INVOKE", 2}, - {"MERGE", 2}, - {"MOVE", 2}, - {"MULTIPLY", 2}, - {"OPEN", 2}, - {"PERFORM", 2}, - {"RAISE", 2}, - {"READ", 2}, - {"RECEIVE", 2}, - {"RELEASE", 2}, - {"RESUME", 2}, - {"RETURN", 2}, - {"REWRITE", 2}, - {"ROLLBACK", 2}, - {"SEARCH", 2}, - {"SEND", 2}, - {"SET", 2}, - {"SORT", 2}, - {"START", 2}, - {"STOP", 2}, - {"STRING", 2}, - {"SUBTRACT", 2}, - {"SUPPRESS", 2}, - {"TERMINATE", 2}, - {"UNLOCK", 2}, - {"UNSTRING", 2}, - {"USE", 2}, - {"VALIDATE", 2}, - {"WRITE", 2}, - - // SYSTEM DEVICE NAMES - {"STANDARD-OUTPUT", 3}, - {"STANDARD-INPUT", 3}, - {"COMMAND-LINE", 3}, - {"SINGLE-KEY", 3}, - - // FIGURATIVE LITERALS - {"ZERO", 4}, - {"ZEROES", 4}, - {"ZEROS", 4}, - {"SPACE", 4}, - {"SPACES", 4}, - {"HIGH-VALUE", 4}, - {"HIGH-VALUES", 4}, - {"LOW-VALUE", 4}, - {"LOW-VALUES", 4}, - {"QUOTE", 4}, - {"QUOTES", 4}, - {"ALL", 4}, - - // Standard COBOL symbols - {"+", 5}, - {"-", 5}, - {"**", 5}, - {"*", 5}, - {"=", 5}, - {"/", 5}, - {"$", 5}, - {",", 5}, - {";", 5}, - {"::", 5}, - {".", 5}, - {"(", 5}, - {")", 5}, - {">>", 5}, - {"<>", 5}, - {">=", 5}, - {"<=", 5}, - {">", 5}, - {"<", 5}, - {"&", 5}, - {"_", 5}, - }; - - private static readonly Dictionary IntrinsicLookup = new(95, StringComparer.OrdinalIgnoreCase) - { - {"ABS", 0}, - {"ACOS", 0}, - {"ANNUITY", 0}, - {"ASIN", 0}, - {"ATAN", 0}, - {"BASECONVERT", 0}, - {"BOOLEAN-OF-INTEGER", 0}, - {"BYTE-LENGTH", 0}, - {"CHAR", 0}, - {"CHAR-NATIONAL", 0}, - {"COMBINED-DATETIME", 0}, - {"CONCAT", 0}, - {"CONVERT", 0}, - {"COS", 0}, - {"CURRENT-DATE", 0}, - {"DATE-OF-INTEGER", 0}, - {"DATE-TO-YYYYMMDD", 0}, - {"DAY-OF-INTEGER", 0}, - {"DAY-TO-YYYYDDD", 0}, - {"DISPLAY-OF", 0}, - {"E", 0}, - {"EXCEPTION-FILE", 0}, - {"EXCEPTION-FILE-N", 0}, - {"EXCEPTION-LOCATION", 0}, - {"EXCEPTION-LOCATION-N", 0}, - {"EXCEPTION-STATEMENT", 0}, - {"EXCEPTION-STATUS", 0}, - {"EXP", 0}, - {"EXP10", 0}, - {"FACTORIAL", 0}, - {"FIND-STRING", 0}, - {"FORMATTED-CURRENT-DATE", 0}, - {"FORMATTED-DATE", 0}, - {"FORMATTED-DATETIME", 0}, - {"FORMATTED-TIME", 0}, - {"FRACTION-PART", 0}, - {"HIGHEST-ALGEBRAIC", 0}, - {"INTEGER", 0}, - {"INTEGER-OF-BOOLEAN", 0}, - {"INTEGER-OF-DATE", 0}, - {"INTEGER-OF-DAY", 0}, - {"INTEGER-OF-FORMATTED-DATE", 0}, - {"INTEGER-PART", 0}, - {"LENGTH", 0}, - {"LOCALE-COMPARE", 0}, - {"LOCALE-DATE", 0}, - {"LOCALE-TIME", 0}, - {"LOCALE-TIME-FROM-SECONDS", 0}, - {"LOG", 0}, - {"LOG10", 0}, - {"LOWER-CASE", 0}, - {"LOWEST-ALGEBRAIC", 0}, - {"MAX", 0}, - {"MEAN", 0}, - {"MEDIAN", 0}, - {"MIDRANGE", 0}, - {"MIN", 0}, - {"MOD", 0}, - {"MODULE-NAME", 0}, - {"NATIONAL-OF", 0}, - {"NUMVAL", 0}, - {"NUMVAL-C", 0}, - {"NUMVAL-F", 0}, - {"ORD", 0}, - {"ORD-MAX", 0}, - {"ORD-MIN", 0}, - {"PI", 0}, - {"PRESENT-VALUE", 0}, - {"RANDOM", 0}, - {"RANGE", 0}, - {"REM", 0}, - {"REVERSE", 0}, - {"SECONDS-FROM-FORMATTED-TIME", 0}, - {"SECONDS-PAST-MIDNIGHT", 0}, - {"SIGN", 0}, - {"SIN", 0}, - {"SMALLEST-ALGEBRAIC", 0}, - {"SQRT", 0}, - {"STANDARD-COMPARE", 0}, - {"STANDARD-DEVIATION", 0}, - {"SUBSTITUTE", 0}, - {"SUM", 0}, - {"TAN", 0}, - {"TEST-DATE-YYYYMMDD", 0}, - {"TEST-DAY-YYYYDDD", 0}, - {"TEST-FORMATTED-DATETIME", 0}, - {"TEST-NUMVAL", 0}, - {"TEST-NUMVAL-C", 0}, - {"TEST-NUMVAL-F", 0}, - {"TRIM", 0}, - {"UPPER-CASE", 0}, - {"VARIANCE", 0}, - {"WHEN-COMPILED", 0}, - {"YEAR-TO-YYYY", 0}, - }; -} diff --git a/Otterkit.Types/src/Token/Token.Methods.cs b/Otterkit.Types/src/Token/Token.Methods.cs deleted file mode 100644 index bff56df6..00000000 --- a/Otterkit.Types/src/Token/Token.Methods.cs +++ /dev/null @@ -1,356 +0,0 @@ -using System.Globalization; -using System.Text; -using System.Text.RegularExpressions; - -namespace Otterkit.Types; - -public sealed partial record Token -{ - public string FetchFile => CompilerContext.FileNames[FileIndex]; - - public static List ClassifyTokens(List tokens) - { - Token previousToken = tokens[0]; - - foreach (Token token in tokens) - { - token.Type = FindType(token); - token.Scope = FindScope(token, previousToken); - token.Context = FindContext(token); - - previousToken = token; - } - - // If a tokenizer error has occured, terminate the compilation process. - // We do not want the compiler to continue when the source code - // potentially contains invalid Unicode. - if (ErrorHandler.HasOccurred) ErrorHandler.StopCompilation("a tokenizer"); - - return tokens; - } - - private static bool TryValidateIdentifier(Token token) - { - // The Unicode standard requires us to document how this works: - - // Otterkit COBOL Identifier Profile (profile of UAX31-R1-1): - // Identifiers must not have more than 63 characters and are case-insensitive. - // All identifiers that contain non-normalized characters are converted into the Normalization Form NFKC - - // Identifier := XID_Start (Medial | XID_Continue)* XID_Continue - // XID_Start := - // XID_Continue := - // Medial := - - // Characters with the Other_ID_Start and Other_ID_Continue properties can be found here: https://www.unicode.org/Public/15.0.0/ucd/PropList.txt - - var fileName = token.FetchFile; - - if (!token.Value.IsNormalized(NormalizationForm.FormKC)) - { - try - { - // If the identifier contains non-normalized characters, - // try to convert into the Normalization Form NFKC. - token.Value = token.Value.Normalize(NormalizationForm.FormKC); - } - catch (ArgumentException) - { - // https://learn.microsoft.com/en-us/dotnet/api/system.string.normalize - // If a string contains non-normalized characters followed by invalid Unicode characters, - // the Normalize method will throw an ArgumentException. - // Return false and report a syntax error: - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 125,""" - Invalid Unicode character. - """) - .WithSourceLine(token, """ - Conversion into Normalization Form NFKC failed due to an invalid character. - """) - .CloseError(); - - return false; - } - } - - if (token.Value.Length >= 64) - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 130,""" - Invalid identifier. - """) - .WithSourceLine(token, """ - Identifiers must not have more than 63 characters. - """) - .CloseError(); - - return false; - } - - var matchesStartCategory = char.GetUnicodeCategory(token.Value[0]) switch - { - UnicodeCategory.UppercaseLetter or // Lu - UnicodeCategory.LowercaseLetter or // Ll - UnicodeCategory.TitlecaseLetter or // Lt - UnicodeCategory.ModifierLetter or // Lm - UnicodeCategory.OtherLetter or // Lo - UnicodeCategory.LetterNumber => true, // Nl - _ => false - }; - - var matchesOtherStartCharacters = token.Value[0] switch - { - // This list includes all characters with the property Other_ID_Start - '\u1885' or '\u1886' => true, // MONGOLIAN LETTER ALI GALI BALUDA .. MONGOLIAN LETTER ALI GALI THREE BALUDA - '\u2118' => true, // SCRIPT CAPITAL P - '\u212E' => true, // ESTIMATED SYMBOL - '\u309B' or '\u309C' => true, // KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK - '0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9' => true, // [0-9] Basic digits required by the COBOL Standard - - // NFKC Modifications: - '\u0E33' => false, // THAI CHARACTER SARA AM - '\u0EB3' => false, // LAO VOWEL SIGN AM - '\uFF9E' => false, // HALFWIDTH KATAKANA VOICED SOUND MARK - '\uFF9F' => false, // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK - '\u037A' => false, // U+037A GREEK YPOGEGRAMMENI - _ => false - }; - - if (!matchesStartCategory && !matchesOtherStartCharacters) - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 130,""" - Invalid identifier. - """) - .WithSourceLine(token, """ - Invalid character at the start of this identifier. - """) - .CloseError(); - - return false; - } - - static bool matchesContinueCategory(char character) - { - return char.GetUnicodeCategory(character) switch - { - UnicodeCategory.UppercaseLetter or // Lu - UnicodeCategory.LowercaseLetter or // Ll - UnicodeCategory.TitlecaseLetter or // Lt - UnicodeCategory.ModifierLetter or // Lm - UnicodeCategory.OtherLetter or // Lo - UnicodeCategory.LetterNumber or // Nl - UnicodeCategory.NonSpacingMark or // Mn - UnicodeCategory.SpacingCombiningMark or // Mc - UnicodeCategory.DecimalDigitNumber or // Nd - UnicodeCategory.ConnectorPunctuation => true, // Pc - _ => false - }; - } - - static bool matchesOtherContinueCharacters(char character) - { - return character switch - { - // This list includes all characters with the properties Other_ID_Start and Other_ID_Continue - '\u1885' or '\u1886' => true, // MONGOLIAN LETTER ALI GALI BALUDA .. MONGOLIAN LETTER ALI GALI THREE BALUDA - '\u2118' => true, // SCRIPT CAPITAL P - '\u212E' => true, // ESTIMATED SYMBOL - '\u309B' or '\u309C' => true, // KATAKANA-HIRAGANA VOICED SOUND MARK .. KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK - '0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9' => true, // [0-9] Basic digits required by the COBOL Standard - '\u00B7' => true, // MIDDLE DOT - '\u0387' => true, // GREEK ANO TELEIA - '\u1369' or '\u136A' or '\u136B' or '\u136C' or '\u136D' or '\u136E' or '\u136F' or '\u1370' or '\u1371' => true, // ETHIOPIC DIGIT ONE .. ETHIOPIC DIGIT NINE - '\u19DA' => true, // NEW TAI LUE THAM DIGIT ONE - // Extra characters required by the COBOL standard: - '\u002D' or '\u005F' => true, // minus sign (HYPHEN-MINUS) and underscore (LOW LINE) - '\u30FB' => true, // KATAKANA MIDDLE DOT - - // NFKC Modifications: - '\u037A' => false, // U+037A GREEK YPOGEGRAMMENI - _ => false - }; - } - - foreach (var character in token.Value.AsSpan(1)) - { - if (!matchesContinueCategory(character) && !matchesOtherContinueCharacters(character)) - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 130,""" - Invalid identifier. - """) - .WithSourceLine(token, """ - Invalid character in the middle of this identifier. - """) - .CloseError(); - - return false; - } - } - - if (token.Value[token.Value.Length - 1] is '\u002D' or '\u005F' or '\u30FB') - { - ErrorHandler - .Build(ErrorType.Syntax, ConsoleColor.Red, 130,""" - Invalid identifier. - """) - .WithSourceLine(token, """ - Invalid character at the end of this identifier. - """) - .CloseError(); - - return false; - } - - return true; - } - - private static TokenType FindType(Token token) - { - if (token.Type is not TokenType.None) return token.Type; - - var value = token.Value; - - // check if the value is a reserved keyword - if (IsReservedWord(value)) - return TokenType.ReservedKeyword; - - // check if the value is a figurative literal - if (IsFigurativeLiteral(value)) - return TokenType.Figurative; - - if (IsOtterkitDevice(token.Value)) - return TokenType.Device; - - // check if the value is an intrinsic function - if (IsStandardIntrinsic(value)) - return TokenType.IntrinsicFunction; - - // check if the value is a symbol - if (IsStandardSymbol(value)) - return TokenType.Symbol; - - // check if the value is a numeric - if (IsNumeric(value) && NumericRegex().IsMatch(value)) - return TokenType.Numeric; - - // check if the value is End Of File - if (value.Equals("EOF")) - return TokenType.EOF; - - // if none of the above, it's an identifier - if (!TryValidateIdentifier(token)) - { - ErrorHandler.HasOccurred = true; - } - - return TokenType.Identifier; - } - - private static TokenContext FindContext(Token token) - { - // check if the token belongs to a data division clause - if (IsStandardClause(token.Value)) - return TokenContext.IsClause; - - // check if the token is a statement - if (IsStandardStatement(token.Value)) - return TokenContext.IsStatement; - - // check if the token is a system device - if (IsOtterkitDevice(token.Value)) - return TokenContext.IsDevice; - - // check if the token represents a file separator - if (token.Line is -5) - return TokenContext.IsEOF; - - // if none of the above, return none - return TokenContext.None; - } - - private static TokenScope FindScope(Token token, Token previousToken) - { - if (token.Value.Equals("PROGRAM-ID", StringComparison.OrdinalIgnoreCase)) - return TokenScope.ProgramId; - - if (token.Value.Equals("FUNCTION-ID", StringComparison.OrdinalIgnoreCase)) - return TokenScope.FunctionId; - - if (token.Value.Equals("INTERFACE-ID", StringComparison.OrdinalIgnoreCase)) - return TokenScope.InterfaceId; - - if (token.Value.Equals("CLASS-ID", StringComparison.OrdinalIgnoreCase)) - return TokenScope.ClassId; - - if (token.Value.Equals("METHOD-ID", StringComparison.OrdinalIgnoreCase)) - return TokenScope.MethodId; - - if (token.Value.Equals("ENVIRONMENT", StringComparison.OrdinalIgnoreCase)) - return TokenScope.EnvironmentDivision; - - if (token.Value.Equals("DATA", StringComparison.OrdinalIgnoreCase)) - return TokenScope.DataDivision; - - if (token.Value.Equals("PROCEDURE", StringComparison.OrdinalIgnoreCase)) - return TokenScope.ProcedureDivision; - - if (token.Value.Equals("FACTORY", StringComparison.OrdinalIgnoreCase)) - return TokenScope.Factory; - - if (token.Value.Equals("OBJECT", StringComparison.OrdinalIgnoreCase)) - return TokenScope.Object; - - return previousToken.Scope; - } - - private static bool IsNumeric(ReadOnlySpan value) - { - return value switch - { - ['+' or '-', '0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9', .. _] => true, - ['.', '0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9', .. _] => true, - ['0' or '1' or '2' or '3' or '4' or '5' or '6' or '7' or '8' or '9', .. _] => true, - [..] => false - }; - - } - - public bool SamePosition(Token token) - { - var sameFile = FileIndex == token.FileIndex; - - if (!sameFile) return false; - - var sameLine = Line == token.Line; - - if (!sameLine) return false; - - var sameColumn = Column == token.Column; - - if (!sameColumn) return false; - - return true; - } - - public override sealed string ToString() - { - StringBuilder stringBuilder = new(); - stringBuilder.Append("Token"); - stringBuilder.Append(" { "); - - stringBuilder.Append($"Ln: {Line, -6},"); - stringBuilder.Append($"Col: {Column, -6},"); - stringBuilder.Append($"Type: {Type, -18},"); - stringBuilder.Append($"Scope: {Scope, -20},"); - stringBuilder.Append($"Context: {Context, -12},"); - stringBuilder.Append($"Value: {Value}"); - - stringBuilder.Append(" }"); - return stringBuilder.ToString(); - } - - [GeneratedRegex("^(\\+|-)?\\.?[0-9]+(\\.[0-9]+)?$", RegexOptions.ExplicitCapture | RegexOptions.NonBacktracking)] - private static partial Regex NumericRegex(); -} diff --git a/Otterkit.Types/src/Token/Token.cs b/Otterkit.Types/src/Token/Token.cs deleted file mode 100644 index 31130de8..00000000 --- a/Otterkit.Types/src/Token/Token.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Otterkit.Types; - -public sealed partial record Token -{ - public int Line; - public int Column; - public string Value; - public int FileIndex; - public TokenType Type; - public TokenScope Scope; - public TokenContext Context; - - public Token(string value, TokenType type, int line, int column) - { - Line = line; - Column = column; - Value = value; - Type = type; - } - - public Token(string value, TokenType type) - { - Value = value; - Type = type; - } -} diff --git a/Otterkit.Types/src/Token/TokenContext.cs b/Otterkit.Types/src/Token/TokenContext.cs deleted file mode 100644 index bef4cdae..00000000 --- a/Otterkit.Types/src/Token/TokenContext.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Otterkit.Types; - -public enum TokenContext -{ - None, - IsClause, - IsStatement, - IsDevice, - IsFigurative, - IsSymbol, - IsEOF -} diff --git a/Otterkit.Types/src/Token/TokenScope.cs b/Otterkit.Types/src/Token/TokenScope.cs deleted file mode 100644 index f8e9ac7a..00000000 --- a/Otterkit.Types/src/Token/TokenScope.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Otterkit.Types; - -public enum TokenScope -{ - Root, - ProgramId, - FunctionId, - InterfaceId, - ClassId, - MethodId, - Factory, - Object, - EnvironmentDivision, - DataDivision, - ProcedureDivision -} diff --git a/Otterkit.Types/src/Token/TokenType.cs b/Otterkit.Types/src/Token/TokenType.cs deleted file mode 100644 index e9af9684..00000000 --- a/Otterkit.Types/src/Token/TokenType.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Otterkit.Types; - -[Flags] -public enum TokenType -{ - None, - Error, - ReservedKeyword = 1 << 1, - Figurative = 1 << 2, - IntrinsicFunction = 1 << 3, - Symbol = 1 << 4, - Picture = 1 << 5, - String = 1 << 6, - HexString = 1 << 7, - Boolean = 1 << 8, - HexBoolean = 1 << 9, - National = 1 << 10, - HexNational = 1 << 11, - Numeric = 1 << 12, - Identifier = 1 << 13, - Expression = 1 << 14, - Device = 1 << 15, - EOF = 1 << 16, -} diff --git a/Otterkit.Types/src/TokenHandling.cs b/Otterkit.Types/src/TokenHandling.cs deleted file mode 100644 index e339e98b..00000000 --- a/Otterkit.Types/src/TokenHandling.cs +++ /dev/null @@ -1,222 +0,0 @@ -namespace Otterkit.Types; - -public static class TokenHandling -{ - /// - /// Used for keeping track of the current token list index. - /// - public static int Index; - public static List Source => CompilerContext.SourceTokens; - - // Analyzer token handling methods. - // These are the main methods used to interact with and iterate through the List of Tokens. - // (And other helpers that it easier to iterate through the List) - // All other methods inside of the analyzer depend on these to parse through the tokens. - public static void AnchorPoint(ReadOnlySpan anchors) - { - while (!CurrentEquals(TokenType.EOF)) - { - if (CurrentEquals(".")) - { - Continue(); - return; - } - - if (CurrentEquals(anchors)) - { - return; - } - - Continue(); - } - } - - public static void AnchorPoint(TokenContext anchor) - { - while (!CurrentEquals(TokenType.EOF)) - { - if (CurrentEquals(".") || CurrentEquals(". ")) - { - Continue(); - return; - } - - if (CurrentEquals(anchor)) - { - return; - } - - Continue(); - } - } - - public static void AnchorPoint(TokenContext anchor, ReadOnlySpan anchors) - { - while (!CurrentEquals(TokenType.EOF)) - { - if (CurrentEquals(".")) - { - Continue(); - return; - } - - if (CurrentEquals(anchors) || CurrentEquals(anchor)) - { - return; - } - - Continue(); - } - } - - public static int CurrentLine() - { - return Current().Line; - } - - public static int CurrentColumn() - { - return Current().Column; - } - - public static int CurrentFile() - { - return Current().FileIndex; - } - - public static Token Peek(int amount) - { - if (Index + amount >= Source.Count) return Source[^1]; - - return Index + amount < 0 ? Source[0] : Source[Index + amount]; - } - - public static bool PeekEquals(int amount, ReadOnlySpan keyword) - { - if (keyword.Contains(' ')) - { - return Optimization.SpaceSeparatedSearch(keyword, Peek(amount).Value); - } - - return keyword.Equals(Peek(amount).Value, StringComparison.OrdinalIgnoreCase); - } - - public static bool PeekEquals(int amount, TokenType type) - { - return type.HasFlag(Peek(amount).Type); - } - - public static Token Current() - { - return Source[Index]; - } - - public static bool CurrentEquals(ReadOnlySpan keyword) - { - if (keyword.Contains(' ')) - { - return Optimization.SpaceSeparatedSearch(keyword, Current().Value); - } - - return keyword.Equals(Current().Value, StringComparison.OrdinalIgnoreCase); - } - - public static bool CurrentEquals(TokenType tokenType) - { - return tokenType.HasFlag(Current().Type); - } - - public static bool CurrentEquals(TokenContext tokenContext) - { - return Current().Context == tokenContext; - } - - public static void Continue(int amount = 1) - { - if (CurrentEquals(TokenType.EOF) && Index >= Source.Count - 1) return; - - Index += amount; - } - - public static void Choice(ReadOnlySpan choices) - { - if (Optimization.SpaceSeparatedSearch(choices, Current().Value)) - { - Continue(); - - return; - } - - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, """ - Unexpected token. - """) - .WithSourceLine(Current(), $""" - Expected one of the following: {string.Concat(", ", choices)}, - """) - .CloseError(); - - Continue(); - } - - public static void Optional(ReadOnlySpan optional) - { - if (CurrentEquals(optional)) Continue(); - } - - public static void OptionalChoice(ReadOnlySpan choices) - { - if (Optimization.SpaceSeparatedSearch(choices, Current().Value)) - { - Continue(); - } - } - - public static bool Expected(ReadOnlySpan expected, bool useDefaultError = true) - { - if (CurrentEquals(TokenType.EOF)) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 0, """ - Unexpected end of file. - """) - .WithSourceLine(Peek(-1), $""" - Expected {expected} after this token. - """) - .CloseError(); - - // Error has already been handled above - return true; - } - - var isExpectedToken = CurrentEquals(expected); - - if (!isExpectedToken && useDefaultError) - { - ErrorHandler - .Build(ErrorType.Analyzer, ConsoleColor.Red, 5, """ - Unexpected token. - """) - .WithSourceLine(Current(), $""" - Expected '{expected}' here, found '{Current().Value}' instead - """) - .CloseError(); - - // Error has already been handled above - // Handled using a default error message - return true; - } - - if (!isExpectedToken && !useDefaultError) - { - // Error has not been handled - // Expected to be handled by the consumer - // of this method using an if statement - return false; - } - - Continue(); - - return true; - } -} diff --git a/Otterkit.Types/src/UnitTypes/AbstractUnit.cs b/Otterkit.Types/src/UnitTypes/AbstractUnit.cs deleted file mode 100644 index ad444a64..00000000 --- a/Otterkit.Types/src/UnitTypes/AbstractUnit.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Otterkit.Types; - -public abstract class AbstractUnit -{ - public Token Identifier; - public UnitKind SourceKind; - public Option ExternalizedName; - - protected AbstractUnit(Token identifier, UnitKind sourceKind) - { - Identifier = identifier; - SourceKind = sourceKind; - } -} diff --git a/Otterkit.Types/src/UnitTypes/CallableUnit.cs b/Otterkit.Types/src/UnitTypes/CallableUnit.cs deleted file mode 100644 index 48a404e5..00000000 --- a/Otterkit.Types/src/UnitTypes/CallableUnit.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Otterkit.Types; - -// Don't use a separate class or struct for this, -// a ValueTuple is enough, and gives us extra syntax sugar -using ParameterTuple = ValueTuple; - -public class CallableUnit : AbstractUnit -{ - public LocalNames LocalNames = new(); - public DataNames DataNames = new(); - public List Parameters = new(); - public Option Returning; - public bool Override; - public bool IsFinal; - - public CallableUnit(Token identifier, UnitKind sourceKind) - : base (identifier, sourceKind) { } -} diff --git a/Otterkit.Types/src/UnitTypes/ClassUnit.cs b/Otterkit.Types/src/UnitTypes/ClassUnit.cs deleted file mode 100644 index 7f80628e..00000000 --- a/Otterkit.Types/src/UnitTypes/ClassUnit.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Otterkit.Types; - -public class ClassUnit : AbstractUnit -{ - public bool IsFinal; - public List Using = new(); - public Option Inherits; - - public List FactoryImplements = new(); - public List ObjectImplements = new(); - - public List FactoryMethods = new(); - public List ObjectMethods = new(); - - public ClassUnit(Token identifier, UnitKind sourceKind) - : base (identifier, sourceKind) { } -} diff --git a/Otterkit.Types/src/UnitTypes/InterfaceUnit.cs b/Otterkit.Types/src/UnitTypes/InterfaceUnit.cs deleted file mode 100644 index e927f46a..00000000 --- a/Otterkit.Types/src/UnitTypes/InterfaceUnit.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Otterkit.Types; - -public class InterfaceUnit : AbstractUnit -{ - public bool IsFinal; - public List Using = new(); - public List Inherits = new(); - - // Interface prototype methods - public List Methods = new(); - - public InterfaceUnit(Token identifier, UnitKind sourceKind) - : base (identifier, sourceKind) { } -} \ No newline at end of file diff --git a/Otterkit.Types/src/UnitTypes/IntrinsicUnit.cs b/Otterkit.Types/src/UnitTypes/IntrinsicUnit.cs deleted file mode 100644 index 2b5387ef..00000000 --- a/Otterkit.Types/src/UnitTypes/IntrinsicUnit.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Otterkit.Types; - -public record struct IntrinsicType(Classes Class, Categories Category); - -public class IntrinsicUnit : AbstractUnit -{ - public List Parameters = new(); - public List IsOptional = new(); - public Option Returning; - - public IntrinsicUnit(Token identifier, UnitKind sourceKind) - : base (identifier, sourceKind) { } - - public (List Types, List IsOptional) GetParameters() - { - return (Parameters, IsOptional); - } -} diff --git a/Otterkit.Workspaces/Otterkit.Workspaces.csproj b/Otterkit.Workspaces/Otterkit.Workspaces.csproj deleted file mode 100644 index c636adde..00000000 --- a/Otterkit.Workspaces/Otterkit.Workspaces.csproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - net7.0 - enable - enable - true - true - true - - - - - true - Otterkit.Workspaces - ./nupkg - Apache-2.0 - 1.0.70 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;COBOL;Workspace;Projects - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - This package contains classes and methods for Otterkit COBOL project file handling. - - - - - - - - - - - - - - diff --git a/Otterkit.Workspaces/README.md b/Otterkit.Workspaces/README.md deleted file mode 100644 index ac7ce894..00000000 --- a/Otterkit.Workspaces/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Otterkit.Workspaces namespace - -This namespace contains classes and methods for -Otterkit COBOL project file handling. diff --git a/Otterkit.Workspaces/src/Build.Properties.cs b/Otterkit.Workspaces/src/Build.Properties.cs deleted file mode 100644 index e7e42257..00000000 --- a/Otterkit.Workspaces/src/Build.Properties.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit.Workspaces; - -public class Build -{ - public string Main { get; set; } - public OutputType Output { get; set; } - public SourceFormat Format { get; set; } - public int Columns { get; set; } - - public Build() - { - // Setup project defaults - Main = "main.cob"; - Output = OutputType.Application; - Format = SourceFormat.Auto; - Columns = 80; - } -} diff --git a/Otterkit.Workspaces/src/Otterproj.Properties.cs b/Otterkit.Workspaces/src/Otterproj.Properties.cs deleted file mode 100644 index cae9333e..00000000 --- a/Otterkit.Workspaces/src/Otterproj.Properties.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Otterkit.Workspaces; - -public class Otterproj -{ - public string Name { get; set; } - public string? PackageId { get; set; } - public string? Description { get; set; } - public string? Authors { get; set; } - public string? License { get; set; } - public Project Project { get; set; } - public Build Build { get; set; } - - public Otterproj() - { - // Setup project defaults - Name = "Program"; - Project = new(); - Build = new(); - } -} diff --git a/Otterkit.Workspaces/src/Project.Properties.cs b/Otterkit.Workspaces/src/Project.Properties.cs deleted file mode 100644 index 9a008b89..00000000 --- a/Otterkit.Workspaces/src/Project.Properties.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Otterkit.Types; - -namespace Otterkit.Workspaces; - -public class Project -{ - public string Sdk { get; set; } - public string Target { get; set; } - public string Standard { get; set; } - - - public Project() - { - // Setup project defaults - Sdk = "main.cob"; - Target = "net7.0"; - Standard = "2023"; - } -} diff --git a/Otterkit.Workspaces/src/ProjectJsonContext.cs b/Otterkit.Workspaces/src/ProjectJsonContext.cs deleted file mode 100644 index a5b8a48f..00000000 --- a/Otterkit.Workspaces/src/ProjectJsonContext.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Otterkit.Workspaces; - -[JsonSerializable(typeof(Otterproj))] -[JsonSourceGenerationOptions( - GenerationMode = JsonSourceGenerationMode.Default, - PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - WriteIndented = true -)] -public partial class ProjectJsonContext : JsonSerializerContext { } diff --git a/Otterkit.Workspaces/src/ProjectLoader.cs b/Otterkit.Workspaces/src/ProjectLoader.cs deleted file mode 100644 index adb10021..00000000 --- a/Otterkit.Workspaces/src/ProjectLoader.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Buffers; -using System.IO.Pipelines; -using System.Text.Json; -using Otterkit.Types; - -namespace Otterkit.Workspaces; - -public static class ProjectLoader -{ - private static readonly ArrayPool ArrayPool = ArrayPool.Shared; - - public static async ValueTask> ReadOtterproj(string otterprojPath) - { - using var otterprojStream = File.OpenRead(otterprojPath); - - var pipeReader = PipeReader.Create(otterprojStream); - - ReadOnlySequence buffer; - - while (true) - { - var readAsync = await pipeReader.ReadAsync(); - - if (readAsync.IsCompleted) - { - buffer = readAsync.Buffer; - break; - } - - pipeReader.AdvanceTo(readAsync.Buffer.Start, readAsync.Buffer.End); - } - - var length = (int)buffer.Length; - var sharedArray = ArrayPool.Rent(length); - - buffer.CopyTo(sharedArray); - - Option otterproj; - - try - { - otterproj = JsonSerializer.Deserialize(sharedArray.AsSpan(0, length), ProjectJsonContext.Default.Otterproj); - } - catch (JsonException exception) - { - var message = exception.Message; - ErrorHandler.Build(ErrorType.Compilation, ConsoleColor.Red, 9555, """ - Failed to load .otterproj project file. - """) - .WithStartingException($""" - {message.AsSpan(0, message.IndexOf('.') + 1)} - """) - .CloseError(); - - otterproj = null; - } - finally - { - ArrayPool.Return(sharedArray); - } - - return otterproj; - } - - public static bool TryLoadProject(Option otterproj) - { - if (!otterproj.Exists) return false; - - var unwrap = otterproj.Unwrap(); - - var build = unwrap.Build; - - CompilerOptions.Initialize(unwrap.Name, build.Main); - - CompilerOptions.SetOptions(build.Output, build.Format, build.Columns); - - return true; - } -} diff --git a/README.md b/README.md index 090911b6..b504404c 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,4 @@ -# Otterkit COBOL Compiler - -Otterkit is an effort to fully modernize the COBOL ecosystem by building a standard conforming implementation (of the [ISO/IEC 1989:2023](https://www.iso.org/standard/74527.html) standard) and to give developers access to modern Standard COBOL features, modern tooling and a better development experience. - -The current situation in the COBOL ecosystem presents a unique opportunity for our project to create a unified and open source platform for COBOL development. We strongly believe that COBOL is capable of so much more than just being a legacy mainframe language, perpetually stuck with legacy standards. - -Our biggest reason for advocating open source in the COBOL ecosystem is that while paying for a compiler may be feasible for larger companies, it currently creates a barrier for individual developers and students who wish to learn COBOL or stay up-to-date with its latest features. We want to change that, by making it accessible for everyone and hopefully helping modernize and unify ecosystem. - -Otterkit and its runtime library are being built entirely in C# (with .NET 7). It compiles COBOL code into C# (with our runtime library) which is then compiled into an executable by the dotnet compiler. - -Warning: The project is currently in pre-release, so not all of the standard has been implemented. - -## About COBOL - -COBOL was created in 1959 by the [CODASYL Committee](https://en.wikipedia.org/wiki/CODASYL) (With Rear Admiral Grace Hopper as a technical consultant to the committee), its design follows Grace Hopper's belief that programs should be written in a language that is close to English. It prioritizes readability, reliability, and long-term maintenance. The language has been implemented throughout the decades on many platforms with many dialects. - -## Frequently Asked Questions - -- What evidence do you have that there's demand for COBOL 2023? - -There will never be a demand for it if developers can't get their hands on modern COBOL to try it out. - -A good comparison for this is that there would be (most likely) no demand for Rust, if developers couldn't get their hands on Rust to try it out. Now that a lot of developers and companies did, there is a growing demand. - -If developers are not aware of most modern COBOL features and no compiler supports it, how can there be any demand for these features? - -It's almost like these features never existed, but we want to help improve this situation and bring more awareness to COBOL's more modern features. - -## Installation - -### Quick Install - -Otterkit is available to install on the [Nuget package manager](https://www.nuget.org/packages/Otterkit/) ([.NET 7](https://dotnet.microsoft.com/en-us/download/dotnet/7.0) is required). To install, type these two lines into the command line: - -``` -dotnet new install Otterkit.Templates::1.7.50 - -dotnet tool install --global Otterkit --version 1.0.80 -``` - -### Create and Build a COBOL Project - -Create a new application (executable) project: - -``` -otterkit new app -``` - -Build the project by specifying the entry point (main file): - -``` -otterkit build -e ${MAIN-FILE}.cob --free -``` - -Build and run the project by specifying the entry point (main file): - -``` -otterkit build --run -e ${MAIN-FILE}.cob --free -``` - -### Build from Source - -First, run the git clone command, with the relevant arguments: -``` -git clone https://github.com/otterkit/otterkit.git --recurse-submodules --remote-submodules -``` -The *recurse-submodules* and *remote-submodules* flags are needed to access the [libotterkit](https://github.com/otterkit/libotterkit) submodule inside. - -Then, navigate into the `otterkit/src` folder (for the compiler, not libotterkit) and then type `dotnet run` into the command line to run and test if everything is working. - -## Sponsors and Open Source Support - -

Open Source Support

- -

- - JetBrains Logo (Main) logo. - -

- -## Standard Acknowledgement - -Any organization interested in reproducing the COBOL standard and specifications in whole or in part, -using ideas from this document as the basis for an instruction manual or for any other purpose, is free -to do so. However, all such organizations are requested to reproduce the following acknowledgment -paragraphs in their entirety as part of the preface to any such publication (any organization using a -short passage from this document, such as in a book review, is requested to mention "COBOL" in -acknowledgment of the source, but need not quote the acknowledgment): - -COBOL is an industry language and is not the property of any company or group of companies, or of any -organization or group of organizations. - -No warranty, expressed or implied, is made by any contributor or by the CODASYL COBOL Committee -as to the accuracy and functioning of the programming system and language. Moreover, no -responsibility is assumed by any contributor, or by the committee, in connection therewith. - -The authors and copyright holders of the copyrighted materials used herein: - -- FLOW-MATIC® (trademark of Sperry Rand Corporation), Programming for the 'UNIVAC® I and - II, Data Automation Systems copyrighted 1958,1959, by Sperry Rand Corporation; -- IBM Commercial Translator Form No F 28-8013, copyrighted 1959 by IBM; -- FACT, DSI 27A5260-2760, copyrighted 1960 by Minneapolis-Honeywell - -Have specifically authorized the use of this material in whole or in part, in the COBOL specifications. -Such authorization extends to the reproduction and use of COBOL specifications in programming -manuals or similar publications. +# Otterkit Toolchain ## Contributing If you have any questions, please feel free to reach out by [opening an issue](https://github.com/otterkit/otterkit/issues) or a [new discussion post](https://github.com/orgs/otterkit/discussions). We're happy to welcome new contributors! @@ -111,7 +6,7 @@ If you have any questions, please feel free to reach out by [opening an issue](h Please keep in mind that the project is licensed under the Apache-2.0, and all contributions (unless otherwise specified) will be made available under the same terms (Apache-2.0, Submission of Contributions). ## Copyright -Copyright © 2022-2023 Gabriel Gonçalves <KTSnowy@outlook.com> +Copyright © 2022-2024 Gabriel Gonçalves <KTSnowy@outlook.com> Unless otherwise specified, all files in this repo (except the Otterkit logo) are licensed under the Apache-2.0 license. diff --git a/SECURITY.md b/SECURITY.md index 9b9ecb70..174f2b62 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,11 +3,11 @@ ## Reporting a Vulnerability If the vulnerability can be discussed publicly due to not being exploitable: - - Please open a new issue with the "Report a security vulnerability in the runtime library" template. + - Please open a new issue with the "Report a security vulnerability" template. If the vulnerability cannot be discussed publicly due to being potentially exploitable: - Please send an email to the following address: security@otterkit.com - - With the subject field "Otterkit Compiler Security Vulnerability" + - With the subject field "Otterkit Toolchain Security Vulnerability" - Include a detailed description of the vulnerability, where it occurs and the steps to reproduce it. - Open a new issue with the "Report a security vulnerability" template, do not include where it occurs -or how to reproduce it, only mention that an email has been sent to discuss the vulnerability. + or how to reproduce it, only mention that an email has been sent to discuss the vulnerability. diff --git a/src/IR-design.md b/src/IR-design.md deleted file mode 100644 index a23724c8..00000000 --- a/src/IR-design.md +++ /dev/null @@ -1,120 +0,0 @@ -# Otterkit Intermediate Representation Design - -The Otterkit Intermediate Representation (IR) is a language agnostic representation of a COBOL program, meant to be used as an internal input for the code generator. The IR is designed to allow for easier code generation to multiple target languages, and to allow for easier optimization and lowering language features to simpler constructs. - -## Design Goals - -The design goals of the IR are: - -- Easy to generate directly from the parser. -- Easy to use as input for the code generator. -- Moderately easy to read and understand. -- Minimize the amount of keywords the code generator needs to handle. -- Allow for easier optimization and lowering language features to simpler constructs. - -## Current Design - -This section describes the current design of the intermediate representation. The design is subject to change as we continue to develop and improve the IR. - -### Defining an IR unit - -A unit is defined by the `unit` keyword followed by the type of unit and the name of the unit. The type of unit can be `program`, `function`, `class`, or `interface`. The name of the unit is a global unique identifier prefixed by `@`. - -``` -unit program @hello-world -``` - -Program and function units must have a single `procedure` block. Class and interface units may have multiple `procedure` blocks, each defining a method. For the latter, the local variables for each method immediately precede the `procedure` block defining the method. - -### Defining an IR variable - -An IR variable is defined using the `automatic` `static`, `initial`, `parameter` or `return` keywords followed by the level number, the index of the variable (order in which it was defined) in the data division prefixed by `%v` (replaces the name, e.g. `%v0`), the class[type] of the variable (e.g. `fixed[999]`) and any other attributes (e.g. `occurs[10]`). - -``` -static 01 $0 fixed[999] -``` - -`automatic` `static`, `initial` refer to the life-time of variable. `automatic` variables are allocated on the stack on every unit call, `static` variables are allocated on the heap, staying in a last-used state between unit calls, and `initial` variables are allocated on the heap, being set to an initial state on every unit call. `parameter` and `return` refer to the parameters and return value of a procedure. - -`static` variables are not shared between object instances, each object instance has its own copy of the variable. - -`automatic` variables are only valid inside the procedure block they are defined in, and for objects, they are only valid inside the procedure block of the method they are defined in. - -`initial` variables only exist in program units defined with the `initial` attribute. - -`parameter` and `return` variables share the same life-time as the variables passed in by the caller. - -Note: the `return` variable is also passed in by the caller, and so its life-time is not the same as a local automatic variable's life-time. This is unlike other languages, where the return variable is allocated by the callee and passed back to the caller. - -See *8.6.4 Automatic, initial, and static internal items* in the COBOL 2023 standard for more information. - -### Defining an IR procedure - -An IR procedure is defined using the `procedure` keyword followed by the parameter list and the return value. The parameter list starts with the `params` keyword followed by the list of parameters. The return value starts with the `ret` keyword followed by the return value. When there are no parameters or return value, the list only contains a percent sign (`%`). The parameter list and return value are separated by the `|` character, each parameter is separated by a space. - -``` -procedure params|%| ret|%| => -``` - -Paragraphs and sections are defined using the `paragraph` and `section` keywords followed the index of the label (order in which it was defined) in the procedure division prefixed by `%l` (replaces the name, e.g. `%l0`). - -``` -[section %l0] - -[paragraph %l1] -``` - -### Defining an IR statement - -An IR statement is defined using the name of the statement followed by lists of "argument" values (e.g. `|"Hello"| |$0|`). The values of each list are separated inside a `| |` (e.g. `|arg arg ...|`), each argument is separated by a space. The arguments can be a literal, a variable, or a label. A literal can be any valid COBOL literal, a variable is a variable defined in the data division, and a label is a paragraph or section name. - -Statements are surrounded by square brackets (`[` and `]`). The name of the statement is followed by the lists of argument values for that particular statement. - -``` -[display |"Hello"| |$0|] -``` - -Statements can be nested inside other statements. The nested statements are also surrounded by square brackets. Arithmetic and conditional expressions are considered argument values, also separated inside a `| |`. - -``` -[if |$0 > 0| - [display |"Hello"| |$0|] -else - [display |"Goodbye"| |$0|]] -``` - -### Lowering language features to simpler constructs - -Certain language features can be lowered to simpler constructs without losing any features. For example, certain `perform` statements can be lowered to simpler forms. The following `perform` statement, which is equivalent to a for loop: - -```cobol -PERFORM VARYING X FROM 1 BY 1 UNTIL X > Y -. . . -END-PERFORM -``` - -Can be lowered to the following form, which is equivalent to a while loop with manual incrementing: - -```cobol -COMPUTE X = 1 -PERFORM UNTIL X > Y - - COMPUTE X = X + 1 -END-PERFORM -``` - -Certain statements can be completely removed from the IR. For example, the arithmetic `add` statement can be lowered to a simpler (for the runtime) `compute` statement. The following `add` statement: - -```cobol -ADD 1 TO X -``` - -Is equivalent to the following `compute` statement: - -```cobol -COMPUTE X = X + 1 -``` - -Lowering all arithmetic statements to specific combinations of `compute` could simplify both the code generator and runtime library, as they would only need to handle a single arithmetic statement as opposed to 5. No features would be lost, as all arithmetic statements can be lowered cleanly to one or two `compute` statements. - -More examples of lowering will be added here as a form of documentation as we continue to develop the IR. The goal is to lower as many language features as possible to simpler constructs, without losing any features. diff --git a/src/Otterkit.cs b/src/Otterkit.cs deleted file mode 100644 index b27b6409..00000000 --- a/src/Otterkit.cs +++ /dev/null @@ -1,430 +0,0 @@ -using System.Diagnostics; -using Otterkit.Analyzers; -using Otterkit.CodeGenerators; -using Otterkit.Tokenizers; -using Otterkit.Workspaces; -using Otterkit.Types; - -using Otterkit.Native; -using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Running; - -using System.Runtime.InteropServices; - -namespace Otterkit; - -[MemoryDiagnoser] -public unsafe partial class Bench { - public static void Run() { - BenchmarkRunner.Run(); - } - - [LibraryImport("nativelib", EntryPoint = "DynamicAlloc")] - public static partial void* DynamicAlloc(long length); - - [LibraryImport("nativelib", EntryPoint = "DynamicDealloc")] - public static partial void DynamicDealloc(void* length); - - [Benchmark] - public void BenchmarkDynamicAlloc() { - byte* alloc = (byte*)DynamicAlloc(32); - alloc[0] = 10; - alloc[31] = 200; - DynamicDealloc(alloc); - } - - [Benchmark] - public void BenchmarkMalloc() { - byte* alloc = (byte*)NativeMemory.Alloc(32); - alloc[0] = 10; - alloc[31] = 200; - NativeMemory.Free(alloc); - } -} - -public static class Otterkit -{ - public static void Main(string[] args) - { - Bench.Run(); - - if (args.Length < 1 || args[0].Equals("-h") || args[0].Equals("--help")) - { - DisplayHelpMessage(); - return; - } - - if (args[0] is "new" or "build" or "tools") - { - TryLoadProject(); - - CommandLineArguments(args); - return; - } - - DisplayHelpMessage(); - } - - private static void CommandLineArguments(string[] args) - { - // Index should always be +1 the true index: - // This makes it easier to get the next item after - // the command line argument, like the entry point file. - if (args[0].Equals("new")) - { - var index = 0; - foreach (string argument in args) - { - index++; - switch (argument) - { - case "app": - case "application": - CompilerOptions.Output = OutputType.Application; - break; - - case "lib": - case "library": - CompilerOptions.Output = OutputType.Library; - break; - - case "-n": - case "--name": - CompilerOptions.Name = args[index]; - break; - } - } - - CallDotnetCompiler(args[0]); - } - - if (args[0].Equals("build")) - { - var index = 0; - foreach (string argument in args) - { - index++; - switch (argument) - { - case "-h": - case "--help": - DisplayHelpMessage(); - Environment.Exit(0); - break; - - case "-e": - case "--entry": - CompilerOptions.Main = args[index]; - break; - - case "-cl": - case "--columns": - CompilerOptions.Columns = int.Parse(args[index]); - break; - - case "-t": - case "--tokenize": - CompilerOptions.Mode = BuildType.LexOnly; - break; - - case "-p": - case "--parse": - CompilerOptions.Mode = BuildType.ParseOnly; - break; - - case "-p:tokens": - case "--parse:tokens": - CompilerOptions.Mode = BuildType.PrintTokens; - break; - - case "-g": - case "--generate": - CompilerOptions.Mode = BuildType.GenerateOnly; - break; - - case "-r": - case "--run": - CompilerOptions.Mode = BuildType.BuildAndRun; - break; - - // --Fixed meaning Fixed Format - case "--fixed": - CompilerOptions.Format = SourceFormat.Fixed; - break; - // --Free meaning Free Format - case "--free": - CompilerOptions.Format = SourceFormat.Free; - break; - - case "--enable-extensions": - CompilerContext.ExtensionsEnabled = true; - break; - - case "--crash-on-error": - ErrorHandler.CrashOnError = true; - break; - } - } - - OtterkitMain(); - } - - if (args[0].Equals("tools")) - { - HandleToolsCommands(args); - } - } - - private static void HandleToolsCommands(string[] args) - { - for (var i = 1; i < args.Length; i++) - { - var argument = args[i]; - - var index = i + 1; - switch (argument) - { - case "--generate-exception-index": - Tools.GenerateExceptionIndex(); - break; - - case "--generate-unicode-data": - - Console.WriteLine("Generating Unicode Data..."); - - if (index > args.Length - 1 || args[index].StartsWith("--")) - { - Console.WriteLine("No path specified."); - goto default; - } - - Console.WriteLine($"Tools path: {args[index]}"); - - var path = args[index]; - - i++; - - Tools.GenerateBasicMultilingualPlane(path); - break; - - default: - Console.WriteLine($"Invalid command: {argument}"); - return; - } - } - } - - private static void TryLoadProject() - { - if (!File.Exists("package.otterproj")) return; - - var otterproj = ProjectLoader.ReadOtterproj("package.otterproj").AwaitResult(); - - if (!ProjectLoader.TryLoadProject(otterproj)) - { - ErrorHandler.StopCompilation("project"); - } - } - - private static void OtterkitMain() - { - var tokenizedLines = Tokenizer.Tokenize(CompilerOptions.Main); - - var classified = Token.ClassifyTokens(tokenizedLines); - - if (CompilerOptions.Mode is BuildType.LexOnly) - { - PrintTokens(); - return; - } - - var analized = Analyzer.Analyze(classified); - - if (CompilerOptions.Mode is BuildType.ParseOnly) - { - if (!ErrorHandler.HasOccurred) ErrorHandler.SuccessfulParse(); - } - - if (CompilerOptions.Mode is BuildType.PrintTokens) - { - PrintTokens(); - } - - TokenHandling.Index = 0; - - if (CompilerOptions.Mode is BuildType.GenerateOnly) - { - CodeGenerator.Generate(analized, CompilerOptions.Main); - } - - if (CompilerOptions.Mode is BuildType.BuildOnly) - { - CodeGenerator.Generate(CompilerContext.SourceTokens, CompilerOptions.Main); - - Directory.CreateDirectory(".otterkit/Build"); - CallDotnetCompiler("build"); - } - - if (CompilerOptions.Mode is BuildType.BuildAndRun) - { - CodeGenerator.Generate(CompilerContext.SourceTokens, CompilerOptions.Main); - - Directory.CreateDirectory(".otterkit/Build"); - CallDotnetCompiler("run"); - } - } - - private static void CallDotnetCompiler(string operation, bool output = true) - { - var arguments = string.Empty; - if (operation.Equals("new")) - { - var templateType = CompilerOptions.Output switch - { - OutputType.Application => "otterkit-app", - OutputType.Library => "otterkit-lib", - _ => "otterkit-app" - }; - - arguments = $"new {templateType} --force"; - - if (Directory.Exists(".otterkit") && File.Exists("package.otterproj")) - { - Console.WriteLine("A project already exists in this directory."); - Console.Write("Delete project and create a new one? ['y' or 'n'] "); - - var character = Console.ReadKey().KeyChar; - - Console.WriteLine(); - - if (character is not 'y') return; - - Directory.Delete(".otterkit", true); - File.Delete("package.otterproj"); - } - } - - if (operation.Equals("run")) - { - CallDotnetCompiler("build", false); - - var binaryName = ".otterkit/Build/OtterkitExport"; - - if (OperatingSystem.IsWindows()) - { - binaryName = @".otterkit\Build\OtterkitExport.exe"; - } - - using Process binary = new(); - binary.StartInfo.FileName = binaryName; - binary.StartInfo.UseShellExecute = false; - binary.Start(); - - binary.WaitForExit(); - - return; - } - - if (operation.Equals("build")) - { - string runtimeIdentifier = string.Empty; - - if (OperatingSystem.IsLinux()) - { - runtimeIdentifier = "linux-x64"; - } - - if (OperatingSystem.IsMacOS()) - { - runtimeIdentifier = "osx-x64"; - } - - if (OperatingSystem.IsWindows()) - { - runtimeIdentifier = "win-x64"; - } - - arguments = $""" - publish .otterkit/Artifacts/OtterkitExport.csproj -r {runtimeIdentifier} -c Release -o .otterkit/Build - """; - } - - using (Process dotnet = new()) - { - dotnet.StartInfo.FileName = "dotnet"; - dotnet.StartInfo.Arguments = arguments; - dotnet.StartInfo.UseShellExecute = false; - dotnet.StartInfo.RedirectStandardOutput = true; - dotnet.Start(); - - if (output) - { - Console.Write(dotnet.StandardOutput.ReadToEnd()); - } - - dotnet.WaitForExit(); - } - } - - private static void PrintTokens() - { - var colorToggle = true; - - foreach (var token in CompilerContext.SourceTokens) - { - if (colorToggle) - { - Console.ForegroundColor = ConsoleColor.Gray; - } - else - { - Console.ForegroundColor = ConsoleColor.DarkGray; - } - - colorToggle = !colorToggle; - - Console.WriteLine(token); - } - - Console.ResetColor(); - - if (!ErrorHandler.HasOccurred) ErrorHandler.SuccessfulParse(); - } - - private static void DisplayHelpMessage() - { - const string helpMessage = """ - - Otterkit COBOL Compiler - Copyright Otterkit Project 2023 - Licensed under Apache 2.0 - - Command line options: - -h --help : Displays this help message - - New command usage: - otterkit new - - New command options: - app : Create a new executable COBOL application - module : Create a new COBOL module library - - Build command usage: - otterkit build - - Build command options: - -e --entry : Specify the entry point for the project - -cl --columns : Specify the max column length (default is 80) - -p --parse : Use the "Parse Only" build mode - -r --run : Use the "Build & Run" build mode - --fixed : Use fixed source format - --free : Use free source format - - Notes: - --columns has no effect on free format - - """; - - Console.WriteLine(helpMessage); - } -} diff --git a/src/Otterkit.csproj b/src/Otterkit.csproj deleted file mode 100644 index 59c527c5..00000000 --- a/src/Otterkit.csproj +++ /dev/null @@ -1,55 +0,0 @@ - - - - Exe - net7.0 - enable - enable - true - true - true - - true - - - - true - true - otterkit - ./nupkg - Apache-2.0 - 1.0.80 - Copyright (c) Otterkit 2023 - Otterkit Authors - Otterkit Project - OtterkitIcon.png - README.md - Otterkit;Standard;COBOL;Compiler - https://github.com/otterkit - https://github.com/otterkit/otterkit - git - - Main package for the Otterkit COBOL compiler. This package installs the compiler as a dotnet global tool. - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Tools/GenerateExceptionIndex.cs b/src/Tools/GenerateExceptionIndex.cs deleted file mode 100644 index a58fd3d6..00000000 --- a/src/Tools/GenerateExceptionIndex.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System.Text; - -namespace Otterkit; - -public static partial class Tools -{ - private const string ExceptionIndexPath = "../Libraries/Otterkit.Runtime/src/Generated/ExceptionIndex.cs"; - - public static void GenerateExceptionIndex() - { - var builder = new StringBuilder(); - - builder.AppendLine("// This file is auto-generated by Otterkit, do not edit manually."); - builder.AppendLine("// Compiler Tool: src/Tools/GenerateExceptionIndex.cs"); - builder.AppendLine("namespace Otterkit.Runtime;\n"); - builder.AppendLine("public static partial class RuntimeHelpers"); - builder.AppendLine("{"); - builder.AppendLine(" // This method performs a case-insensitive lookup of an exception name."); - builder.AppendLine(" // It returns the index of the exception in the exception table."); - builder.AppendLine(" public static int FetchExceptionIndex(ReadOnlySpan name)"); - builder.AppendLine(" {"); - builder.AppendLine(" return name switch"); - builder.AppendLine(" {"); - - GenerateSwitchLookup( - builder, - "EC-ALL", - "EC-ARGUMENT", - "EC-ARGUMENT-FUNCTION", - "EC-ARGUMENT-IMP", - "EC-BOUND", - "EC-BOUND-FUNC-RET-VALUE", - "EC-BOUND-IMP", - "EC-BOUND-ODO", - "EC-BOUND-OVERFLOW", - "EC-BOUND-PTR", - "EC-BOUND-REF-MOD", - "EC-BOUND-SET", - "EC-BOUND-SUBSCRIPT", - "EC-BOUND-TABLE-LIMIT", - "EC-CONTINUE", - "EC-CONTINUE-IMP", - "EC-CONTINUE-LESS-THAN-ZERO", - "EC-DATA", - "EC-DATA-CONVERSION", - "EC-DATA-IMP", - "EC-DATA-INCOMPATIBLE", - "EC-DATA-NOT-FINITE", - "EC-DATA-OVERFLOW", - "EC-DATA-PTR-NULL", - "EC-EXTERNAL", - "EC-EXTERNAL-DATA-MISMATCH", - "EC-EXTERNAL-FILE-MISMATCH", - "EC-EXTERNAL-FORMAT-CONFLICT", - "EC-EXTERNAL-IMP", - "EC-FLOW", - "EC-FLOW-APPLY-COMMIT", - "EC-FLOW-COMMIT", - "EC-FLOW-GLOBAL-EXIT", - "EC-FLOW-GLOBAL-GOBACK", - "EC-FLOW-IMP", - "EC-FLOW-RELEASE", - "EC-FLOW-REPORT", - "EC-FLOW-RETURN", - "EC-FLOW-ROLLBACK", - "EC-FLOW-SEARCH", - "EC-FLOW-USE", - "EC-FUNCTION", - "EC-FUNCTION-ARG-OMITTED", - "EC-FUNCTION-IMP", - "EC-FUNCTION-NOT-FOUND", - "EC-FUNCTION-PTR-INVALID", - "EC-FUNCTION-PTR-NULL", - "EC-I-O", - "EC-I-O-AT-END", - "EC-I-O-EOP", - "EC-I-O-EOP-OVERFLOW", - "EC-I-O-FILE-SHARING", - "EC-I-O-IMP", - "EC-I-O-INVALID-KEY", - "EC-I-O-LINAGE", - "EC-I-O-LOGIC-ERROR", - "EC-I-O-PERMANENT-ERROR", - "EC-I-O-RECORD-CONTENT", - "EC-I-O-RECORD-OPERATION", - "EC-I-O-WARNING", - "EC-IMP", - "EC-IMP-suffix", - "EC-LOCALE", - "EC-LOCALE-IMP", - "EC-LOCALE-INCOMPATIBLE", - "EC-LOCALE-INVALID", - "EC-LOCALE-INVALID-PTR", - "EC-LOCALE-MISSING", - "EC-LOCALE-SIZE", - "EC-MCS", - "EC-MCS-ABNORMAL-TERMINATION", - "EC-MCS-IMP", - "EC-MCS-INVALID-TAG", - "EC-MCS-MESSAGE-LENGTH", - "EC-MCS-NO-REQUESTER", - "EC-MCS-NO-SERVER", - "EC-MCS-NORMAL-TERMINATION", - "EC-MCS-REQUESTOR-FAILED", - "EC-OO", - "EC-OO-ARG-OMITTED", - "EC-OO-CONFORMANCE", - "EC-OO-EXCEPTION", - "EC-OO-IMP", - "EC-OO-METHOD", - "EC-OO-NULL", - "EC-OO-RESOURCE", - "EC-OO-UNIVERSAL", - "EC-ORDER", - "EC-ORDER-IMP", - "EC-ORDER-NOT-SUPPORTED", - "EC-OVERFLOW", - "EC-OVERFLOW-IMP", - "EC-OVERFLOW-STRING", - "EC-OVERFLOW-UNSTRING", - "EC-PROGRAM", - "EC-PROGRAM-ARG-MISMATCH", - "EC-PROGRAM-ARG-OMITTED", - "EC-PROGRAM-CANCEL-ACTIVE", - "EC-PROGRAM-IMP", - "EC-PROGRAM-NOT-FOUND", - "EC-PROGRAM-PTR-NULL", - "EC-PROGRAM-RECURSIVE-CALL", - "EC-PROGRAM-RESOURCES", - "EC-RAISING", - "EC-RAISING-IMP", - "EC-RAISING-NOT-SPECIFIED", - "EC-RANGE", - "EC-RANGE-IMP", - "EC-RANGE-INDEX", - "EC-RANGE-INSPECT-SIZE", - "EC-RANGE-INVALID", - "EC-RANGE-PERFORM-VARYING", - "EC-RANGE-PTR", - "EC-RANGE-SEARCH-INDEX", - "EC-RANGE-SEARCH-NO-MATCH", - "EC-REPORT", - "EC-REPORT-ACTIVE", - "EC-REPORT-COLUMN-OVERLAP", - "EC-REPORT-FILE-MODE", - "EC-REPORT-IMP", - "EC-REPORT-INACTIVE", - "EC-REPORT-LINE-OVERLAP", - "EC-REPORT-NOT-TERMINATED", - "EC-REPORT-PAGE-LIMIT", - "EC-REPORT-PAGE-WIDTH", - "EC-REPORT-SUM-SIZE", - "EC-REPORT-VARYING", - "EC-SCREEN", - "EC-SCREEN-FIELD-OVERLAP", - "EC-SCREEN-IMP", - "EC-SCREEN-ITEM-TRUNCATED", - "EC-SCREEN-LINE-NUMBER", - "EC-SCREEN-STARTING-COLUMN", - "EC-SIZE", - "EC-SIZE-ADDRESS", - "EC-SIZE-EXPONENTIATION", - "EC-SIZE-IMP", - "EC-SIZE-OVERFLOW", - "EC-SIZE-TRUNCATION", - "EC-SIZE-UNDERFLOW", - "EC-SIZE-ZERO-DIVIDE", - "EC-SORT-MERGE", - "EC-SORT-MERGE-ACTIVE", - "EC-SORT-MERGE-FILE-OPEN", - "EC-SORT-MERGE-IMP", - "EC-SORT-MERGE-RELEASE", - "EC-SORT-MERGE-RETURN", - "EC-SORT-MERGE-SEQUENCE", - "EC-STORAGE", - "EC-STORAGE-IMP", - "EC-STORAGE-NOT-ALLOC", - "EC-STORAGE-NOT-AVAIL", - "EC-USER", - "EC-USER-suffix", - "EC-VALIDATE", - "EC-VALIDATE-CONTENT", - "EC-VALIDATE-FORMAT", - "EC-VALIDATE-IMP", - "EC-VALIDATE-RELATION", - "EC-VALIDATE-VARYING" - ); - - builder.AppendLine(" _ => -5"); - builder.AppendLine(" };"); - builder.AppendLine(" }"); - builder.AppendLine("}"); - - File.WriteAllText(ExceptionIndexPath, builder.ToString()); - } -} diff --git a/src/Tools/GenerateSwitchLookup.cs b/src/Tools/GenerateSwitchLookup.cs deleted file mode 100644 index 7f8a556d..00000000 --- a/src/Tools/GenerateSwitchLookup.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Text; - -namespace Otterkit; - -public static partial class Tools -{ - public static void GenerateSwitchLookup(StringBuilder builder, params string[] strings) - { - Span span = stackalloc byte[64]; - - span.Fill(0); - - for (int i = 0; i < strings.Length; i++) - { - ReadOnlySpan name = strings[i].ToUpperInvariant(); - - var length = Encoding.UTF8.GetBytes(name, span); - - builder.AppendLine($" // {name}"); - builder.Append(" ["); - - for (int j = 0; j < length; j++) - { - var _byte = span[j]; - - if (_byte == 0) break; - - if (_byte > 64 && _byte < 91) - { - builder.Append($"{_byte + 32} or {_byte},"); - continue; - } - - if (j == length - 1) - { - builder.Append($"{_byte}"); - break; - } - - builder.Append($"{_byte},"); - } - - builder.AppendLine($"] => {i},"); - - span.Fill(0); - } - } -} diff --git a/src/Tools/GenerateUnicodeTable.cs b/src/Tools/GenerateUnicodeTable.cs deleted file mode 100644 index ff22196d..00000000 --- a/src/Tools/GenerateUnicodeTable.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System.Globalization; -using System.Runtime.InteropServices; -using System.Text; -using Otterkit.Runtime; - -namespace Otterkit; - -[StructLayout(LayoutKind.Explicit)] -public unsafe struct u8Char -{ - [FieldOffset(0)] - public fixed byte Bytes[4]; - - [FieldOffset(0)] - public uint Codepoint; - - public static implicit operator u8Char(byte[] bytes) - { - var u8char = new u8Char(); - - if (bytes.Length is 1) - { - u8char.Bytes[0] = bytes[0]; - u8char.Bytes[1] = 0; - u8char.Bytes[2] = 0; - u8char.Bytes[3] = 0; - } - else if (bytes.Length is 2) - { - u8char.Bytes[0] = bytes[0]; - u8char.Bytes[1] = bytes[1]; - u8char.Bytes[2] = 0; - u8char.Bytes[3] = 0; - } - else if (bytes.Length is 3) - { - u8char.Bytes[0] = bytes[0]; - u8char.Bytes[1] = bytes[1]; - u8char.Bytes[2] = bytes[2]; - u8char.Bytes[3] = 0; - } - else if (bytes.Length is 4) - { - u8char.Bytes[0] = bytes[0]; - u8char.Bytes[1] = bytes[1]; - u8char.Bytes[2] = bytes[2]; - u8char.Bytes[3] = bytes[3]; - } - - return u8char; - } -} - -public static partial class Tools -{ - public static Dictionary FetchUnicodeData(string toolsPath) - { - Directory.SetCurrentDirectory(toolsPath); - - var lines = File.ReadAllText("UnicodeData.txt").Split("\n"); - - var casefoldLines = File.ReadAllText("CaseFolding.txt").Split("\n"); - - var unicodeData = new Dictionary(); - - for (uint i = 0x0000; i <= 0x10FFFF; i++) - { - unicodeData.Add(i, (i, i)); - } - - var casefoldData = File.CreateText("u8CaseFolding.h"); - - casefoldData.AutoFlush = true; - - Span bytes = stackalloc byte[4]; - Span casefoldBytes = stackalloc byte[4]; - - var differences = new HashSet(); - - foreach (var casefold in casefoldLines) - { - if (casefold.Length < 3) continue; - - if (casefold[0] is '#') continue; - - var data = casefold.Split(";"); - - if (data[1][1..] is "C" or "S") - { - var codepoint = uint.Parse(data[0], NumberStyles.HexNumber); - - if (codepoint > 0x10FFFF) continue; - - var casefolded = uint.Parse(data[2][1..], NumberStyles.HexNumber); - - if (casefolded > 0x10FFFF) continue; - - unicodeData[codepoint] = (unicodeData[codepoint].Uppercase, casefolded); - - Unicode.FromCodepoint(codepoint, bytes); - - Unicode.FromCodepoint(casefolded, casefoldBytes); - - differences.Add((int)casefolded - (int)codepoint); - - var bytesDiff = $"{casefoldBytes[0]-bytes[0]:X2} {casefoldBytes[1]-bytes[1]:X2} {casefoldBytes[2]-bytes[2]:X2} {casefoldBytes[3]-bytes[3]:X2}"; - - casefoldData.WriteLine($"// 0x{codepoint:X4}; {data[1][1..]}; 0x{casefolded:X4}; DIFF[{bytesDiff}] ;{data[3]}"); - } - else - { - var codepoint = uint.Parse(data[0], NumberStyles.HexNumber); - - unicodeData[codepoint] = (unicodeData[codepoint].Uppercase, codepoint); - } - } - - Console.WriteLine($"Differences: {differences.Count}"); - - var uppercaseData = File.CreateText("UpperCase.txt"); - - uppercaseData.AutoFlush = true; - - Span uppercase = stackalloc byte[4]; - - foreach (var line in lines) - { - var data = line.Split(";"); - - if (data.Length < 14) continue; - - var codepoint = uint.Parse(data[0], NumberStyles.HexNumber); - - if (codepoint > 0x10FFFF) continue; - - if (data[12] is not "") - { - Unicode.FromCodepoint(codepoint, bytes); - - Unicode.FromCodepoint(uint.Parse(data[12], NumberStyles.HexNumber), uppercase); - - uppercaseData.WriteLine($"{bytes[0]:X2} {bytes[1]:X2} {bytes[2]:X2} {bytes[3]:X2}; U; {uppercase[0]:X2} {uppercase[1]:X2} {uppercase[2]:X2} {uppercase[3]:X2}; # {data[1]}"); - } - - bytes.Clear(); - uppercase.Clear(); - - // unicodeData[codepoint] = (uppercase, unicodeData[codepoint].Casefolded); - } - - return unicodeData; - } - - public static Dictionary FetchCaseFoldData(string toolsPath) - { - Directory.SetCurrentDirectory(toolsPath); - - var casefoldLines = File.ReadAllText("CaseFolding.txt").Split("\n"); - - var casefoldData = new Dictionary(); - - foreach (var casefold in casefoldLines) - { - if (casefold.Length < 3) continue; - - if (casefold[0] is '#') continue; - - var data = casefold.Split(";"); - - if (data[1][1..] is "C" or "S") - { - var codepoint = uint.Parse(data[0], NumberStyles.HexNumber); - - var casefolded = uint.Parse(data[2][1..], NumberStyles.HexNumber); - - casefoldData[codepoint] = casefolded; - } - } - - return casefoldData; - } - - public static void GenerateBasicMultilingualPlane(string toolsPath) - { - var unicodeData = FetchUnicodeData(toolsPath); - - StringBuilder builder = new(); - - builder.AppendLine("// Tool: src/Tools/GenerateUnicodeTable.cs"); - builder.AppendLine("// This file is generated by Otterkit, do not edit manually!"); - builder.AppendLine("// Generated at: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); - builder.AppendLine("// Unicode version: 15.0.0"); - builder.AppendLine(); - - builder.AppendLine("#include \"u8unicode.h\"\n"); - - builder.AppendLine("// Unicode Codepoint Database (U+0000 ... U+FFFF)"); - builder.AppendLine("const UnicodeTableEntry u8Unicode[0x10000] ="); - builder.AppendLine("{"); - - for (uint index = 0x0000; index <= 0xFFFF; index++) - { - var line = $"{{ 0x{index:X4}, 0x{(unicodeData[index].Uppercase):X4}, 0x{(unicodeData[index].Casefolded):X4} }}"; - - AppendCodepoint(builder, line, index, index == 0xFFFF); - } - - builder.AppendLine("};"); - - if (!Directory.Exists("Unicode")) - { - Directory.CreateDirectory("Unicode"); - } - - File.WriteAllText("Unicode/u8unicode.c", builder.ToString()); - } - - private static void AppendCodepoint(StringBuilder builder, string codepoint, uint index, bool isEnd = false) - { - if (isEnd) - { - builder.AppendLine($" {codepoint} // [{index}]"); - } - else - { - builder.AppendLine($" {codepoint}, // [{index}]"); - } - } -} diff --git a/src/Tools/TestCaseFolding.cs b/src/Tools/TestCaseFolding.cs deleted file mode 100644 index 1957231b..00000000 --- a/src/Tools/TestCaseFolding.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Otterkit.Runtime; -using Otterkit.Native; - -namespace Otterkit; - -public static unsafe partial class Tools -{ - public static void TestCaseFolding(string toolsPath) - { - var data = Tools.FetchCaseFoldData(toolsPath); - - var _string = stackalloc byte[5] { 0x00, 0x00, 0x00, 0x00, 0x00 }; - - var _string2 = stackalloc byte[5] { 0x00, 0x00, 0x00, 0x00, 0x00 }; - - foreach (var casefold in data) - { - Unicode.FromCodepoint(casefold.Key, new(_string, 4)); - - Unicode.FromCodepoint(casefold.Value, new(_string2, 4)); - - var result = Unicode.Casefold(_string, 4); - - Console.WriteLine($"Testing: {casefold.Key:X4} -> {casefold.Value:X4}"); - - if (result[0] != _string2[0] || result[1] != _string2[1] || result[2] != _string2[2] || result[3] != _string2[3]) - { - Console.WriteLine($"Casefold failed: {casefold.Key:X4} -> {casefold.Value:X4}"); - Console.WriteLine($"Input: {_string[0]:X2} {_string[1]:X2} {_string[2]:X2} {_string[3]:X2}"); - Console.WriteLine($"Expected: {_string2[0]:X2} {_string2[1]:X2} {_string2[2]:X2} {_string2[3]:X2}"); - Console.WriteLine($"Got: {result[0]:X2} {result[1]:X2} {result[2]:X2} {result[3]:X2}"); - Console.WriteLine(); - - Allocator.Dealloc(result); - - return; - } - - Allocator.Dealloc(result); - - _string[0] = 0x00; - _string[1] = 0x00; - _string[2] = 0x00; - _string[3] = 0x00; - - _string2[0] = 0x00; - _string2[1] = 0x00; - _string2[2] = 0x00; - _string2[3] = 0x00; - } - - Console.WriteLine("Casefold test passed!"); - } -} diff --git a/src/parsinginfo.json b/src/parsinginfo.json deleted file mode 100644 index 16072fcf..00000000 --- a/src/parsinginfo.json +++ /dev/null @@ -1,662 +0,0 @@ -{ - "reservedKeywords": [ - "ACCEPT", - "ACCESS", - "ACTIVE-CLASS", - "ADD", - "ADDRESS", - "ADVANCING", - "AFTER", - "ALIGNED", - "ALLOCATE", - "ALPHABET", - "ALPHABETIC", - "ALPHABETIC-LOWER", - "ALPHABETIC-UPPER", - "ALPHANUMERIC", - "ALPHANUMERIC-EDITED", - "ALSO", - "ALTERNATE", - "AND", - "ANY", - "ANYCASE", - "ARE", - "AREA", - "AREAS", - "AS", - "ASCENDING", - "ASSIGN", - "AT", - "B-AND", - "B-NOT", - "B-OR", - "B-SHIFT", - "B-SHIFT-LC", - "B-SHIFT-RC", - "BY", - "B-XOR", - "BASED", - "BEFORE", - "BINARY", - "BINARY-CHAR", - "BINARY-DOUBLE", - "BINARY-LONG", - "BINARY-SHORT", - "BIT", - "BLANK", - "BLOCK", - "BOOLEAN", - "BOTTOM", - "CALL", - "CANCEL", - "CF", - "CH", - "CHARACTER", - "CHARACTERS", - "CLASS", - "CLASS-ID", - "CLOSE", - "CODE", - "CODE-SET", - "COL", - "COLLATING", - "COLS", - "COLUMN", - "COLUMNS", - "COMMA", - "COMMIT", - "COMMON", - "COMP", - "COMPUTATIONAL", - "COMPUTE", - "CONFIGURATION", - "CONSTANT", - "CONTAINS", - "CONTENT", - "CONTINUE", - "CONTROL", - "CONTROLS", - "CONVERTING", - "COPY", - "CORR", - "CORRESPONDING", - "COUNT", - "CRT", - "CURRENCY", - "CURSOR", - "DATA", - "DATA-POINTER", - "DATE", - "DAY", - "DAY-OF-WEEK", - "DE", - "DECIMAL-POINT", - "DECLARATIVES", - "DEFAULT", - "DELETE", - "DELIMITED", - "DELIMITER", - "DEPENDING", - "DESCENDING", - "DESTINATION", - "DETAIL", - "DISPLAY", - "DIVIDE", - "DIVISION", - "DOWN", - "DUPLICATES", - "DYNAMIC", - "EC", - "EDITING", - "ELSE", - "EMI", - "END", - "END-ACCEPT", - "END-ADD", - "END-CALL", - "END-COMPUTE", - "END-DELETE", - "END-DISPLAY", - "END-DIVIDE", - "END-EVALUATE", - "END-IF", - "END-MULTIPLY", - "END-OF-PAGE", - "END-PERFORM", - "END-RECEIVE", - "END-READ", - "END-RETURN", - "END-REWRITE", - "END-SEARCH", - "END-SEND", - "END-START", - "END-STRING", - "END-SUBTRACT", - "END-UNSTRING", - "END-WRITE", - "ENVIRONMENT", - "EOL", - "EOP", - "EQUAL", - "ERROR", - "EVALUATE", - "EXCEPTION", - "EXCEPTION-OBJECT", - "EXCLUSIVE-OR", - "EXIT", - "EXTEND", - "EXTERNAL", - "FACTORY", - "FARTHEST-FROM-ZERO", - "FALSE", - "FD", - "FILE", - "FILE-CONTROL", - "FILLER", - "FINAL", - "FINALLY", - "FIRST", - "FLOAT-BINARY-32", - "FLOAT-BINARY-64", - "FLOAT-BINARY-128", - "FLOAT-DECIMAL-16", - "FLOAT-DECIMAL-34", - "FLOAT-EXTENDED", - "FLOAT-INFINITY", - "FLOAT-LONG", - "FLOAT-NOT-A-NUMBER", - "FLOAT-NOT-A-NUMBER-QUIET", - "FLOAT-NOT-A-NUMBER-SIGNALING", - "FOOTING", - "FOR", - "FORMAT", - "FREE", - "FROM", - "FUNCTION", - "FUNCTION-ID", - "FUNCTION-POINTER", - "GENERATE", - "GET", - "GIVING", - "GLOBAL", - "GO", - "GOBACK", - "GREATER", - "GROUP", - "GROUP-USAGE", - "HEADING", - "I-O", - "I-O-CONTROL", - "IDENTIFICATION", - "IF", - "IN", - "IN-ARITHMETIC-RANGE", - "INDEX", - "INDEXED", - "INDICATE", - "INHERITS", - "INITIAL", - "INITIALIZE", - "INITIALIZED", - "INITIATE", - "INPUT", - "INPUT-OUTPUT", - "INSPECT", - "INTERFACE", - "INTERFACE-ID", - "INTO", - "INVALID", - "INVOKE", - "IS", - "JUST", - "JUSTIFIED", - "KEY", - "LAST", - "LEADING", - "LEFT", - "LENGTH", - "LESS", - "LIMIT", - "LIMITS", - "LINAGE", - "LINAGE-COUNTER", - "LINE", - "LINE-COUNTER", - "LINES", - "LINKAGE", - "LOCAL-STORAGE", - "LOCALE", - "LOCATION", - "LOCK", - "MERGE", - "MESSAGE-TAG", - "METHOD", - "METHOD-ID", - "MINUS", - "MODE", - "MOVE", - "MULTIPLY", - "NATIONAL", - "NATIONAL-EDITED", - "NATIVE", - "NEAREST-TO-ZERO", - "NESTED", - "NEXT", - "NO", - "NOT", - "NULL", - "NUMBER", - "NUMERIC", - "NUMERIC-EDITED", - "OBJECT", - "OBJECT-COMPUTER", - "OBJECT-REFERENCE", - "OCCURS", - "OF", - "OFF", - "OMITTED", - "ON", - "OPEN", - "OPTIONAL", - "OPTIONS", - "OR", - "ORDER", - "ORGANIZATION", - "OTHER", - "OUTPUT", - "OVERFLOW", - "OVERRIDE", - "PACKED-DECIMAL", - "PAGE", - "PAGE-COUNTER", - "PERFORM", - "PF", - "PH", - "PIC", - "PICTURE", - "PLUS", - "POINTER", - "POSITIVE", - "PRESENT", - "PRINTING", - "PROCEDURE", - "PROGRAM", - "PROGRAM-ID", - "PROGRAM-POINTER", - "PROPERTY", - "PROTOTYPE", - "RAISE", - "RAISING", - "RANDOM", - "RD", - "READ", - "RECEIVE", - "RECORD", - "RECORDS", - "REDEFINES", - "REEL", - "REF", - "REFERENCE", - "RELATIVE", - "RELEASE", - "REMAINDER", - "REMOVAL", - "RENAMES", - "REPLACE", - "REPLACING", - "REPORT", - "REPORTING", - "REPORTS", - "REPOSITORY", - "RESERVE", - "RESET", - "RESUME", - "RETRY", - "RETURN", - "RETURNING", - "REWIND", - "REWRITE", - "RF", - "RH", - "RIGHT", - "ROLLBACK", - "ROUNDED", - "RUN", - "SAME", - "SCREEN", - "SD", - "SEARCH", - "SECONDS", - "SECTION", - "SELECT", - "SEND", - "SELF", - "SENTENCE", - "SEPARATE", - "SEQUENCE", - "SEQUENTIAL", - "SET", - "SHARING", - "SIGN", - "SIZE", - "SORT", - "SORT-MERGE", - "SOURCE", - "SOURCE-COMPUTER", - "SOURCES", - "SPECIAL-NAMES", - "STANDARD", - "STANDARD-1", - "STANDARD-2", - "START", - "STATUS", - "STOP", - "STRING", - "SUBTRACT", - "SUM", - "SUPER", - "SUPPRESS", - "SYMBOLIC", - "SYNC", - "SYNCHRONIZED", - "SYSTEM-DEFAULT", - "TABLE", - "TALLYING", - "TERMINATE", - "TEST", - "THAN", - "THEN", - "THROUGH", - "THRU", - "TIME", - "TIMES", - "TO", - "TOP", - "TRAILING", - "TRUE", - "TYPE", - "TYPEDEF", - "UNIT", - "UNIVERSAL", - "UNLOCK", - "UNSTRING", - "UNTIL", - "UP", - "UPON", - "USAGE", - "USE", - "USE", - "USER-DEFAULT", - "USING", - "VAL-STATUS", - "VALID", - "VALIDATE", - "VALIDATE-STATUS", - "VALUE", - "VALUES", - "VARYING", - "WHEN", - "WITH", - "WORKING-STORAGE", - "WRITE", - "XOR" - ], - "clauses": [ - "ALIGNED", - "ANY", - "LENGTH", - "AUTO", - "BACKGROUND-COLOR", - "BASED", - "BELL", - "BLANK", - "WHEN", - "ZERO", - "BLINK", - "BLOCK", - "CONTAINS", - "CLASS", - "CODE", - "CODE-SET", - "COLUMN", - "CONSTANT", - "CONTROL", - "DEFAULT", - "DESTINATION", - "DYNAMIC", - "ERASE", - "EXTERNAL", - "FOREGROUND-COLOR", - "FORMAT", - "FROM", - "FULL", - "GLOBAL", - "GROUP", - "INDICATE", - "GROUP-USAGE", - "HIGHLIGHT", - "INVALID", - "JUSTIFIED", - "LINAGE", - "LINE", - "LOWLIGHT", - "NEXT", - "OCCURS", - "PAGE", - "PICTURE", - "PIC", - "IS", - "PRESENT", - "PROPERTY", - "RECORD", - "REDEFINES", - "RENAMES", - "REPORT", - "REQUIRED", - "REVERSE-VIDEO", - "SAME", - "AS", - "SECURE", - "SELECT", - "SIGN", - "SOURCE", - "SUM", - "SYNCHRONIZED", - "TO", - "TYPE", - "TYPEDEF", - "UNDERLINE", - "USAGE", - "USING", - "VALIDATE-STATUS", - "VALUE", - "VARYING" - ], - "statements": [ - "ACCEPT", - "ADD", - "ALLOCATE", - "CALL", - "CANCEL", - "CLOSE", - "COMMIT", - "COMPUTE", - "CONTINUE", - "DELETE", - "DISPLAY", - "DIVIDE", - "EVALUATE", - "EXIT", - "FREE", - "GENERATE", - "GOBACK", - "GO", - "TO", - "IF", - "INITIALIZE", - "INITIATE", - "INSPECT", - "INVOKE", - "MERGE", - "MOVE", - "MULTIPLY", - "OPEN", - "PERFORM", - "RAISE", - "READ", - "RECEIVE", - "RELEASE", - "RESUME", - "RETURN", - "REWRITE", - "ROLLBACK", - "SEARCH", - "SEND", - "SET", - "SORT", - "START", - "STOP", - "RUN", - "STRING", - "SUBTRACT", - "SUPPRESS", - "TERMINATE", - "UNLOCK", - "UNSTRING", - "VALIDATE", - "WRITE" - ], - "figurativeLiteral": [ - "ZERO", - "ZEROES", - "ZEROS", - "SPACE", - "SPACES", - "HIGH-VALUE", - "HIGH-VALUES", - "LOW-VALUE", - "LOW-VALUES", - "QUOTE", - "QUOTES", - "ALL" - ], - "intrinsicFunctions": [ - "ABS", - "ACOS", - "ANNUITY", - "ASIN", - "ATAN", - "BASECONVERT", - "BOOLEAN-OF-INTEGER", - "BYTE-LENGTH", - "CHAR", - "CHAR-NATIONAL", - "COMBINED-DATETIME", - "CONCAT", - "CONVERT", - "COS", - "CURRENT-DATE", - "DATE-OF-INTEGER", - "DATE-TO-YYYYMMDD", - "DAY-OF-INTEGER", - "DAY-TO-YYYYDDD", - "DISPLAY-OF", - "E", - "EXCEPTION-FILE", - "EXCEPTION-FILE-N", - "EXCEPTION-LOCATION", - "EXCEPTION-LOCATION-N", - "EXCEPTION-STATEMENT", - "EXCEPTION-STATUS", - "EXP", - "EXP10", - "FACTORIAL", - "FIND-STRING", - "FORMATTED-CURRENT-DATE", - "FORMATTED-DATE", - "FORMATTED-DATETIME", - "FORMATTED-TIME", - "FRACTION-PART", - "HIGHEST-ALGEBRAIC", - "INTEGER", - "INTEGER-OF-BOOLEAN", - "INTEGER-OF-DATE", - "INTEGER-OF-DAY", - "INTEGER-OF-FORMATTED-DATE", - "INTEGER-PART", - "LENGTH", - "LOCALE-COMPARE", - "LOCALE-DATE", - "LOCALE-TIME", - "LOCALE-TIME-FROM-SECONDS", - "LOG", - "LOG10", - "LOWER-CASE", - "LOWEST-ALGEBRAIC", - "MAX", - "MEAN", - "MEDIAN", - "MIDRANGE", - "MIN", - "MOD", - "MODULE-NAME", - "NATIONAL-OF", - "NUMVAL", - "NUMVAL-C", - "NUMVAL-F", - "ORD", - "ORD-MAX", - "ORD-MIN", - "PI", - "PRESENT-VALUE", - "RANDOM", - "RANGE", - "REM", - "REVERSE", - "SECONDS-FROM-FORMATTED-TIME", - "SECONDS-PAST-MIDNIGHT", - "SIGN", - "SIN", - "SMALLEST-ALGEBRAIC", - "SQRT", - "STANDARD-COMPARE", - "STANDARD-DEVIATION", - "SUBSTITUTE", - "SUM", - "TAN", - "TEST-DATE-YYYYMMDD", - "TEST-DAY-YYYYDDD", - "TEST-FORMATTED-DATETIME", - "TEST-NUMVAL", - "TEST-NUMVAL-C", - "TEST-NUMVAL-F", - "TRIM", - "UPPER-CASE", - "VARIANCE", - "WHEN-COMPILED", - "YEAR-TO-YYYY" - ], - "symbols": [ - "+", - "-", - "**", - "*", - "=", - "/", - "$", - ",", - ";", - "::", - ".", - "(", - ")", - ">>", - "<>", - ">=", - "<=", - ">", - "<", - "&", - "_" - ] -} diff --git a/src/schema.json b/src/schema.json deleted file mode 100644 index 72ede729..00000000 --- a/src/schema.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "properties": { - "author": { - "description": "The author of this COBOL project.", - "type": "string" - }, - "description": { - "type": "string", - "description": "A short description of this COBOL project's purpose." - }, - "tags": { - "description": "Zero or more tags that describe this COBOL project's purpose and functionality.", - "type": "array", - "items": { - "type": "string", - "minLength": 1 - } - }, - "name": { - "description": "The name of this COBOL project.", - "type": "string", - "minLength": 1 - }, - "id": { - "description": "A unique id for this COBOL project, in a Company.ProjectName format.", - "type": "string", - "minLength": 1 - }, - "metadata": { - "description": "Project information required by the Otterkit COBOL compiler to be able to compile correctly.", - "type": "object", - "required": ["entryPoint", "type"], - "properties": { - "entryPoint": { - "description": "This COBOL project's entry point, in a file#program-id format (example main.cob#main).", - "type": "string" - }, - "type": { - "description": "The type of COBOL project: application or module.", - "enum": ["application", "module"] - } - } - }, - "license": { - "description": "An URL for a document containing the license for this COBOL project.", - "type": "string" - }, - "thirdPartyLicenses": { - "description": "An URL for a document containing the third-party licenses used by this COBOL project.", - "type": "string" - } - }, - "required": [ - "author", - "description", - "name", - "id", - "metadata", - "license" - ], - "title": "JSON schema Otterkit COBOL compiler configuration (OtterkitConfig.json).", - "type": "object" - } \ No newline at end of file