@mpeggroup/mpeg-sdl-parser 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +337 -0
- package/bun.lock +65 -0
- package/dist/index.js +11829 -0
- package/grammar/sdl.ebnf.grammar +399 -0
- package/grammar/sdl.lezer.grammar +629 -0
- package/index.ts +83 -0
- package/package.json +61 -0
- package/src/analyser/checks/check-array-definition.ts +90 -0
- package/src/analyser/checks/check-array-element-access.ts +31 -0
- package/src/analyser/checks/check-class-declaration.ts +417 -0
- package/src/analyser/checks/check-computed-array-definition.ts +44 -0
- package/src/analyser/checks/check-computed-elementary-type-definition.ts +45 -0
- package/src/analyser/checks/check-elementary-type-definition.ts +167 -0
- package/src/analyser/checks/check-expression-binary.ts +242 -0
- package/src/analyser/checks/check-expression-lengthof.ts +34 -0
- package/src/analyser/checks/check-expression-unary.ts +166 -0
- package/src/analyser/checks/check-identifier.ts +71 -0
- package/src/analyser/checks/check-if-statement.ts +164 -0
- package/src/analyser/checks/check-map-declaration.ts +180 -0
- package/src/analyser/checks/check-map-definition.ts +118 -0
- package/src/analyser/checks/check-number-literal-float.ts +28 -0
- package/src/analyser/checks/check-parameter-list.ts +42 -0
- package/src/analyser/checks/check-specification.ts +53 -0
- package/src/analyser/checks/check-switch-statement.ts +206 -0
- package/src/analyser/checks/check.ts +20 -0
- package/src/analyser/create-sdl-analyser.ts +85 -0
- package/src/analyser/node-handler/abstract-analysis-node-handler.ts +626 -0
- package/src/analyser/node-handler/build-symbol-table-node-handler.ts +649 -0
- package/src/analyser/node-handler/specific-check-node-handler.ts +46 -0
- package/src/analyser/node-handler/validate-scope-node-handler.ts +290 -0
- package/src/analyser/node-handler/validate-type-node-handler.ts +497 -0
- package/src/analyser/sdl-analyser.ts +119 -0
- package/src/analyser/symbol-table.ts +388 -0
- package/src/analyser/util/symbol-table-utils.ts +458 -0
- package/src/analyser/util/type-utils.ts +238 -0
- package/src/ast/build/consume/consume-abstract-node.ts +199 -0
- package/src/ast/build/consume/consume-ast-node.ts +400 -0
- package/src/ast/build/consume/consume-primitive.ts +59 -0
- package/src/ast/build/consume/consume-trivia.ts +96 -0
- package/src/ast/build/consume/consume-white-space-and-missing-errors.ts +27 -0
- package/src/ast/build/node/build-aggregate-output-value.ts +57 -0
- package/src/ast/build/node/build-aligned-modifier.ts +99 -0
- package/src/ast/build/node/build-array-definition.ts +131 -0
- package/src/ast/build/node/build-array-element-access.ts +45 -0
- package/src/ast/build/node/build-base64-string-literal.ts +41 -0
- package/src/ast/build/node/build-binary-expression.ts +113 -0
- package/src/ast/build/node/build-binary-literal.ts +37 -0
- package/src/ast/build/node/build-bit-modifier.ts +86 -0
- package/src/ast/build/node/build-case-clause.ts +101 -0
- package/src/ast/build/node/build-class-declaration.ts +124 -0
- package/src/ast/build/node/build-class-definition.ts +56 -0
- package/src/ast/build/node/build-class-id-range.ts +32 -0
- package/src/ast/build/node/build-class-id.ts +19 -0
- package/src/ast/build/node/build-class-member-access.ts +27 -0
- package/src/ast/build/node/build-compound-statement.ts +33 -0
- package/src/ast/build/node/build-computed-array-definition.ts +53 -0
- package/src/ast/build/node/build-computed-elementary-type-definition.ts +100 -0
- package/src/ast/build/node/build-decimal-literal.ts +15 -0
- package/src/ast/build/node/build-default-clause.ts +76 -0
- package/src/ast/build/node/build-do-statement.ts +71 -0
- package/src/ast/build/node/build-elementary-type-definition.ts +164 -0
- package/src/ast/build/node/build-elementary-type-output-value.ts +25 -0
- package/src/ast/build/node/build-elementary-type.ts +36 -0
- package/src/ast/build/node/build-expandable-modifier.ts +68 -0
- package/src/ast/build/node/build-explicit-array-dimension.ts +37 -0
- package/src/ast/build/node/build-expression-statement.ts +31 -0
- package/src/ast/build/node/build-extended-class-id-range.ts +27 -0
- package/src/ast/build/node/build-extends-modifier.ts +41 -0
- package/src/ast/build/node/build-floating-point-literal.ts +15 -0
- package/src/ast/build/node/build-for-statement.ts +117 -0
- package/src/ast/build/node/build-hexadecimal-literal.ts +38 -0
- package/src/ast/build/node/build-identifier.ts +8 -0
- package/src/ast/build/node/build-if-statement.ts +82 -0
- package/src/ast/build/node/build-implicit-array-dimension.ts +78 -0
- package/src/ast/build/node/build-integer-literal.ts +15 -0
- package/src/ast/build/node/build-length-attribute.ts +48 -0
- package/src/ast/build/node/build-lengthof-expression.ts +45 -0
- package/src/ast/build/node/build-map-declaration.ts +110 -0
- package/src/ast/build/node/build-map-definition.ts +103 -0
- package/src/ast/build/node/build-map-entry.ts +33 -0
- package/src/ast/build/node/build-missing-error.ts +10 -0
- package/src/ast/build/node/build-multiple-character-literal.ts +65 -0
- package/src/ast/build/node/build-parameter-list.ts +50 -0
- package/src/ast/build/node/build-parameter-value-list.ts +54 -0
- package/src/ast/build/node/build-parameter.ts +47 -0
- package/src/ast/build/node/build-partial-array-dimension.ts +55 -0
- package/src/ast/build/node/build-specification.ts +24 -0
- package/src/ast/build/node/build-string-definition.ts +106 -0
- package/src/ast/build/node/build-switch-statement.ts +84 -0
- package/src/ast/build/node/build-token.ts +26 -0
- package/src/ast/build/node/build-unary-expression.ts +109 -0
- package/src/ast/build/node/build-unexpected-error.ts +14 -0
- package/src/ast/build/node/build-utf-string-literal.ts +110 -0
- package/src/ast/build/node/build-while-statement.ts +55 -0
- package/src/ast/build/util/array-dimension-kind-by-token-type-id-map.ts +167 -0
- package/src/ast/build/util/binary-operator-kind-by-token-type-id-map.ts +152 -0
- package/src/ast/build/util/build-context.ts +36 -0
- package/src/ast/build/util/class-id-kind-by-token-type-id-map.ts +160 -0
- package/src/ast/build/util/expression-kind-by-token-type-id-map.ts +168 -0
- package/src/ast/build/util/fetch-node.ts +433 -0
- package/src/ast/build/util/node-kind-by-token-type-id-map.ts +202 -0
- package/src/ast/build/util/statement-kind-by-token-type-id-map.ts +210 -0
- package/src/ast/build/util/string-literal-kind-by-token-type-id-map.ts +162 -0
- package/src/ast/build/util/token-kind-by-token-type-id-map.ts +337 -0
- package/src/ast/build-ast.ts +114 -0
- package/src/ast/node/abstract-array-definition.ts +17 -0
- package/src/ast/node/abstract-array-dimension.ts +20 -0
- package/src/ast/node/abstract-class-id.ts +13 -0
- package/src/ast/node/abstract-composite-node.ts +58 -0
- package/src/ast/node/abstract-elementary-type-definition.ts +29 -0
- package/src/ast/node/abstract-expression.ts +13 -0
- package/src/ast/node/abstract-leaf-node.ts +10 -0
- package/src/ast/node/abstract-node.ts +16 -0
- package/src/ast/node/abstract-statement.ts +13 -0
- package/src/ast/node/aggregate-output-value.ts +28 -0
- package/src/ast/node/aligned-modifier.ts +21 -0
- package/src/ast/node/array-definition.ts +44 -0
- package/src/ast/node/array-element-access.ts +24 -0
- package/src/ast/node/binary-expression.ts +28 -0
- package/src/ast/node/bit-modifier.ts +24 -0
- package/src/ast/node/case-clause.ts +30 -0
- package/src/ast/node/class-declaration.ts +39 -0
- package/src/ast/node/class-definition.ts +23 -0
- package/src/ast/node/class-id-range.ts +17 -0
- package/src/ast/node/class-id.ts +14 -0
- package/src/ast/node/class-member-access.ts +19 -0
- package/src/ast/node/compound-statement.ts +19 -0
- package/src/ast/node/computed-array-definition.ts +26 -0
- package/src/ast/node/computed-elementary-type-definition.ts +34 -0
- package/src/ast/node/default-clause.ts +26 -0
- package/src/ast/node/do-statement.ts +28 -0
- package/src/ast/node/elementary-type-definition.ts +49 -0
- package/src/ast/node/elementary-type-output-value.ts +19 -0
- package/src/ast/node/elementary-type.ts +18 -0
- package/src/ast/node/enum/array-dimension-kind.ts +11 -0
- package/src/ast/node/enum/binary-operator-kind.ts +41 -0
- package/src/ast/node/enum/class-id-kind.ts +12 -0
- package/src/ast/node/enum/elementary-type-kind.ts +13 -0
- package/src/ast/node/enum/expression-kind.ts +11 -0
- package/src/ast/node/enum/node-kind.ts +57 -0
- package/src/ast/node/enum/number-literal-kind.ts +17 -0
- package/src/ast/node/enum/statement-kind.ts +37 -0
- package/src/ast/node/enum/string-literal-kind.ts +13 -0
- package/src/ast/node/enum/string-variable-kind.ts +25 -0
- package/src/ast/node/enum/token-kind.ts +87 -0
- package/src/ast/node/expandable-modifier.ts +21 -0
- package/src/ast/node/explicit-array-dimension.ts +26 -0
- package/src/ast/node/expression-statement.ts +23 -0
- package/src/ast/node/extended-class-id-range.ts +20 -0
- package/src/ast/node/extends-modifier.ts +21 -0
- package/src/ast/node/for-statement.ts +29 -0
- package/src/ast/node/identifier.ts +12 -0
- package/src/ast/node/if-statement.ts +28 -0
- package/src/ast/node/implicit-array-dimension.ts +34 -0
- package/src/ast/node/length-attribute.ts +24 -0
- package/src/ast/node/length-of-expression.ts +21 -0
- package/src/ast/node/map-declaration.ts +34 -0
- package/src/ast/node/map-definition.ts +27 -0
- package/src/ast/node/map-entry.ts +18 -0
- package/src/ast/node/missing-error.ts +9 -0
- package/src/ast/node/number-literal.ts +18 -0
- package/src/ast/node/parameter-list.ts +25 -0
- package/src/ast/node/parameter-value-list.ts +29 -0
- package/src/ast/node/parameter.ts +20 -0
- package/src/ast/node/partial-array-dimension.ts +28 -0
- package/src/ast/node/specification.ts +21 -0
- package/src/ast/node/string-definition.ts +28 -0
- package/src/ast/node/string-literal.ts +21 -0
- package/src/ast/node/switch-statement.ts +32 -0
- package/src/ast/node/token.ts +20 -0
- package/src/ast/node/trivia.ts +13 -0
- package/src/ast/node/unary-expression.ts +31 -0
- package/src/ast/node/unexpected-error.ts +12 -0
- package/src/ast/node/while-statement.ts +26 -0
- package/src/ast/util/types.ts +138 -0
- package/src/ast/visitor/node-handler.ts +15 -0
- package/src/ast/visitor/node-visitor.ts +13 -0
- package/src/ast/visitor/traversing-visitor.ts +69 -0
- package/src/completion/completion-rules.ts +447 -0
- package/src/completion/get-potential-syntactic-tokens.ts +54 -0
- package/src/completion/get-potential-token-type-ids.ts +116 -0
- package/src/completion/hierarchical-map.ts +43 -0
- package/src/completion/rules/abstract-types.ts +174 -0
- package/src/completion/rules/aggregate-output-value-rules.ts +48 -0
- package/src/completion/rules/aligned-modifier-rules.ts +45 -0
- package/src/completion/rules/array-definition-rules.ts +87 -0
- package/src/completion/rules/array-element-access-rules.ts +22 -0
- package/src/completion/rules/assignment-expression-rules.ts +19 -0
- package/src/completion/rules/binary-expression-rules.ts +23 -0
- package/src/completion/rules/bit-modifier-rules.ts +25 -0
- package/src/completion/rules/case-clause-rules.ts +39 -0
- package/src/completion/rules/class-declaration-rules.ts +81 -0
- package/src/completion/rules/class-definition-rules.ts +28 -0
- package/src/completion/rules/class-id-range-rules.ts +17 -0
- package/src/completion/rules/class-id-rules.ts +9 -0
- package/src/completion/rules/class-member-access-rules.ts +7 -0
- package/src/completion/rules/compound-statement-rules.ts +25 -0
- package/src/completion/rules/computed-array-definition-rules.ts +25 -0
- package/src/completion/rules/computed-elementary-type-rules.ts +44 -0
- package/src/completion/rules/default-clause-rules.ts +23 -0
- package/src/completion/rules/do-statement-rules.ts +38 -0
- package/src/completion/rules/elementary-type-definition-rules.ts +62 -0
- package/src/completion/rules/elementary-type-output-value-rules.ts +13 -0
- package/src/completion/rules/elementary-type-rules.ts +18 -0
- package/src/completion/rules/expandable-modifier-rules.ts +21 -0
- package/src/completion/rules/explicit-array-dimension-rules.ts +22 -0
- package/src/completion/rules/expression-statement-rules.ts +22 -0
- package/src/completion/rules/extended-class-id-range-rules.ts +17 -0
- package/src/completion/rules/extends-modifier-rules.ts +17 -0
- package/src/completion/rules/for-statement-rules.ts +51 -0
- package/src/completion/rules/if-statement-rules.ts +42 -0
- package/src/completion/rules/implicit-array-dimension-rules.ts +21 -0
- package/src/completion/rules/length-attribute-rules.ts +19 -0
- package/src/completion/rules/lengthof-expression-rules.ts +23 -0
- package/src/completion/rules/map-declaration-rules.ts +45 -0
- package/src/completion/rules/map-definition-rules.ts +46 -0
- package/src/completion/rules/map-entry-rules.ts +17 -0
- package/src/completion/rules/parameter-list-rules.ts +21 -0
- package/src/completion/rules/parameter-rules.ts +17 -0
- package/src/completion/rules/parameter-value-list-rules.ts +27 -0
- package/src/completion/rules/partial-array-dimension-rules.ts +33 -0
- package/src/completion/rules/specification-rules.ts +37 -0
- package/src/completion/rules/string-definition-rules.ts +103 -0
- package/src/completion/rules/switch-statement-rules.ts +50 -0
- package/src/completion/rules/unary-expression-rules.ts +41 -0
- package/src/completion/rules/utf-string-literal-rules.ts +17 -0
- package/src/completion/rules/while-statement-rules.ts +38 -0
- package/src/lezer/context-tracker.ts +45 -0
- package/src/lezer/create-sdl-parser.ts +88 -0
- package/src/lezer/create-syntax-error-from-text-and-cursor.ts +110 -0
- package/src/lezer/create-syntax-error-from-text-and-position.ts +36 -0
- package/src/lezer/parser.terms.ts +129 -0
- package/src/lezer/parser.ts +63 -0
- package/src/lezer/props/fold-node-prop-source.ts +27 -0
- package/src/lezer/props/primitive-node-prop-source.ts +19 -0
- package/src/lezer/props/style-tags-node-prop-source.ts +188 -0
- package/src/lezer/props/syntactic-token-node-prop-source.ts +298 -0
- package/src/lezer/sdl-string-input.ts +46 -0
- package/src/location.ts +13 -0
- package/src/parse-helper.ts +93 -0
- package/src/prettier/prettier-plugin-sdl.ts +89 -0
- package/src/prettier/print-abstract-array-dimension.ts +84 -0
- package/src/prettier/print-abstract-class-id.ts +53 -0
- package/src/prettier/print-abstract-expression.ts +168 -0
- package/src/prettier/print-abstract-node.ts +224 -0
- package/src/prettier/print-abstract-statement.ts +124 -0
- package/src/prettier/print-aggregate-output-value.ts +35 -0
- package/src/prettier/print-aligned-modifier.ts +50 -0
- package/src/prettier/print-array-definition.ts +95 -0
- package/src/prettier/print-array-element-access.ts +14 -0
- package/src/prettier/print-bit-modifier.ts +48 -0
- package/src/prettier/print-case-clause.ts +58 -0
- package/src/prettier/print-class-declaration.ts +99 -0
- package/src/prettier/print-class-definition.ts +44 -0
- package/src/prettier/print-class-member-access.ts +13 -0
- package/src/prettier/print-computed-array-definition.ts +33 -0
- package/src/prettier/print-computed-elementary-type-definition.ts +60 -0
- package/src/prettier/print-default-clause.ts +39 -0
- package/src/prettier/print-do-statement.ts +31 -0
- package/src/prettier/print-elementary-type-definition.ts +108 -0
- package/src/prettier/print-elementary-type-output-value.ts +13 -0
- package/src/prettier/print-elementary-type.ts +28 -0
- package/src/prettier/print-expandable-modifier.ts +41 -0
- package/src/prettier/print-extends-modifier.ts +29 -0
- package/src/prettier/print-for-statement.ts +64 -0
- package/src/prettier/print-identifier.ts +10 -0
- package/src/prettier/print-if-statement.ts +76 -0
- package/src/prettier/print-length-attribute.ts +14 -0
- package/src/prettier/print-map-declaration.ts +75 -0
- package/src/prettier/print-map-definition.ts +67 -0
- package/src/prettier/print-map-entry.ts +22 -0
- package/src/prettier/print-number-literal.ts +84 -0
- package/src/prettier/print-parameter-list.ts +20 -0
- package/src/prettier/print-parameter-value-list.ts +20 -0
- package/src/prettier/print-parameter.ts +34 -0
- package/src/prettier/print-specification.ts +51 -0
- package/src/prettier/print-string-definition.ts +114 -0
- package/src/prettier/print-string-literal.ts +57 -0
- package/src/prettier/print-switch-statement.ts +46 -0
- package/src/prettier/print-token.ts +7 -0
- package/src/prettier/print-unexpected-error.ts +10 -0
- package/src/prettier/print-while-statement.ts +26 -0
- package/src/prettier/util/print-utils.ts +607 -0
- package/src/prettier/util/types.ts +40 -0
- package/src/scanner-error.ts +65 -0
- package/src/util/location-utils.ts +16 -0
- package/src/util/logger.ts +165 -0
- package/tests/analyser/create-sdl-analyser.test.ts +54 -0
- package/tests/analyser/get-sdl-analyser-test-scenarios.ts +80 -0
- package/tests/analyser/sdl-analyser-scenarios.test.ts +67 -0
- package/tests/analyser/semantic-error-scenarios.test.ts +40 -0
- package/tests/analyser/symbol-table.test.ts +188 -0
- package/tests/analyser/test-cases/array_definition.txt +50 -0
- package/tests/analyser/test-cases/class_declaration.txt +112 -0
- package/tests/analyser/test-cases/class_definition.txt +60 -0
- package/tests/analyser/test-cases/compound_statement.txt +63 -0
- package/tests/analyser/test-cases/computed_array_definition.txt +12 -0
- package/tests/analyser/test-cases/computed_elementary_type_definition.txt +39 -0
- package/tests/analyser/test-cases/do_statement.txt +16 -0
- package/tests/analyser/test-cases/elementary_type_definition.txt +58 -0
- package/tests/analyser/test-cases/expression.txt +159 -0
- package/tests/analyser/test-cases/for_statement.txt +55 -0
- package/tests/analyser/test-cases/if_statement.txt +57 -0
- package/tests/analyser/test-cases/map_declaration.txt +89 -0
- package/tests/analyser/test-cases/map_definition.txt +35 -0
- package/tests/analyser/test-cases/number_literal.txt +31 -0
- package/tests/analyser/test-cases/parameter_list.txt +16 -0
- package/tests/analyser/test-cases/scopes.txt +239 -0
- package/tests/analyser/test-cases/specification.txt +28 -0
- package/tests/analyser/test-cases/string_definition.txt +40 -0
- package/tests/analyser/test-cases/switch_statement.txt +96 -0
- package/tests/analyser/test-cases/while_statement.txt +16 -0
- package/tests/analyser/util/symbol-table-utils.test.ts +65 -0
- package/tests/ast/__snapshots__/build-ast.test.ts.snap +38897 -0
- package/tests/ast/build-ast.test.ts +463 -0
- package/tests/ast/visitor/traversing-visitor.test.ts +36 -0
- package/tests/completion/get-potential-syntactic-tokens.test.ts +89 -0
- package/tests/completion/get-potential-token-type-ids.test.ts +76 -0
- package/tests/completion/test-potential-syntactic-tokens-scenario.ts +24 -0
- package/tests/completion/test-potential-token-type-ids-scenario.ts +33 -0
- package/tests/fixtures/history-recording-node-handler.ts +232 -0
- package/tests/lezer/create-parse-error-from-text-and-position.test.ts +129 -0
- package/tests/lezer/create-sdl-parser.test.ts +15 -0
- package/tests/lezer/sdl-parser-scenarios.test.ts +24 -0
- package/tests/lezer/sdl-string-input.test.ts +12 -0
- package/tests/lezer/syntax-error-scenarios.test.ts +114 -0
- package/tests/lezer/test-cases/array_definition.txt +109 -0
- package/tests/lezer/test-cases/class_declaration.txt +141 -0
- package/tests/lezer/test-cases/class_definition.txt +89 -0
- package/tests/lezer/test-cases/comment.txt +335 -0
- package/tests/lezer/test-cases/compound_statement.txt +109 -0
- package/tests/lezer/test-cases/computed_array_definition.txt +33 -0
- package/tests/lezer/test-cases/computed_elementary_type_definition.txt +59 -0
- package/tests/lezer/test-cases/do_statement.txt +48 -0
- package/tests/lezer/test-cases/elementary_type_definition.txt +158 -0
- package/tests/lezer/test-cases/expression.txt +1203 -0
- package/tests/lezer/test-cases/for_statement.txt +183 -0
- package/tests/lezer/test-cases/if_statement.txt +183 -0
- package/tests/lezer/test-cases/invalid.txt +97 -0
- package/tests/lezer/test-cases/map_declaration.txt +152 -0
- package/tests/lezer/test-cases/map_definition.txt +59 -0
- package/tests/lezer/test-cases/number_literal.txt +273 -0
- package/tests/lezer/test-cases/specification.txt +38 -0
- package/tests/lezer/test-cases/string_definition.txt +263 -0
- package/tests/lezer/test-cases/string_literal.txt +303 -0
- package/tests/lezer/test-cases/switch_statement.txt +407 -0
- package/tests/lezer/test-cases/while_statement.txt +45 -0
- package/tests/parse-helper.test.ts +361 -0
- package/tests/prettier/__snapshots__/prettier-plugin-sdl.test.ts.snap +127 -0
- package/tests/prettier/prettier-plugin-sdl.test.ts +58 -0
- package/tests/prettier/print-array.test.ts +29 -0
- package/tests/prettier/print-class.test.ts +15 -0
- package/tests/prettier/print-do.test.ts +25 -0
- package/tests/prettier/print-elementary-type.test.ts +62 -0
- package/tests/prettier/print-error.test.ts +40 -0
- package/tests/prettier/print-expression.test.ts +17 -0
- package/tests/prettier/print-for.test.ts +23 -0
- package/tests/prettier/print-if.test.ts +71 -0
- package/tests/prettier/print-number-literal.test.ts +28 -0
- package/tests/prettier/print-specification.test.ts +54 -0
- package/tests/prettier/print-string.test.ts +36 -0
- package/tests/prettier/print-switch.test.ts +69 -0
- package/tests/prettier/print-while.test.ts +23 -0
- package/tests/prettier/test-prettier-scenario.ts +41 -0
- package/tests/prettier/util/print-utils.test.ts +665 -0
- package/tests/prettier/util/types.test.ts +38 -0
- package/tests/sample-specifications/invalid.sdl +24 -0
- package/tests/sample-specifications/prettified-invalid.sdl +28 -0
- package/tests/sample-specifications/prettified-various-elements-narrow.sdl +97 -0
- package/tests/sample-specifications/prettified-various-elements.sdl +90 -0
- package/tests/sample-specifications/sample.sdl +24 -0
- package/tests/sample-specifications/various-elements.sdl +88 -0
- package/tests/util/logger.test.ts +36 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { LengthAttribute } from "../../../dist/index.js";
|
|
2
|
+
import type { ElementaryTypeDefinition } from "../../ast/node/elementary-type-definition.ts";
|
|
3
|
+
import { ElementaryTypeKind } from "../../ast/node/enum/elementary-type-kind.ts";
|
|
4
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
5
|
+
import { StatementKind } from "../../ast/node/enum/statement-kind.ts";
|
|
6
|
+
import type { NumberLiteral } from "../../ast/node/number-literal.ts";
|
|
7
|
+
import { isNumberLiteral } from "../../ast/util/types.ts";
|
|
8
|
+
import {
|
|
9
|
+
getElementaryTypeKind,
|
|
10
|
+
getRequiredElementaryType,
|
|
11
|
+
} from "../util/symbol-table-utils.ts";
|
|
12
|
+
import type { Check, CheckResult } from "./check.ts";
|
|
13
|
+
|
|
14
|
+
function checkOptionalCannotDefineRange(
|
|
15
|
+
definition: ElementaryTypeDefinition,
|
|
16
|
+
): CheckResult[] {
|
|
17
|
+
if (
|
|
18
|
+
definition.assignmentOperator === undefined &&
|
|
19
|
+
definition.rangeOperator !== undefined
|
|
20
|
+
) {
|
|
21
|
+
const location = definition.startToken?.getLocation();
|
|
22
|
+
if (location) {
|
|
23
|
+
return [{
|
|
24
|
+
message:
|
|
25
|
+
"An optional elementary type definition cannot define a range for a value.",
|
|
26
|
+
location,
|
|
27
|
+
}];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function checkRangeMinMaxValidation(
|
|
34
|
+
definition: ElementaryTypeDefinition,
|
|
35
|
+
): CheckResult[] {
|
|
36
|
+
if (
|
|
37
|
+
definition.value && definition.endValue &&
|
|
38
|
+
isNumberLiteral(definition.value) && isNumberLiteral(definition.endValue)
|
|
39
|
+
) {
|
|
40
|
+
const minValue = definition.value as NumberLiteral;
|
|
41
|
+
const maxValue = definition.endValue as NumberLiteral;
|
|
42
|
+
|
|
43
|
+
// Check that types match
|
|
44
|
+
if (minValue.numberLiteralKind !== maxValue.numberLiteralKind) {
|
|
45
|
+
const location = maxValue.startToken?.getLocation() ||
|
|
46
|
+
definition.startToken!.getLocation();
|
|
47
|
+
if (location) {
|
|
48
|
+
return [{
|
|
49
|
+
message:
|
|
50
|
+
"The min_value and max_value must be of the same type and the max_value must be greater than or equal to the min_value.",
|
|
51
|
+
location,
|
|
52
|
+
}];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Check that max >= min
|
|
57
|
+
if (maxValue.value < minValue.value) {
|
|
58
|
+
const location = maxValue.startToken?.getLocation() ||
|
|
59
|
+
definition.startToken!.getLocation();
|
|
60
|
+
if (location) {
|
|
61
|
+
return [{
|
|
62
|
+
message:
|
|
63
|
+
"The min_value and max_value must be of the same type and the max_value must be greater than or equal to the min_value.",
|
|
64
|
+
location,
|
|
65
|
+
}];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function checkValueRepresentability(
|
|
73
|
+
definition: ElementaryTypeDefinition,
|
|
74
|
+
strict: boolean,
|
|
75
|
+
): CheckResult[] {
|
|
76
|
+
const elementaryType = getRequiredElementaryType(
|
|
77
|
+
definition.elementaryType,
|
|
78
|
+
definition,
|
|
79
|
+
strict,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
if (!elementaryType) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const elementaryTypeKind = getElementaryTypeKind(elementaryType, strict);
|
|
87
|
+
if (elementaryTypeKind === undefined) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Get bit width from length attribute
|
|
92
|
+
if (
|
|
93
|
+
!definition.lengthAttribute ||
|
|
94
|
+
definition.lengthAttribute.nodeKind !== NodeKind.LENGTH_ATTRIBUTE
|
|
95
|
+
) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const lengthAttribute = definition.lengthAttribute as LengthAttribute;
|
|
100
|
+
if (!isNumberLiteral(lengthAttribute.length)) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const lengthLiteral = lengthAttribute.length as NumberLiteral;
|
|
105
|
+
const bitWidth = lengthLiteral.value;
|
|
106
|
+
|
|
107
|
+
// Check if value is a NumberLiteral
|
|
108
|
+
if (definition.value && isNumberLiteral(definition.value)) {
|
|
109
|
+
const valueLiteral = definition.value as NumberLiteral;
|
|
110
|
+
const value = valueLiteral.value;
|
|
111
|
+
|
|
112
|
+
let isValid = false;
|
|
113
|
+
|
|
114
|
+
switch (elementaryTypeKind) {
|
|
115
|
+
case ElementaryTypeKind.UNSIGNED_INTEGER:
|
|
116
|
+
case ElementaryTypeKind.BIT:
|
|
117
|
+
isValid = value >= 0 && value < Math.pow(2, bitWidth);
|
|
118
|
+
break;
|
|
119
|
+
case ElementaryTypeKind.INTEGER: {
|
|
120
|
+
const minSigned = -Math.pow(2, bitWidth - 1);
|
|
121
|
+
const maxSigned = Math.pow(2, bitWidth - 1);
|
|
122
|
+
isValid = value >= minSigned && value < maxSigned;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case ElementaryTypeKind.FLOATING_POINT:
|
|
126
|
+
isValid = true;
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
isValid = false;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!isValid) {
|
|
134
|
+
const location = valueLiteral.startToken?.getLocation() ||
|
|
135
|
+
definition.startToken!.getLocation();
|
|
136
|
+
if (location) {
|
|
137
|
+
return [{
|
|
138
|
+
message:
|
|
139
|
+
"The specified value cannot be represented using the specific width of the variable.",
|
|
140
|
+
location,
|
|
141
|
+
}];
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const checkElementaryTypeDefinition: Check = {
|
|
150
|
+
nodeKind: NodeKind.STATEMENT,
|
|
151
|
+
subKind: StatementKind.ELEMENTARY_TYPE_DEFINITION,
|
|
152
|
+
checkFunc: function (
|
|
153
|
+
definition: ElementaryTypeDefinition,
|
|
154
|
+
_symbolTable,
|
|
155
|
+
strict: boolean,
|
|
156
|
+
): CheckResult[] {
|
|
157
|
+
const results: CheckResult[] = [];
|
|
158
|
+
|
|
159
|
+
results.push(...checkOptionalCannotDefineRange(definition));
|
|
160
|
+
|
|
161
|
+
results.push(...checkRangeMinMaxValidation(definition));
|
|
162
|
+
|
|
163
|
+
results.push(...checkValueRepresentability(definition, strict));
|
|
164
|
+
|
|
165
|
+
return results;
|
|
166
|
+
},
|
|
167
|
+
};
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
2
|
+
import type { BinaryExpression } from "../../ast/node/binary-expression.ts";
|
|
3
|
+
import type { AbstractExpression } from "../../ast/node/abstract-expression.ts";
|
|
4
|
+
import { BinaryOperatorKind } from "../../ast/node/enum/binary-operator-kind.ts";
|
|
5
|
+
import { ExpressionKind } from "../../ast/node/enum/expression-kind.ts";
|
|
6
|
+
import type { Identifier } from "../../ast/node/identifier.ts";
|
|
7
|
+
import type { NumberLiteral } from "../../ast/node/number-literal.ts";
|
|
8
|
+
import { isIdentifier, isNumberLiteral } from "../../ast/util/types.ts";
|
|
9
|
+
import { resolveNumericType } from "../util/type-utils.ts";
|
|
10
|
+
import { NumericType } from "../symbol-table.ts";
|
|
11
|
+
import type { Check, CheckResult } from "./check.ts";
|
|
12
|
+
import type { SymbolTable } from "../symbol-table.ts";
|
|
13
|
+
|
|
14
|
+
function checkConstMutationViaAssignment(
|
|
15
|
+
node: BinaryExpression,
|
|
16
|
+
symbolTable: SymbolTable,
|
|
17
|
+
): CheckResult[] {
|
|
18
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.ASSIGNMENT) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!isIdentifier(node.leftOperand)) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const identifier = node.leftOperand as Identifier;
|
|
27
|
+
const symbol = symbolTable.lookupVariable(identifier.name);
|
|
28
|
+
|
|
29
|
+
if (symbol && symbol.attributes.isConst && symbol.attributes.isComputed) {
|
|
30
|
+
return [{
|
|
31
|
+
message: "a const computed variable cannot be mutated.",
|
|
32
|
+
location: node.startToken!.getLocation(),
|
|
33
|
+
}];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function checkModulusWithNegativeRhs(
|
|
40
|
+
node: BinaryExpression,
|
|
41
|
+
): CheckResult[] {
|
|
42
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.MODULUS) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!isNumberLiteral(node.rightOperand)) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const rightLiteral = node.rightOperand as NumberLiteral;
|
|
51
|
+
if (rightLiteral.value < 0) {
|
|
52
|
+
return [{
|
|
53
|
+
message:
|
|
54
|
+
"Using the modulus operator with a negative right-hand operand will lead to undefined behavior.",
|
|
55
|
+
location: node.startToken!.getLocation(),
|
|
56
|
+
isWarning: true,
|
|
57
|
+
}];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function checkModulusWithFloatOperands(
|
|
64
|
+
node: BinaryExpression,
|
|
65
|
+
symbolTable: SymbolTable,
|
|
66
|
+
): CheckResult[] {
|
|
67
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.MODULUS) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const leftType = resolveNumericType(node.leftOperand, symbolTable);
|
|
72
|
+
const rightType = resolveNumericType(node.rightOperand, symbolTable);
|
|
73
|
+
|
|
74
|
+
if (
|
|
75
|
+
leftType === NumericType.FLOATING_POINT ||
|
|
76
|
+
rightType === NumericType.FLOATING_POINT
|
|
77
|
+
) {
|
|
78
|
+
return [{
|
|
79
|
+
message: "Using the modulus operator cannot be used with float operands.",
|
|
80
|
+
location: node.startToken!.getLocation(),
|
|
81
|
+
}];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function checkModulusWithZeroRhs(
|
|
88
|
+
node: BinaryExpression,
|
|
89
|
+
): CheckResult[] {
|
|
90
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.MODULUS) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!isNumberLiteral(node.rightOperand)) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const rightLiteral = node.rightOperand as NumberLiteral;
|
|
99
|
+
if (rightLiteral.value === 0) {
|
|
100
|
+
return [{
|
|
101
|
+
message:
|
|
102
|
+
"Using the modulus operator with a right-hand operand of zero will lead to undefined behavior.",
|
|
103
|
+
location: node.startToken!.getLocation(),
|
|
104
|
+
isWarning: true,
|
|
105
|
+
}];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function checkDivisionByZero(
|
|
112
|
+
node: BinaryExpression,
|
|
113
|
+
): CheckResult[] {
|
|
114
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.DIVIDE) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!isNumberLiteral(node.rightOperand)) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const rightLiteral = node.rightOperand as NumberLiteral;
|
|
123
|
+
if (rightLiteral.value === 0) {
|
|
124
|
+
return [{
|
|
125
|
+
message:
|
|
126
|
+
"The value of division where the value of the second operand is zero will lead to undefined behavior.",
|
|
127
|
+
location: node.startToken!.getLocation(),
|
|
128
|
+
isWarning: true,
|
|
129
|
+
}];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function checkIntegerDivisionWithNegatives(
|
|
136
|
+
node: BinaryExpression,
|
|
137
|
+
symbolTable: SymbolTable,
|
|
138
|
+
): CheckResult[] {
|
|
139
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.DIVIDE) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const leftType = resolveNumericType(node.leftOperand, symbolTable);
|
|
144
|
+
const rightType = resolveNumericType(node.rightOperand, symbolTable);
|
|
145
|
+
|
|
146
|
+
if (leftType !== NumericType.INTEGER || rightType !== NumericType.INTEGER) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const leftIsNegative = isNumberLiteral(node.leftOperand) &&
|
|
151
|
+
(node.leftOperand as NumberLiteral).value < 0;
|
|
152
|
+
const rightIsNegative = isNumberLiteral(node.rightOperand) &&
|
|
153
|
+
(node.rightOperand as NumberLiteral).value < 0;
|
|
154
|
+
|
|
155
|
+
if (leftIsNegative || rightIsNegative) {
|
|
156
|
+
return [{
|
|
157
|
+
message:
|
|
158
|
+
"The direction of truncation for integer division with negative operands is not defined by the SDL which will lead to undefined behavior.",
|
|
159
|
+
location: node.startToken!.getLocation(),
|
|
160
|
+
isWarning: true,
|
|
161
|
+
}];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return [];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function checkRightShiftOnSignedInt(
|
|
168
|
+
node: BinaryExpression,
|
|
169
|
+
symbolTable: SymbolTable,
|
|
170
|
+
): CheckResult[] {
|
|
171
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.SHIFT_RIGHT) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const leftType = resolveNumericType(node.leftOperand, symbolTable);
|
|
176
|
+
if (leftType === NumericType.INTEGER) {
|
|
177
|
+
return [{
|
|
178
|
+
message:
|
|
179
|
+
"The behaviour of the right shift operator applied to a signed int value is not defined by the SDL which will lead to undefined behavior.",
|
|
180
|
+
location: node.startToken!.getLocation(),
|
|
181
|
+
isWarning: true,
|
|
182
|
+
}];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function checkLeftHandAssignmentConst(
|
|
189
|
+
node: BinaryExpression,
|
|
190
|
+
symbolTable: SymbolTable,
|
|
191
|
+
): CheckResult[] {
|
|
192
|
+
if (node.binaryOperatorKind !== BinaryOperatorKind.ASSIGNMENT) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!isIdentifier(node.leftOperand)) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const identifier = node.leftOperand as Identifier;
|
|
201
|
+
const symbol = symbolTable.lookupVariable(identifier.name);
|
|
202
|
+
|
|
203
|
+
if (symbol && symbol.attributes.isConst) {
|
|
204
|
+
return [{
|
|
205
|
+
message:
|
|
206
|
+
"The left-hand operand of an assignment operator cannot be a const variable.",
|
|
207
|
+
location: node.startToken!.getLocation(),
|
|
208
|
+
}];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export const checkExpressionBinary: Check = {
|
|
215
|
+
nodeKind: NodeKind.EXPRESSION,
|
|
216
|
+
subKind: ExpressionKind.BINARY,
|
|
217
|
+
checkFunc: function (
|
|
218
|
+
node: AbstractExpression,
|
|
219
|
+
symbolTable: SymbolTable,
|
|
220
|
+
_strict: boolean,
|
|
221
|
+
): CheckResult[] {
|
|
222
|
+
const results: CheckResult[] = [];
|
|
223
|
+
|
|
224
|
+
// Only process BinaryExpression nodes
|
|
225
|
+
if (node.expressionKind !== ExpressionKind.BINARY) {
|
|
226
|
+
return results;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const binaryExpression = node as BinaryExpression;
|
|
230
|
+
|
|
231
|
+
return [
|
|
232
|
+
...checkConstMutationViaAssignment(binaryExpression, symbolTable),
|
|
233
|
+
...checkModulusWithNegativeRhs(binaryExpression),
|
|
234
|
+
...checkModulusWithFloatOperands(binaryExpression, symbolTable),
|
|
235
|
+
...checkModulusWithZeroRhs(binaryExpression),
|
|
236
|
+
...checkDivisionByZero(binaryExpression),
|
|
237
|
+
...checkIntegerDivisionWithNegatives(binaryExpression, symbolTable),
|
|
238
|
+
...checkRightShiftOnSignedInt(binaryExpression, symbolTable),
|
|
239
|
+
...checkLeftHandAssignmentConst(binaryExpression, symbolTable),
|
|
240
|
+
];
|
|
241
|
+
},
|
|
242
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ExpressionKind } from "../../ast/node/enum/expression-kind.ts";
|
|
2
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
3
|
+
import type { LengthofExpression } from "../../ast/node/length-of-expression.ts";
|
|
4
|
+
import { isIdentifier } from "../../ast/util/types.ts";
|
|
5
|
+
import type { Check, CheckResult } from "./check.ts";
|
|
6
|
+
|
|
7
|
+
export const checkExpressionLengthof: Check = {
|
|
8
|
+
nodeKind: NodeKind.EXPRESSION,
|
|
9
|
+
subKind: ExpressionKind.LENGTHOF,
|
|
10
|
+
checkFunc: function (
|
|
11
|
+
node: LengthofExpression,
|
|
12
|
+
symbolTable,
|
|
13
|
+
_strict,
|
|
14
|
+
): CheckResult[] {
|
|
15
|
+
const results: CheckResult[] = [];
|
|
16
|
+
|
|
17
|
+
// Check if operand is an identifier
|
|
18
|
+
if (isIdentifier(node.operand)) {
|
|
19
|
+
// Look up the variable in the symbol table
|
|
20
|
+
const variable = symbolTable.lookupVariable(node.operand.name);
|
|
21
|
+
|
|
22
|
+
// If variable exists and is computed, report error
|
|
23
|
+
if (variable && variable.attributes.isComputed) {
|
|
24
|
+
results.push({
|
|
25
|
+
message:
|
|
26
|
+
"The lengthof operator cannot be used with a computed variable.",
|
|
27
|
+
location: node.operand.startToken!.getLocation(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return results;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { ArrayDefinition } from "../../ast/node/array-definition.ts";
|
|
2
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
3
|
+
import { StatementKind } from "../../ast/node/enum/statement-kind.ts";
|
|
4
|
+
import { TokenKind } from "../../ast/node/enum/token-kind.ts";
|
|
5
|
+
import type { UnaryExpression } from "../../ast/node/unary-expression.ts";
|
|
6
|
+
import { ExpressionKind } from "../../ast/node/enum/expression-kind.ts";
|
|
7
|
+
import { isIdentifier, isUnaryExpression } from "../../ast/util/types.ts";
|
|
8
|
+
import type { SymbolTable } from "../symbol-table.ts";
|
|
9
|
+
import type { Check, CheckResult } from "./check.ts";
|
|
10
|
+
import type { AbstractStatement } from "../../ast/node/abstract-statement.ts";
|
|
11
|
+
import type { Token } from "../../ast/node/token.ts";
|
|
12
|
+
import type { Identifier } from "../../ast/node/identifier.ts";
|
|
13
|
+
import type { NumberLiteral } from "../../ast/node/number-literal.ts";
|
|
14
|
+
|
|
15
|
+
function checkConstMutationViaPostfix(
|
|
16
|
+
expression: UnaryExpression,
|
|
17
|
+
symbolTable: SymbolTable,
|
|
18
|
+
): CheckResult[] {
|
|
19
|
+
const results: CheckResult[] = [];
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
expression.postfixOperator !== undefined &&
|
|
23
|
+
((expression.postfixOperator as Token).tokenKind ===
|
|
24
|
+
TokenKind.POSTFIX_INCREMENT ||
|
|
25
|
+
(expression.postfixOperator as Token).tokenKind ===
|
|
26
|
+
TokenKind.POSTFIX_DECREMENT)
|
|
27
|
+
) {
|
|
28
|
+
let targetIdentifier: Identifier | undefined;
|
|
29
|
+
if (isIdentifier(expression.operand)) {
|
|
30
|
+
targetIdentifier = expression.operand;
|
|
31
|
+
} else if (
|
|
32
|
+
expression.operand.nodeKind === NodeKind.EXPRESSION &&
|
|
33
|
+
isIdentifier((expression.operand as UnaryExpression).operand)
|
|
34
|
+
) {
|
|
35
|
+
targetIdentifier = (expression.operand as UnaryExpression)
|
|
36
|
+
.operand as Identifier;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (targetIdentifier) {
|
|
40
|
+
const variable = symbolTable.lookupVariable(targetIdentifier.name);
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
variable &&
|
|
44
|
+
variable.attributes.isConst &&
|
|
45
|
+
variable.attributes.isComputed
|
|
46
|
+
) {
|
|
47
|
+
results.push({
|
|
48
|
+
message: "a const computed variable cannot be mutated.",
|
|
49
|
+
location: expression.startToken!.getLocation(),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return results;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function checkArrayDimensionCountMismatch(
|
|
59
|
+
expression: UnaryExpression,
|
|
60
|
+
symbolTable: SymbolTable,
|
|
61
|
+
): CheckResult[] {
|
|
62
|
+
const results: CheckResult[] = [];
|
|
63
|
+
|
|
64
|
+
if (expression.arrayElementAccess) {
|
|
65
|
+
// Find the base identifier by traversing nested UnaryExpressions
|
|
66
|
+
let baseIdentifier: Identifier | undefined;
|
|
67
|
+
let currentExpr: UnaryExpression | Identifier | NumberLiteral = expression;
|
|
68
|
+
let accessDimensions = 0;
|
|
69
|
+
|
|
70
|
+
// Count array access dimensions by traversing the nested structure
|
|
71
|
+
while (isUnaryExpression(currentExpr)) {
|
|
72
|
+
if (currentExpr.arrayElementAccess) {
|
|
73
|
+
accessDimensions++;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
currentExpr = currentExpr.operand as UnaryExpression;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check if we found an identifier at the base
|
|
80
|
+
if (isIdentifier(currentExpr)) {
|
|
81
|
+
baseIdentifier = currentExpr;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (baseIdentifier) {
|
|
85
|
+
const variable = symbolTable.lookupVariable(baseIdentifier.name);
|
|
86
|
+
|
|
87
|
+
if (variable && variable.attributes.isArray) {
|
|
88
|
+
// Get the array definition from the symbol's AST node
|
|
89
|
+
const arrayDefinition = variable.node as ArrayDefinition;
|
|
90
|
+
|
|
91
|
+
// Count dimensions in the array definition
|
|
92
|
+
let definedDimensions = 0;
|
|
93
|
+
|
|
94
|
+
if (arrayDefinition.implicitArrayDimension) {
|
|
95
|
+
definedDimensions++;
|
|
96
|
+
}
|
|
97
|
+
definedDimensions += arrayDefinition.dimensions.length;
|
|
98
|
+
|
|
99
|
+
if (definedDimensions !== accessDimensions) {
|
|
100
|
+
results.push({
|
|
101
|
+
message:
|
|
102
|
+
"The number of dimensions used when accessing an array element must match the number of dimensions in the array definition.",
|
|
103
|
+
location: expression.startToken!.getLocation()!,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function checkUninitializedComputedVariableAccess(
|
|
114
|
+
expression: UnaryExpression,
|
|
115
|
+
_symbolTable: SymbolTable,
|
|
116
|
+
): CheckResult[] {
|
|
117
|
+
const results: CheckResult[] = [];
|
|
118
|
+
|
|
119
|
+
if (isIdentifier(expression.operand)) {
|
|
120
|
+
const variable = _symbolTable.lookupVariable(expression.operand.name);
|
|
121
|
+
|
|
122
|
+
if (variable && variable.attributes.isComputed) {
|
|
123
|
+
// Check if the variable definition has no initial value
|
|
124
|
+
// For computed variables, this would be AbstractElementaryTypeDefinition
|
|
125
|
+
if (
|
|
126
|
+
(variable.node.nodeKind === NodeKind.STATEMENT) &&
|
|
127
|
+
((variable.node as AbstractStatement).statementKind ===
|
|
128
|
+
StatementKind.COMPUTED_ELEMENTARY_TYPE_DEFINITION)
|
|
129
|
+
) {
|
|
130
|
+
const definition = variable.node as { value?: unknown };
|
|
131
|
+
|
|
132
|
+
if (!definition.value) {
|
|
133
|
+
results.push({
|
|
134
|
+
message:
|
|
135
|
+
"Accessing a computed variable value before it is initialised will result in undefined behaviour.",
|
|
136
|
+
location: expression.operand.startToken?.getLocation() ||
|
|
137
|
+
expression.operand.leadingTrivia?.[0]?.location!,
|
|
138
|
+
isWarning: true,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return results;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const checkExpressionUnary: Check = {
|
|
149
|
+
nodeKind: NodeKind.EXPRESSION,
|
|
150
|
+
subKind: ExpressionKind.UNARY,
|
|
151
|
+
checkFunc: function (
|
|
152
|
+
expression: UnaryExpression,
|
|
153
|
+
symbolTable: SymbolTable,
|
|
154
|
+
_strict: boolean,
|
|
155
|
+
): CheckResult[] {
|
|
156
|
+
const results: CheckResult[] = [];
|
|
157
|
+
|
|
158
|
+
results.push(...checkConstMutationViaPostfix(expression, symbolTable));
|
|
159
|
+
results.push(...checkArrayDimensionCountMismatch(expression, symbolTable));
|
|
160
|
+
results.push(
|
|
161
|
+
...checkUninitializedComputedVariableAccess(expression, symbolTable),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
return results;
|
|
165
|
+
},
|
|
166
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
2
|
+
import type { Identifier } from "../../ast/node/identifier.ts";
|
|
3
|
+
import type { Check, CheckResult } from "./check.ts";
|
|
4
|
+
|
|
5
|
+
// Build set of SDL keywords and literal prefixes
|
|
6
|
+
const getReservedIdentifiers = (): Set<string> => {
|
|
7
|
+
// Add SDL keywords from token mapping
|
|
8
|
+
const reserved = new Set([
|
|
9
|
+
"abstract",
|
|
10
|
+
"aligned",
|
|
11
|
+
"base64string",
|
|
12
|
+
"bit",
|
|
13
|
+
"break",
|
|
14
|
+
"case",
|
|
15
|
+
"class",
|
|
16
|
+
"computed",
|
|
17
|
+
"const",
|
|
18
|
+
"default",
|
|
19
|
+
"do",
|
|
20
|
+
"else",
|
|
21
|
+
"expandable",
|
|
22
|
+
"extends",
|
|
23
|
+
"float",
|
|
24
|
+
"for",
|
|
25
|
+
"if",
|
|
26
|
+
"int",
|
|
27
|
+
"legacy",
|
|
28
|
+
"lengthof",
|
|
29
|
+
"map",
|
|
30
|
+
"reserved",
|
|
31
|
+
"switch",
|
|
32
|
+
"unsigned",
|
|
33
|
+
"utf8string",
|
|
34
|
+
"utf16string",
|
|
35
|
+
"utfstring",
|
|
36
|
+
"utf8list",
|
|
37
|
+
"while",
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
// Add literal prefixes
|
|
41
|
+
reserved.add("0b");
|
|
42
|
+
reserved.add("0x");
|
|
43
|
+
|
|
44
|
+
return reserved;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const reservedIdentifiers = getReservedIdentifiers();
|
|
48
|
+
|
|
49
|
+
export const checkIdentifier: Check = {
|
|
50
|
+
nodeKind: NodeKind.IDENTIFIER,
|
|
51
|
+
checkFunc: function (
|
|
52
|
+
node: Identifier,
|
|
53
|
+
_symbolTable,
|
|
54
|
+
_strict,
|
|
55
|
+
): CheckResult[] {
|
|
56
|
+
const results: CheckResult[] = [];
|
|
57
|
+
|
|
58
|
+
const identifierName = node.name.toLowerCase();
|
|
59
|
+
|
|
60
|
+
if (reservedIdentifiers.has(identifierName)) {
|
|
61
|
+
results.push({
|
|
62
|
+
message:
|
|
63
|
+
"It is illegal to define an identifier which conflicts (ignoring case) with SDL syntax items such as keywords, binary, hexadecimal and string literal prefixes.",
|
|
64
|
+
location: node.startToken?.getLocation() ||
|
|
65
|
+
node.leadingTrivia?.[0]?.location!,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return results;
|
|
70
|
+
},
|
|
71
|
+
};
|