@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,458 @@
|
|
|
1
|
+
import type { AbstractNode } from "../../ast/node/abstract-node.ts";
|
|
2
|
+
import type { ElementaryType } from "../../ast/node/elementary-type.ts";
|
|
3
|
+
import { ElementaryTypeKind } from "../../ast/node/enum/elementary-type-kind.ts";
|
|
4
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
5
|
+
import { StringVariableKind } from "../../ast/node/enum/string-variable-kind.ts";
|
|
6
|
+
import { TokenKind } from "../../ast/node/enum/token-kind.ts";
|
|
7
|
+
import type { Identifier } from "../../ast/node/identifier.ts";
|
|
8
|
+
import type { Token } from "../../ast/node/token.ts";
|
|
9
|
+
import {
|
|
10
|
+
isAbstractExpression,
|
|
11
|
+
isElementaryType,
|
|
12
|
+
isIdentifier,
|
|
13
|
+
isNumberLiteral,
|
|
14
|
+
isToken,
|
|
15
|
+
type RequiredNode,
|
|
16
|
+
} from "../../ast/util/types.ts";
|
|
17
|
+
import { SemanticError } from "../../scanner-error.ts";
|
|
18
|
+
import getLogger from "../../util/logger.ts";
|
|
19
|
+
import {
|
|
20
|
+
NumericType,
|
|
21
|
+
type Scope,
|
|
22
|
+
ScopeKind,
|
|
23
|
+
StringType,
|
|
24
|
+
type Symbol,
|
|
25
|
+
SymbolKind,
|
|
26
|
+
type SymbolTable,
|
|
27
|
+
} from "../symbol-table.ts";
|
|
28
|
+
|
|
29
|
+
const logger = getLogger("SymbolTableUtils");
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Converts the given node to a required Identifier.
|
|
33
|
+
* If the node is undefined or not an Identifier, it throws a SemanticError in strict mode.
|
|
34
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
35
|
+
*
|
|
36
|
+
* @param node the node to convert
|
|
37
|
+
* @param parentNode the parent node for error location context
|
|
38
|
+
* @param strict whether to operate in strict mode
|
|
39
|
+
* @return the node as an Identifier or undefined
|
|
40
|
+
*/
|
|
41
|
+
export function getRequiredIdentifier(
|
|
42
|
+
node: RequiredNode<AbstractNode>,
|
|
43
|
+
parentNode: AbstractNode,
|
|
44
|
+
strict: boolean,
|
|
45
|
+
): Identifier | undefined {
|
|
46
|
+
if (node === undefined) {
|
|
47
|
+
if (strict) {
|
|
48
|
+
throw new SemanticError(
|
|
49
|
+
"Required identifier property is missing",
|
|
50
|
+
parentNode.leadingTrivia
|
|
51
|
+
? parentNode.leadingTrivia[0].location
|
|
52
|
+
: undefined,
|
|
53
|
+
);
|
|
54
|
+
} else {
|
|
55
|
+
logger.debug(
|
|
56
|
+
"Ignoring missing required identifier property in lenient mode.",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isIdentifier(node)) {
|
|
63
|
+
return node;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (strict) {
|
|
67
|
+
if (isToken(node)) {
|
|
68
|
+
throw new SemanticError(
|
|
69
|
+
`Required identifier property is a Token node: ${
|
|
70
|
+
TokenKind[node.tokenKind]
|
|
71
|
+
}`,
|
|
72
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
throw new SemanticError(
|
|
76
|
+
"Required identifier property is not an Identifier node: " +
|
|
77
|
+
NodeKind[node.nodeKind],
|
|
78
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
79
|
+
);
|
|
80
|
+
} else {
|
|
81
|
+
logger.debug(
|
|
82
|
+
"Ignoring invalid required identifier property in lenient mode.",
|
|
83
|
+
);
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Converts the given node to a required Token.
|
|
90
|
+
* If the node is undefined or not an Token, it throws a SemanticError in strict mode.
|
|
91
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
92
|
+
*
|
|
93
|
+
* @param node the node to convert
|
|
94
|
+
* @param parentNode the parent node for error location context
|
|
95
|
+
* @param strict whether to operate in strict mode
|
|
96
|
+
* @return the node as an Token or undefined
|
|
97
|
+
*/
|
|
98
|
+
export function getRequiredToken(
|
|
99
|
+
node: RequiredNode<AbstractNode>,
|
|
100
|
+
parentNode: AbstractNode,
|
|
101
|
+
strict: boolean,
|
|
102
|
+
): Token | undefined {
|
|
103
|
+
if (node === undefined) {
|
|
104
|
+
if (strict) {
|
|
105
|
+
throw new SemanticError(
|
|
106
|
+
"Required token property is missing",
|
|
107
|
+
parentNode.leadingTrivia
|
|
108
|
+
? parentNode.leadingTrivia[0].location
|
|
109
|
+
: undefined,
|
|
110
|
+
);
|
|
111
|
+
} else {
|
|
112
|
+
logger.debug(
|
|
113
|
+
"Ignoring missing required token property in lenient mode.",
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isToken(node)) {
|
|
120
|
+
return node;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (strict) {
|
|
124
|
+
throw new SemanticError(
|
|
125
|
+
"Required token property is not a Token node: " + NodeKind[node.nodeKind],
|
|
126
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
logger.debug(
|
|
130
|
+
"Ignoring invalid required token property in lenient mode.",
|
|
131
|
+
);
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Converts the given node to a required ElementaryType.
|
|
138
|
+
* If the node is undefined or not an ElementaryType, it throws a SemanticError in strict mode.
|
|
139
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
140
|
+
*
|
|
141
|
+
* @param node the node to convert
|
|
142
|
+
* @param parentNode the parent node for error location context
|
|
143
|
+
* @param strict whether to operate in strict mode
|
|
144
|
+
* @return the node as an ElementaryType or undefined
|
|
145
|
+
*/
|
|
146
|
+
export function getRequiredElementaryType(
|
|
147
|
+
node: RequiredNode<AbstractNode>,
|
|
148
|
+
parentNode: AbstractNode,
|
|
149
|
+
strict: boolean,
|
|
150
|
+
): ElementaryType | undefined {
|
|
151
|
+
if (node === undefined) {
|
|
152
|
+
if (strict) {
|
|
153
|
+
throw new SemanticError(
|
|
154
|
+
"Required elementary type property is missing",
|
|
155
|
+
parentNode.leadingTrivia
|
|
156
|
+
? parentNode.leadingTrivia[0].location
|
|
157
|
+
: undefined,
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
logger.debug(
|
|
161
|
+
"Ignoring missing required elementary type property in lenient mode.",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
return undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (isElementaryType(node)) {
|
|
168
|
+
return node;
|
|
169
|
+
}
|
|
170
|
+
if (strict) {
|
|
171
|
+
if (isToken(node)) {
|
|
172
|
+
throw new SemanticError(
|
|
173
|
+
`Required identifier property is a Token node: ${
|
|
174
|
+
TokenKind[node.tokenKind]
|
|
175
|
+
}`,
|
|
176
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
throw new SemanticError(
|
|
180
|
+
"Required elementary type property is not an ElementaryType node: " +
|
|
181
|
+
NodeKind[node.nodeKind],
|
|
182
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
183
|
+
);
|
|
184
|
+
} else {
|
|
185
|
+
logger.debug(
|
|
186
|
+
"Ignoring invalid required elementary type property in lenient mode.",
|
|
187
|
+
);
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Converts the ElementaryType node to a required ElementaryTypeKind.
|
|
194
|
+
* If the ElementaryType is not populated fully, it throws a SemanticError in strict mode.
|
|
195
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
196
|
+
*/
|
|
197
|
+
export function getElementaryTypeKind(
|
|
198
|
+
elementaryType: ElementaryType,
|
|
199
|
+
strict: boolean,
|
|
200
|
+
): ElementaryTypeKind | undefined {
|
|
201
|
+
if (elementaryType.unsignedQualifierKeyword) {
|
|
202
|
+
if (!isToken(elementaryType.unsignedQualifierKeyword)) {
|
|
203
|
+
if (strict) {
|
|
204
|
+
throw new SemanticError(
|
|
205
|
+
"Elementary type unsigned qualifier is not a Token node: " +
|
|
206
|
+
NodeKind[elementaryType.unsignedQualifierKeyword.nodeKind],
|
|
207
|
+
elementaryType.leadingTrivia
|
|
208
|
+
? elementaryType.leadingTrivia[0].location
|
|
209
|
+
: undefined,
|
|
210
|
+
);
|
|
211
|
+
} else {
|
|
212
|
+
logger.debug(
|
|
213
|
+
"Ignoring invalid elementary type unsigned qualifier in lenient mode.",
|
|
214
|
+
);
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (
|
|
220
|
+
elementaryType.unsignedQualifierKeyword.tokenKind !== TokenKind.UNSIGNED
|
|
221
|
+
) {
|
|
222
|
+
if (strict) {
|
|
223
|
+
throw new SemanticError(
|
|
224
|
+
`Elementary type unsigned qualifier has invalid token kind: ${
|
|
225
|
+
TokenKind[elementaryType.unsignedQualifierKeyword.tokenKind]
|
|
226
|
+
}`,
|
|
227
|
+
elementaryType.unsignedQualifierKeyword.getLocation(),
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
logger.debug(
|
|
231
|
+
`Ignoring invalid elementary type unsigned qualifier token kind: ${
|
|
232
|
+
TokenKind[elementaryType.unsignedQualifierKeyword.tokenKind]
|
|
233
|
+
} in lenient mode.`,
|
|
234
|
+
);
|
|
235
|
+
return undefined;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!isToken(elementaryType.typeKeyword)) {
|
|
241
|
+
if (strict) {
|
|
242
|
+
throw new SemanticError(
|
|
243
|
+
"Elementary type type keyword is not a Token node: " +
|
|
244
|
+
NodeKind[elementaryType.typeKeyword.nodeKind],
|
|
245
|
+
elementaryType.leadingTrivia
|
|
246
|
+
? elementaryType.leadingTrivia[0].location
|
|
247
|
+
: undefined,
|
|
248
|
+
);
|
|
249
|
+
} else {
|
|
250
|
+
logger.debug(
|
|
251
|
+
"Ignoring invalid elementary type type keyword in lenient mode.",
|
|
252
|
+
);
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const isUnsigned = elementaryType.unsignedQualifierKeyword !== undefined;
|
|
258
|
+
const typeToken = elementaryType.typeKeyword as Token;
|
|
259
|
+
|
|
260
|
+
switch (typeToken.tokenKind) {
|
|
261
|
+
case TokenKind.INT:
|
|
262
|
+
return isUnsigned
|
|
263
|
+
? ElementaryTypeKind.UNSIGNED_INTEGER
|
|
264
|
+
: ElementaryTypeKind.INTEGER;
|
|
265
|
+
case TokenKind.FLOAT:
|
|
266
|
+
return ElementaryTypeKind.FLOATING_POINT;
|
|
267
|
+
case TokenKind.BIT:
|
|
268
|
+
return ElementaryTypeKind.BIT;
|
|
269
|
+
default:
|
|
270
|
+
if (strict) {
|
|
271
|
+
throw new SemanticError(
|
|
272
|
+
`Unsupported elementary type token kind: ${
|
|
273
|
+
TokenKind[typeToken.tokenKind]
|
|
274
|
+
}`,
|
|
275
|
+
typeToken.getLocation(),
|
|
276
|
+
);
|
|
277
|
+
} else {
|
|
278
|
+
logger.debug(
|
|
279
|
+
`Ignoring unsupported elementary type token kind: ${
|
|
280
|
+
TokenKind[typeToken.tokenKind]
|
|
281
|
+
} in lenient mode.`,
|
|
282
|
+
);
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Converts the given string variable kind Token to a required StringVariableKind.
|
|
290
|
+
* If the Token is not populated fully, it throws a SemanticError in strict mode.
|
|
291
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
292
|
+
*/
|
|
293
|
+
export function getStringVariableKind(
|
|
294
|
+
stringVariableKindToken: Token,
|
|
295
|
+
strict: boolean,
|
|
296
|
+
): StringVariableKind | undefined {
|
|
297
|
+
switch (stringVariableKindToken.tokenKind) {
|
|
298
|
+
case TokenKind.BASE64_STRING:
|
|
299
|
+
return StringVariableKind.BASE64;
|
|
300
|
+
case TokenKind.UTF8_STRING:
|
|
301
|
+
return StringVariableKind.UTF8;
|
|
302
|
+
case TokenKind.UTF16_STRING:
|
|
303
|
+
return StringVariableKind.UTF16;
|
|
304
|
+
case TokenKind.UTF_STRING:
|
|
305
|
+
return StringVariableKind.UTF;
|
|
306
|
+
case TokenKind.UTF8_LIST:
|
|
307
|
+
return StringVariableKind.UTF8_LIST;
|
|
308
|
+
default:
|
|
309
|
+
if (strict) {
|
|
310
|
+
throw new SemanticError(
|
|
311
|
+
`Unsupported string variable kind token: ${
|
|
312
|
+
TokenKind[stringVariableKindToken.tokenKind]
|
|
313
|
+
}`,
|
|
314
|
+
stringVariableKindToken.getLocation(),
|
|
315
|
+
);
|
|
316
|
+
} else {
|
|
317
|
+
logger.debug(
|
|
318
|
+
`Ignoring unsupported string variable kind token: ${
|
|
319
|
+
TokenKind[stringVariableKindToken.tokenKind]
|
|
320
|
+
} in lenient mode.`,
|
|
321
|
+
);
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Converts the given node to a required Operand.
|
|
329
|
+
* If the node is undefined or not an AbstractExpression, Identifier or
|
|
330
|
+
* NumberLiteral, it throws a SemanticError in strict mode.
|
|
331
|
+
* In lenient mode, it logs a debug message and returns undefined.
|
|
332
|
+
*
|
|
333
|
+
* @param node the node to convert
|
|
334
|
+
* @param parentNode the parent node for error location context
|
|
335
|
+
* @param strict whether to operate in strict mode
|
|
336
|
+
* @return the node or undefined
|
|
337
|
+
*/
|
|
338
|
+
export function getRequiredOperand(
|
|
339
|
+
node: RequiredNode<AbstractNode>,
|
|
340
|
+
parentNode: AbstractNode,
|
|
341
|
+
strict: boolean,
|
|
342
|
+
): AbstractNode | undefined {
|
|
343
|
+
if (node === undefined) {
|
|
344
|
+
if (strict) {
|
|
345
|
+
throw new SemanticError(
|
|
346
|
+
"Required operand property is missing",
|
|
347
|
+
parentNode.leadingTrivia
|
|
348
|
+
? parentNode.leadingTrivia[0].location
|
|
349
|
+
: undefined,
|
|
350
|
+
);
|
|
351
|
+
} else {
|
|
352
|
+
logger.debug(
|
|
353
|
+
"Ignoring missing required operand property in lenient mode.",
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
return undefined;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (
|
|
360
|
+
isAbstractExpression(node) || isIdentifier(node) || isNumberLiteral(node)
|
|
361
|
+
) {
|
|
362
|
+
return node;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (strict) {
|
|
366
|
+
throw new SemanticError(
|
|
367
|
+
"Required operand property is not an AbstractExpression, Identifier or NumberLiteral node: " +
|
|
368
|
+
NodeKind[node.nodeKind],
|
|
369
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
370
|
+
);
|
|
371
|
+
} else {
|
|
372
|
+
logger.debug(
|
|
373
|
+
"Ignoring invalid required operand property in lenient mode.",
|
|
374
|
+
);
|
|
375
|
+
return undefined;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function getSymbolString(symbol: Symbol): string {
|
|
380
|
+
const kindName = SymbolKind[symbol.kind];
|
|
381
|
+
let attributesStr = "";
|
|
382
|
+
|
|
383
|
+
if (symbol.attributes) {
|
|
384
|
+
const attributes = symbol.attributes;
|
|
385
|
+
const parts: string[] = [];
|
|
386
|
+
|
|
387
|
+
if (attributes.stringType !== undefined) {
|
|
388
|
+
parts.push(StringType[attributes.stringType]);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (attributes.numericType !== undefined) {
|
|
392
|
+
parts.push(NumericType[attributes.numericType]);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (attributes.classType) {
|
|
396
|
+
parts.push("(class: " + attributes.classType + ")");
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (attributes.mapType) {
|
|
400
|
+
parts.push("(map: " + attributes.mapType + ")");
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (attributes.isComputed) {
|
|
404
|
+
parts.push("COMPUTED");
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (attributes.isConst) {
|
|
408
|
+
parts.push("CONST");
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (attributes.isArray) {
|
|
412
|
+
parts.push("[]");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
attributesStr = parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
416
|
+
}
|
|
417
|
+
return `${symbol.name} ${kindName}${attributesStr}`;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function getSymbolTableString(symbolTable: SymbolTable): string {
|
|
421
|
+
const lines: string[] = [];
|
|
422
|
+
const formatScope = (scope: Scope, indent: number): void => {
|
|
423
|
+
const prefix = " ".repeat(indent);
|
|
424
|
+
|
|
425
|
+
lines.push(
|
|
426
|
+
`${prefix}[${ScopeKind[scope.kind]}]${
|
|
427
|
+
scope.kind === ScopeKind.GLOBAL ? "" : " " + scope.name
|
|
428
|
+
}:`,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
if (scope.classMemberSymbols && (scope.classMemberSymbols.size > 0)) {
|
|
432
|
+
lines.push(`${prefix} members:`);
|
|
433
|
+
|
|
434
|
+
for (const memberEntries of scope.classMemberSymbols.values()) {
|
|
435
|
+
for (const entry of memberEntries) {
|
|
436
|
+
const branchStr = entry.branchId
|
|
437
|
+
? ` (branch: ${entry.branchId})`
|
|
438
|
+
: "";
|
|
439
|
+
lines.push(
|
|
440
|
+
`${prefix} ${getSymbolString(entry.symbol)}${branchStr}`,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
for (const symbol of scope.symbols.values()) {
|
|
447
|
+
lines.push(`${prefix} ${getSymbolString(symbol)}`);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for (const child of scope.children) {
|
|
451
|
+
formatScope(child, indent + 1);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
formatScope(symbolTable.getGlobalScope(), 0);
|
|
456
|
+
|
|
457
|
+
return lines.join("\n").trim();
|
|
458
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import type { AbstractExpression } from "../../ast/node/abstract-expression.ts";
|
|
2
|
+
import type { AbstractNode } from "../../ast/node/abstract-node.ts";
|
|
3
|
+
import { BinaryOperatorKind } from "../../ast/node/enum/binary-operator-kind.ts";
|
|
4
|
+
import { ElementaryTypeKind } from "../../ast/node/enum/elementary-type-kind.ts";
|
|
5
|
+
import { ExpressionKind } from "../../ast/node/enum/expression-kind.ts";
|
|
6
|
+
import { NumberLiteralKind } from "../../ast/node/enum/number-literal-kind.ts";
|
|
7
|
+
import type { Identifier } from "../../ast/node/identifier.ts";
|
|
8
|
+
import type { BinaryExpression } from "../../ast/node/binary-expression.ts";
|
|
9
|
+
import type { UnaryExpression } from "../../ast/node/unary-expression.ts";
|
|
10
|
+
import {
|
|
11
|
+
isAbstractExpression,
|
|
12
|
+
isIdentifier,
|
|
13
|
+
isNumberLiteral,
|
|
14
|
+
} from "../../ast/util/types.ts";
|
|
15
|
+
import { NumericType, StringType, type SymbolTable } from "../symbol-table.ts";
|
|
16
|
+
import { InternalScannerError } from "../../scanner-error.ts";
|
|
17
|
+
import { StringVariableKind } from "../../ast/node/enum/string-variable-kind.ts";
|
|
18
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
19
|
+
|
|
20
|
+
export function getNumericTypeFromElementaryTypeKind(
|
|
21
|
+
kind: ElementaryTypeKind,
|
|
22
|
+
): NumericType {
|
|
23
|
+
switch (kind) {
|
|
24
|
+
case ElementaryTypeKind.INTEGER:
|
|
25
|
+
case ElementaryTypeKind.UNSIGNED_INTEGER:
|
|
26
|
+
case ElementaryTypeKind.BIT:
|
|
27
|
+
return NumericType.INTEGER;
|
|
28
|
+
case ElementaryTypeKind.FLOATING_POINT:
|
|
29
|
+
return NumericType.FLOATING_POINT;
|
|
30
|
+
default: {
|
|
31
|
+
const exhaustiveCheck: never = kind;
|
|
32
|
+
throw new InternalScannerError(
|
|
33
|
+
"Unreachable code reached, kind == " + exhaustiveCheck,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getStringTypeFromStringVariableKind(
|
|
40
|
+
kind: StringVariableKind,
|
|
41
|
+
): StringType {
|
|
42
|
+
switch (kind) {
|
|
43
|
+
case StringVariableKind.BASE64:
|
|
44
|
+
return StringType.BASIC;
|
|
45
|
+
case StringVariableKind.UTF8:
|
|
46
|
+
case StringVariableKind.UTF16:
|
|
47
|
+
case StringVariableKind.UTF:
|
|
48
|
+
case StringVariableKind.UTF8_LIST:
|
|
49
|
+
return StringType.UCS;
|
|
50
|
+
default: {
|
|
51
|
+
const exhaustiveCheck: never = kind;
|
|
52
|
+
throw new InternalScannerError(
|
|
53
|
+
"Unreachable code reached, kind == " + exhaustiveCheck,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getNumericTypeFromNumberLiteralKind(
|
|
60
|
+
kind: NumberLiteralKind,
|
|
61
|
+
): NumericType {
|
|
62
|
+
switch (kind) {
|
|
63
|
+
case NumberLiteralKind.BINARY:
|
|
64
|
+
case NumberLiteralKind.HEXADECIMAL:
|
|
65
|
+
case NumberLiteralKind.INTEGER:
|
|
66
|
+
case NumberLiteralKind.MULTIPLE_CHARACTER:
|
|
67
|
+
return NumericType.INTEGER;
|
|
68
|
+
case NumberLiteralKind.FLOATING_POINT:
|
|
69
|
+
return NumericType.FLOATING_POINT;
|
|
70
|
+
case NumberLiteralKind.DECIMAL:
|
|
71
|
+
return NumericType.DECIMAL;
|
|
72
|
+
default: {
|
|
73
|
+
const exhaustiveCheck: never = kind;
|
|
74
|
+
throw new InternalScannerError(
|
|
75
|
+
"Unreachable code reached, kind == " + exhaustiveCheck,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function resolveNumericType(
|
|
82
|
+
node: AbstractNode,
|
|
83
|
+
symbolTable: SymbolTable,
|
|
84
|
+
): NumericType | undefined {
|
|
85
|
+
if (isNumberLiteral(node)) {
|
|
86
|
+
return getNumericTypeFromNumberLiteralKind(node.numberLiteralKind);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (isIdentifier(node)) {
|
|
90
|
+
return resolveNumericTypeFromIdentifier(node, symbolTable);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (isAbstractExpression(node)) {
|
|
94
|
+
return resolveNumericTypeFromExpression(node, symbolTable);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
throw new InternalScannerError(
|
|
98
|
+
`Undexpected node kind: ${NodeKind[node.nodeKind]}`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveNumericTypeFromIdentifier(
|
|
103
|
+
identifier: Identifier,
|
|
104
|
+
symbolTable: SymbolTable,
|
|
105
|
+
): NumericType | undefined {
|
|
106
|
+
const symbol = symbolTable.lookupVariable(identifier.name);
|
|
107
|
+
|
|
108
|
+
if (symbol && (symbol.attributes.numericType !== undefined)) {
|
|
109
|
+
return symbol.attributes.numericType;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const classMembers = symbolTable.lookupClassMember(identifier.name);
|
|
113
|
+
|
|
114
|
+
// Use the first class member as they should all have the same type in different branches
|
|
115
|
+
if (classMembers && (classMembers.length > 0)) {
|
|
116
|
+
const memberSymbol = classMembers[0].symbol;
|
|
117
|
+
|
|
118
|
+
if (memberSymbol.attributes.numericType !== undefined) {
|
|
119
|
+
return memberSymbol.attributes.numericType;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Identifier is not defined, there will already be an SemanticError for this
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function resolveNumericTypeFromExpression(
|
|
128
|
+
expression: AbstractExpression,
|
|
129
|
+
symbolTable: SymbolTable,
|
|
130
|
+
): NumericType | undefined {
|
|
131
|
+
const kind = expression.expressionKind;
|
|
132
|
+
|
|
133
|
+
switch (kind) {
|
|
134
|
+
case ExpressionKind.BINARY:
|
|
135
|
+
return resolveBinaryExpressionType(
|
|
136
|
+
expression as BinaryExpression,
|
|
137
|
+
symbolTable,
|
|
138
|
+
);
|
|
139
|
+
case ExpressionKind.UNARY:
|
|
140
|
+
return resolveNumericType(
|
|
141
|
+
(expression as UnaryExpression).operand,
|
|
142
|
+
symbolTable,
|
|
143
|
+
);
|
|
144
|
+
case ExpressionKind.LENGTHOF:
|
|
145
|
+
return NumericType.INTEGER;
|
|
146
|
+
default: {
|
|
147
|
+
const exhaustiveCheck: never = kind;
|
|
148
|
+
throw new InternalScannerError(
|
|
149
|
+
"Unreachable code reached, kind == " + exhaustiveCheck,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function resolveBinaryExpressionType(
|
|
156
|
+
expression: BinaryExpression,
|
|
157
|
+
symbolTable: SymbolTable,
|
|
158
|
+
): NumericType | undefined {
|
|
159
|
+
const operatorKind = expression.binaryOperatorKind;
|
|
160
|
+
if (operatorKind === undefined) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (isRelationalOperator(operatorKind) || isLogicalOperator(operatorKind)) {
|
|
165
|
+
return NumericType.INTEGER;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (operatorKind === BinaryOperatorKind.ASSIGNMENT) {
|
|
169
|
+
return resolveNumericType(
|
|
170
|
+
expression.leftOperand as AbstractNode,
|
|
171
|
+
symbolTable,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const leftNumericType = resolveNumericType(
|
|
176
|
+
expression.leftOperand as AbstractNode,
|
|
177
|
+
symbolTable,
|
|
178
|
+
);
|
|
179
|
+
const rightNumericType = resolveNumericType(
|
|
180
|
+
expression.rightOperand as AbstractNode,
|
|
181
|
+
symbolTable,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
if (
|
|
185
|
+
(leftNumericType === NumericType.FLOATING_POINT) ||
|
|
186
|
+
(rightNumericType === NumericType.FLOATING_POINT)
|
|
187
|
+
) {
|
|
188
|
+
return NumericType.FLOATING_POINT;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (
|
|
192
|
+
(leftNumericType === NumericType.DECIMAL) ||
|
|
193
|
+
(rightNumericType === NumericType.DECIMAL)
|
|
194
|
+
) {
|
|
195
|
+
return NumericType.DECIMAL;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (
|
|
199
|
+
(leftNumericType === NumericType.INTEGER) ||
|
|
200
|
+
(rightNumericType === NumericType.INTEGER)
|
|
201
|
+
) {
|
|
202
|
+
return NumericType.INTEGER;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return leftNumericType || rightNumericType;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function isRelationalOperator(kind: BinaryOperatorKind): boolean {
|
|
209
|
+
return (kind === BinaryOperatorKind.LESS_THAN) ||
|
|
210
|
+
(kind === BinaryOperatorKind.LESS_THAN_OR_EQUAL) ||
|
|
211
|
+
(kind === BinaryOperatorKind.GREATER_THAN) ||
|
|
212
|
+
(kind === BinaryOperatorKind.GREATER_THAN_OR_EQUAL) ||
|
|
213
|
+
(kind === BinaryOperatorKind.EQUAL) ||
|
|
214
|
+
(kind === BinaryOperatorKind.NOT_EQUAL);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function isLogicalOperator(kind: BinaryOperatorKind): boolean {
|
|
218
|
+
return (kind === BinaryOperatorKind.LOGICAL_AND) ||
|
|
219
|
+
(kind === BinaryOperatorKind.LOGICAL_OR);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function isShiftOperator(kind: BinaryOperatorKind): boolean {
|
|
223
|
+
return (kind === BinaryOperatorKind.SHIFT_LEFT) ||
|
|
224
|
+
(kind === BinaryOperatorKind.SHIFT_RIGHT);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function isBitwiseOperator(kind: BinaryOperatorKind): boolean {
|
|
228
|
+
return (kind === BinaryOperatorKind.BITWISE_AND) ||
|
|
229
|
+
(kind === BinaryOperatorKind.BITWISE_OR);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export function isArithmeticOperator(kind: BinaryOperatorKind): boolean {
|
|
233
|
+
return (kind === BinaryOperatorKind.ADD) ||
|
|
234
|
+
(kind === BinaryOperatorKind.SUBTRACT) ||
|
|
235
|
+
(kind === BinaryOperatorKind.MULTIPLY) ||
|
|
236
|
+
(kind === BinaryOperatorKind.DIVIDE) ||
|
|
237
|
+
(kind === BinaryOperatorKind.MODULUS);
|
|
238
|
+
}
|