@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,626 @@
|
|
|
1
|
+
import type { AbstractArrayDimension } from "../../ast/node/abstract-array-dimension.ts";
|
|
2
|
+
import type { AbstractClassId } from "../../ast/node/abstract-class-id.ts";
|
|
3
|
+
import type { AbstractCompositeNode } from "../../ast/node/abstract-composite-node.ts";
|
|
4
|
+
import type { AbstractExpression } from "../../ast/node/abstract-expression.ts";
|
|
5
|
+
import type { AbstractLeafNode } from "../../ast/node/abstract-leaf-node.ts";
|
|
6
|
+
import type { AbstractStatement } from "../../ast/node/abstract-statement.ts";
|
|
7
|
+
import type { ClassDeclaration } from "../../ast/node/class-declaration.ts";
|
|
8
|
+
import { NodeKind } from "../../ast/node/enum/node-kind.ts";
|
|
9
|
+
import { StatementKind } from "../../ast/node/enum/statement-kind.ts";
|
|
10
|
+
import { TokenKind } from "../../ast/node/enum/token-kind.ts";
|
|
11
|
+
import type { ForStatement } from "../../ast/node/for-statement.ts";
|
|
12
|
+
import type { IfStatement } from "../../ast/node/if-statement.ts";
|
|
13
|
+
import type { MapDeclaration } from "../../ast/node/map-declaration.ts";
|
|
14
|
+
import type { SwitchStatement } from "../../ast/node/switch-statement.ts";
|
|
15
|
+
import type { Token } from "../../ast/node/token.ts";
|
|
16
|
+
import type { WhileStatement } from "../../ast/node/while-statement.ts";
|
|
17
|
+
import {
|
|
18
|
+
isCaseClause,
|
|
19
|
+
isDefaultClause,
|
|
20
|
+
isStatement,
|
|
21
|
+
} from "../../ast/util/types.ts";
|
|
22
|
+
import type { NodeHandler } from "../../ast/visitor/node-handler.ts";
|
|
23
|
+
import { SemanticError, SemanticWarning } from "../../scanner-error.ts";
|
|
24
|
+
import getLogger from "../../util/logger.ts";
|
|
25
|
+
import type { SymbolTable } from "../symbol-table.ts";
|
|
26
|
+
import { getRequiredIdentifier } from "../util/symbol-table-utils.ts";
|
|
27
|
+
|
|
28
|
+
const logger = getLogger("AbstractAnalysisNodeHandler");
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* This abstract class provides a base implementation for node handlers that analyze
|
|
32
|
+
* abstract syntax tree (AST) nodes. It implements the `NodeHandler` interface and
|
|
33
|
+
* provides default behaviour to handle error nodes and missing required values in
|
|
34
|
+
* either strict or lenient mode.
|
|
35
|
+
*
|
|
36
|
+
* Handlers for specific node kinds (and optional sub-kinds) can be registered using the `registerBeforeNodeHandler`
|
|
37
|
+
* and `registerAfterNodeHandler` methods, which will be called before and after visiting nodes of the specified kinds, respectively.
|
|
38
|
+
*
|
|
39
|
+
* In strict mode, encountering an unexpected error node or an error token will throw a `SemanticError`.
|
|
40
|
+
* In lenient mode, these nodes will be ignored, and a debug message will be logged.
|
|
41
|
+
*
|
|
42
|
+
* Support for adding implicit block scopes for if, switch, while and for statements is implemented
|
|
43
|
+
* by registering these nodes in implicitScopeNodes (if required) in implicitScopeNodes. The implicit scopes
|
|
44
|
+
* are then entered and left within beforeVisit() and afterVisit().
|
|
45
|
+
*/
|
|
46
|
+
export abstract class AbstractAnalysisNodeHandler implements NodeHandler {
|
|
47
|
+
public readonly semanticErrors: Array<SemanticError> = [];
|
|
48
|
+
public readonly semanticWarnings: Array<SemanticWarning> = [];
|
|
49
|
+
|
|
50
|
+
private handlersByNodeKind: Map<NodeKind, {
|
|
51
|
+
beforeVisit?: ((node: AbstractCompositeNode) => void)[];
|
|
52
|
+
afterVisit?: ((node: AbstractCompositeNode) => void)[];
|
|
53
|
+
}> = new Map();
|
|
54
|
+
|
|
55
|
+
private handlersByNodeKindAndSubKind: Map<string, {
|
|
56
|
+
beforeVisit?: ((node: AbstractCompositeNode) => void)[];
|
|
57
|
+
afterVisit?: ((node: AbstractCompositeNode) => void)[];
|
|
58
|
+
}> = new Map();
|
|
59
|
+
|
|
60
|
+
// Set of nodes that we encounter that should implicitly create a new scope
|
|
61
|
+
// - if statements with non-compound bodies
|
|
62
|
+
// - switch case clauses with non-compound bodies
|
|
63
|
+
// - switch default clause with non-compound body
|
|
64
|
+
// - while statements with non-compound bodies
|
|
65
|
+
// - for statements with non-compound bodies
|
|
66
|
+
private implicitScopeNodes: Set<AbstractCompositeNode> = new Set();
|
|
67
|
+
|
|
68
|
+
private subKindKey(nodeKind: NodeKind, subKind: number): string {
|
|
69
|
+
return `${nodeKind}:${subKind}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
constructor(
|
|
73
|
+
public readonly symbolTable: SymbolTable,
|
|
74
|
+
public readonly strict: boolean,
|
|
75
|
+
) {
|
|
76
|
+
// use our own beforeVisit and afterVisit implementations for node kinds with sub-kinds
|
|
77
|
+
// to dispatch to any registered handlers based on node kind and sub-kind
|
|
78
|
+
this.registerBeforeNodeHandler(NodeKind.STATEMENT, undefined, (node) => {
|
|
79
|
+
this.handleBeforeStatementKinds(node as AbstractStatement);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this.registerAfterNodeHandler(NodeKind.STATEMENT, undefined, (node) => {
|
|
83
|
+
this.handleAfterStatementKinds(node as AbstractStatement);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
this.registerBeforeNodeHandler(
|
|
87
|
+
NodeKind.ARRAY_DIMENSION,
|
|
88
|
+
undefined,
|
|
89
|
+
(node) => {
|
|
90
|
+
this.handleBeforeArrayDimensionKinds(node as AbstractArrayDimension);
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
this.registerAfterNodeHandler(
|
|
95
|
+
NodeKind.ARRAY_DIMENSION,
|
|
96
|
+
undefined,
|
|
97
|
+
(node) => {
|
|
98
|
+
this.handleAfterArrayDimensionKinds(node as AbstractArrayDimension);
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
this.registerBeforeNodeHandler(NodeKind.CLASS_ID, undefined, (node) => {
|
|
103
|
+
this.handleBeforeClassIdKinds(node as AbstractClassId);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
this.registerAfterNodeHandler(NodeKind.CLASS_ID, undefined, (node) => {
|
|
107
|
+
this.handleAfterClassIdKinds(node as AbstractClassId);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
this.registerBeforeNodeHandler(NodeKind.EXPRESSION, undefined, (node) => {
|
|
111
|
+
this.handleBeforeExpressionKinds(node as AbstractExpression);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
this.registerAfterNodeHandler(NodeKind.EXPRESSION, undefined, (node) => {
|
|
115
|
+
this.handleAfterExpressionKinds(node as AbstractExpression);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Implicit scope registration
|
|
119
|
+
|
|
120
|
+
this.registerBeforeNodeHandler(
|
|
121
|
+
NodeKind.STATEMENT,
|
|
122
|
+
StatementKind.IF,
|
|
123
|
+
(node) => this.registerIfStatementImplicitScopes(node as IfStatement),
|
|
124
|
+
);
|
|
125
|
+
this.registerBeforeNodeHandler(
|
|
126
|
+
NodeKind.STATEMENT,
|
|
127
|
+
StatementKind.SWITCH,
|
|
128
|
+
(node) =>
|
|
129
|
+
this.registerSwitchStatementImplicitScopes(node as SwitchStatement),
|
|
130
|
+
);
|
|
131
|
+
this.registerBeforeNodeHandler(
|
|
132
|
+
NodeKind.STATEMENT,
|
|
133
|
+
StatementKind.WHILE,
|
|
134
|
+
(node) =>
|
|
135
|
+
this.registerWhileStatementImplicitScopes(node as WhileStatement),
|
|
136
|
+
);
|
|
137
|
+
this.registerBeforeNodeHandler(
|
|
138
|
+
NodeKind.STATEMENT,
|
|
139
|
+
StatementKind.FOR,
|
|
140
|
+
(node) => this.registerForStatementImplicitScopes(node as ForStatement),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Scope enter
|
|
144
|
+
|
|
145
|
+
this.registerBeforeNodeHandler(
|
|
146
|
+
NodeKind.STATEMENT,
|
|
147
|
+
StatementKind.FOR,
|
|
148
|
+
(_node) =>
|
|
149
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.FOR]),
|
|
150
|
+
);
|
|
151
|
+
this.registerBeforeNodeHandler(
|
|
152
|
+
NodeKind.STATEMENT,
|
|
153
|
+
StatementKind.COMPOUND,
|
|
154
|
+
(_node) =>
|
|
155
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.COMPOUND]),
|
|
156
|
+
);
|
|
157
|
+
this.registerBeforeNodeHandler(
|
|
158
|
+
NodeKind.STATEMENT,
|
|
159
|
+
StatementKind.WHILE,
|
|
160
|
+
(_node) =>
|
|
161
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.WHILE]),
|
|
162
|
+
);
|
|
163
|
+
this.registerBeforeNodeHandler(
|
|
164
|
+
NodeKind.STATEMENT,
|
|
165
|
+
StatementKind.DO,
|
|
166
|
+
(_node) =>
|
|
167
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.DO]),
|
|
168
|
+
);
|
|
169
|
+
this.registerBeforeNodeHandler(
|
|
170
|
+
NodeKind.STATEMENT,
|
|
171
|
+
StatementKind.SWITCH,
|
|
172
|
+
(_node) =>
|
|
173
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.SWITCH]),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
this.registerBeforeNodeHandler(
|
|
177
|
+
NodeKind.STATEMENT,
|
|
178
|
+
StatementKind.CLASS_DECLARATION,
|
|
179
|
+
(node) => this.handleBeforeClassDeclaration(node as ClassDeclaration),
|
|
180
|
+
);
|
|
181
|
+
this.registerBeforeNodeHandler(
|
|
182
|
+
NodeKind.STATEMENT,
|
|
183
|
+
StatementKind.MAP_DECLARATION,
|
|
184
|
+
(node) => this.handleBeforeMapDeclaration(node as MapDeclaration),
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
// Scope exit
|
|
188
|
+
|
|
189
|
+
this.registerAfterNodeHandler(
|
|
190
|
+
NodeKind.STATEMENT,
|
|
191
|
+
StatementKind.COMPOUND,
|
|
192
|
+
() => this.symbolTable.exitScope(),
|
|
193
|
+
);
|
|
194
|
+
this.registerAfterNodeHandler(
|
|
195
|
+
NodeKind.STATEMENT,
|
|
196
|
+
StatementKind.CLASS_DECLARATION,
|
|
197
|
+
() => this.symbolTable.exitScope(),
|
|
198
|
+
);
|
|
199
|
+
this.registerAfterNodeHandler(
|
|
200
|
+
NodeKind.STATEMENT,
|
|
201
|
+
StatementKind.MAP_DECLARATION,
|
|
202
|
+
() => this.symbolTable.exitScope(),
|
|
203
|
+
);
|
|
204
|
+
this.registerAfterNodeHandler(
|
|
205
|
+
NodeKind.STATEMENT,
|
|
206
|
+
StatementKind.FOR,
|
|
207
|
+
() => this.symbolTable.exitScope(),
|
|
208
|
+
);
|
|
209
|
+
this.registerAfterNodeHandler(
|
|
210
|
+
NodeKind.STATEMENT,
|
|
211
|
+
StatementKind.WHILE,
|
|
212
|
+
() => this.symbolTable.exitScope(),
|
|
213
|
+
);
|
|
214
|
+
this.registerAfterNodeHandler(
|
|
215
|
+
NodeKind.STATEMENT,
|
|
216
|
+
StatementKind.DO,
|
|
217
|
+
() => this.symbolTable.exitScope(),
|
|
218
|
+
);
|
|
219
|
+
this.registerAfterNodeHandler(
|
|
220
|
+
NodeKind.STATEMENT,
|
|
221
|
+
StatementKind.SWITCH,
|
|
222
|
+
() => this.symbolTable.exitScope(),
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private handleBeforeClassDeclaration(
|
|
227
|
+
classDeclaration: ClassDeclaration,
|
|
228
|
+
): void {
|
|
229
|
+
const identifier = getRequiredIdentifier(
|
|
230
|
+
classDeclaration.identifier,
|
|
231
|
+
classDeclaration,
|
|
232
|
+
this.strict,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
if (!identifier) {
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.symbolTable.enterClassScope(identifier.name);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private handleBeforeMapDeclaration(mapDeclaration: MapDeclaration): void {
|
|
243
|
+
const identifier = getRequiredIdentifier(
|
|
244
|
+
mapDeclaration.identifier,
|
|
245
|
+
mapDeclaration,
|
|
246
|
+
this.strict,
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
if (!identifier) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
this.symbolTable.enterMapScope(identifier.name);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private handleBeforeStatementKinds(node: AbstractStatement): void {
|
|
257
|
+
const key = this.subKindKey(node.nodeKind, node.statementKind);
|
|
258
|
+
if (
|
|
259
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
260
|
+
) {
|
|
261
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
262
|
+
|
|
263
|
+
if (handlers && handlers.beforeVisit) {
|
|
264
|
+
for (const handler of handlers.beforeVisit) {
|
|
265
|
+
handler(node);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private handleAfterStatementKinds(node: AbstractStatement): void {
|
|
272
|
+
const key = this.subKindKey(node.nodeKind, node.statementKind);
|
|
273
|
+
if (
|
|
274
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
275
|
+
) {
|
|
276
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
277
|
+
|
|
278
|
+
if (handlers && handlers.afterVisit) {
|
|
279
|
+
for (const handler of handlers.afterVisit) {
|
|
280
|
+
handler(node);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private handleBeforeArrayDimensionKinds(node: AbstractArrayDimension): void {
|
|
287
|
+
const key = this.subKindKey(node.nodeKind, node.arrayDimensionKind);
|
|
288
|
+
if (
|
|
289
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
290
|
+
) {
|
|
291
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
292
|
+
|
|
293
|
+
if (handlers && handlers.beforeVisit) {
|
|
294
|
+
for (const handler of handlers.beforeVisit) {
|
|
295
|
+
handler(node);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private handleAfterArrayDimensionKinds(node: AbstractArrayDimension): void {
|
|
302
|
+
const key = this.subKindKey(node.nodeKind, node.arrayDimensionKind);
|
|
303
|
+
if (
|
|
304
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
305
|
+
) {
|
|
306
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
307
|
+
|
|
308
|
+
if (handlers && handlers.afterVisit) {
|
|
309
|
+
for (const handler of handlers.afterVisit) {
|
|
310
|
+
handler(node);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private handleBeforeClassIdKinds(node: AbstractClassId): void {
|
|
317
|
+
const key = this.subKindKey(node.nodeKind, node.classIdKind);
|
|
318
|
+
if (
|
|
319
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
320
|
+
) {
|
|
321
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
322
|
+
|
|
323
|
+
if (handlers && handlers.beforeVisit) {
|
|
324
|
+
for (const handler of handlers.beforeVisit) {
|
|
325
|
+
handler(node);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private handleAfterClassIdKinds(node: AbstractClassId): void {
|
|
332
|
+
const key = this.subKindKey(node.nodeKind, node.classIdKind);
|
|
333
|
+
if (
|
|
334
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
335
|
+
) {
|
|
336
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
337
|
+
|
|
338
|
+
if (handlers && handlers.afterVisit) {
|
|
339
|
+
for (const handler of handlers.afterVisit) {
|
|
340
|
+
handler(node);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
private handleBeforeExpressionKinds(node: AbstractExpression): void {
|
|
347
|
+
const key = this.subKindKey(node.nodeKind, node.expressionKind);
|
|
348
|
+
if (
|
|
349
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
350
|
+
) {
|
|
351
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
352
|
+
|
|
353
|
+
if (handlers && handlers.beforeVisit) {
|
|
354
|
+
for (const handler of handlers.beforeVisit) {
|
|
355
|
+
handler(node);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private handleAfterExpressionKinds(node: AbstractExpression): void {
|
|
362
|
+
const key = this.subKindKey(node.nodeKind, node.expressionKind);
|
|
363
|
+
if (
|
|
364
|
+
this.handlersByNodeKindAndSubKind.has(key)
|
|
365
|
+
) {
|
|
366
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
367
|
+
|
|
368
|
+
if (handlers && handlers.afterVisit) {
|
|
369
|
+
for (const handler of handlers.afterVisit) {
|
|
370
|
+
handler(node);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
private registerIfStatementImplicitScopes(ifStatement: IfStatement): void {
|
|
377
|
+
if (isStatement(ifStatement.ifStatement)) {
|
|
378
|
+
const ifNode = ifStatement.ifStatement as AbstractStatement;
|
|
379
|
+
|
|
380
|
+
if (
|
|
381
|
+
(ifNode.statementKind !== StatementKind.IF) &&
|
|
382
|
+
(ifNode.statementKind !== StatementKind.COMPOUND)
|
|
383
|
+
) {
|
|
384
|
+
this.implicitScopeNodes.add(ifNode);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (isStatement(ifStatement.elseStatement)) {
|
|
389
|
+
const elseNode = ifStatement.elseStatement as AbstractStatement;
|
|
390
|
+
|
|
391
|
+
if (
|
|
392
|
+
(elseNode.statementKind !== StatementKind.IF) &&
|
|
393
|
+
(elseNode.statementKind !== StatementKind.COMPOUND)
|
|
394
|
+
) {
|
|
395
|
+
this.implicitScopeNodes.add(elseNode);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private registerSwitchStatementImplicitScopes(
|
|
401
|
+
switchStatement: SwitchStatement,
|
|
402
|
+
): void {
|
|
403
|
+
for (const caseClause of switchStatement.caseClauses) {
|
|
404
|
+
if (isCaseClause(caseClause)) {
|
|
405
|
+
this.implicitScopeNodes.add(caseClause);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (isDefaultClause(switchStatement.defaultClause)) {
|
|
410
|
+
this.implicitScopeNodes.add(switchStatement.defaultClause);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private registerWhileStatementImplicitScopes(
|
|
415
|
+
whileStatement: WhileStatement,
|
|
416
|
+
): void {
|
|
417
|
+
if (isStatement(whileStatement.statement)) {
|
|
418
|
+
const ifNode = whileStatement.statement as AbstractStatement;
|
|
419
|
+
|
|
420
|
+
if (ifNode.statementKind !== StatementKind.COMPOUND) {
|
|
421
|
+
this.implicitScopeNodes.add(ifNode);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
private registerForStatementImplicitScopes(forStatement: ForStatement): void {
|
|
427
|
+
if (isStatement(forStatement.statement)) {
|
|
428
|
+
const ifNode = forStatement.statement as AbstractStatement;
|
|
429
|
+
|
|
430
|
+
if (ifNode.statementKind !== StatementKind.COMPOUND) {
|
|
431
|
+
this.implicitScopeNodes.add(ifNode);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
protected registerBeforeNodeHandler(
|
|
437
|
+
nodeKind: NodeKind,
|
|
438
|
+
subKind: number | undefined,
|
|
439
|
+
handler: (node: AbstractCompositeNode) => void,
|
|
440
|
+
): void {
|
|
441
|
+
if (subKind !== undefined) {
|
|
442
|
+
const key = this.subKindKey(nodeKind, subKind);
|
|
443
|
+
|
|
444
|
+
if (!this.handlersByNodeKindAndSubKind.has(key)) {
|
|
445
|
+
this.handlersByNodeKindAndSubKind.set(key, {});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
449
|
+
|
|
450
|
+
if (handlers) {
|
|
451
|
+
if (!handlers.beforeVisit) {
|
|
452
|
+
handlers.beforeVisit = [];
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Special case for class and declarations:
|
|
456
|
+
// The scope needs to be entered AFTER any sub-class implementation
|
|
457
|
+
// but it cannot be done via registerAfterNodeHandler as the child elements
|
|
458
|
+
// have been processed by then.
|
|
459
|
+
|
|
460
|
+
if (
|
|
461
|
+
(nodeKind === NodeKind.STATEMENT) &&
|
|
462
|
+
((subKind === StatementKind.CLASS_DECLARATION) ||
|
|
463
|
+
(subKind === StatementKind.MAP_DECLARATION))
|
|
464
|
+
) {
|
|
465
|
+
handlers.beforeVisit.unshift(handler);
|
|
466
|
+
} else {
|
|
467
|
+
handlers.beforeVisit.push(handler);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
if (!this.handlersByNodeKind.has(nodeKind)) {
|
|
472
|
+
this.handlersByNodeKind.set(nodeKind, {});
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const handlers = this.handlersByNodeKind.get(nodeKind);
|
|
476
|
+
|
|
477
|
+
if (handlers) {
|
|
478
|
+
if (!handlers.beforeVisit) {
|
|
479
|
+
handlers.beforeVisit = [];
|
|
480
|
+
}
|
|
481
|
+
handlers.beforeVisit.push(handler);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
protected registerAfterNodeHandler(
|
|
487
|
+
nodeKind: NodeKind,
|
|
488
|
+
subKind: number | undefined,
|
|
489
|
+
handler: (node: AbstractCompositeNode) => void,
|
|
490
|
+
): void {
|
|
491
|
+
if (subKind !== undefined) {
|
|
492
|
+
const key = this.subKindKey(nodeKind, subKind);
|
|
493
|
+
|
|
494
|
+
if (!this.handlersByNodeKindAndSubKind.has(key)) {
|
|
495
|
+
this.handlersByNodeKindAndSubKind.set(key, {});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const handlers = this.handlersByNodeKindAndSubKind.get(key);
|
|
499
|
+
|
|
500
|
+
if (handlers) {
|
|
501
|
+
if (!handlers.afterVisit) {
|
|
502
|
+
handlers.afterVisit = [];
|
|
503
|
+
}
|
|
504
|
+
handlers.afterVisit.push(handler);
|
|
505
|
+
}
|
|
506
|
+
} else {
|
|
507
|
+
if (!this.handlersByNodeKind.has(nodeKind)) {
|
|
508
|
+
this.handlersByNodeKind.set(nodeKind, {});
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const handlers = this.handlersByNodeKind.get(nodeKind);
|
|
512
|
+
|
|
513
|
+
if (handlers) {
|
|
514
|
+
if (!handlers.afterVisit) {
|
|
515
|
+
handlers.afterVisit = [];
|
|
516
|
+
}
|
|
517
|
+
handlers.afterVisit.push(handler);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* If the node is an unexpected node, throw an error in strict mode or ignore in lenient mode.
|
|
524
|
+
*
|
|
525
|
+
* @param node the leaf node to visit
|
|
526
|
+
*/
|
|
527
|
+
|
|
528
|
+
beforeVisit(node: AbstractCompositeNode): void {
|
|
529
|
+
if (node.nodeKind === NodeKind.UNEXPECTED_ERROR) {
|
|
530
|
+
if (this.strict) {
|
|
531
|
+
throw new SemanticError(
|
|
532
|
+
"UNEXPECTED_ERROR node encountered",
|
|
533
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// In lenient mode, we simply ignore the unexpected error node
|
|
538
|
+
logger.debug("Ignoring UNEXPECTED_ERROR node in lenient mode.");
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Enter any implicit scopes for this node
|
|
542
|
+
if (this.implicitScopeNodes.has(node)) {
|
|
543
|
+
this.symbolTable.enterBlockScope(StatementKind[StatementKind.COMPOUND]);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (this.handlersByNodeKind.has(node.nodeKind)) {
|
|
547
|
+
const handlers = this.handlersByNodeKind.get(node.nodeKind);
|
|
548
|
+
|
|
549
|
+
if (handlers && handlers.beforeVisit) {
|
|
550
|
+
for (const handler of handlers.beforeVisit) {
|
|
551
|
+
handler(node);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* If the node is an error token or unexpected node, throw an error in strict mode or ignore in lenient mode.
|
|
559
|
+
*
|
|
560
|
+
* @param node the leaf node to visit
|
|
561
|
+
*/
|
|
562
|
+
visit(node: AbstractLeafNode): void {
|
|
563
|
+
if (node.nodeKind === NodeKind.UNEXPECTED_ERROR) {
|
|
564
|
+
if (this.strict) {
|
|
565
|
+
throw new SemanticError(
|
|
566
|
+
"UNEXPECTED_ERROR node encountered",
|
|
567
|
+
node.leadingTrivia ? node.leadingTrivia[0].location : undefined,
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// In lenient mode, we simply ignore the unexpected error node
|
|
572
|
+
logger.debug("Ignoring UNEXPECTED_ERROR node in lenient mode.");
|
|
573
|
+
|
|
574
|
+
return;
|
|
575
|
+
} else if (node.nodeKind === NodeKind.TOKEN) {
|
|
576
|
+
const token = node as Token;
|
|
577
|
+
|
|
578
|
+
if (token.tokenKind === TokenKind.ERROR_UNKNOWN_TOKEN) {
|
|
579
|
+
if (this.strict) {
|
|
580
|
+
throw new SemanticError(
|
|
581
|
+
"ERROR_UNKNOWN_TOKEN encountered",
|
|
582
|
+
token.getLocation(),
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// In lenient mode, we simply ignore the ERROR_UNKNOWN_TOKEN
|
|
587
|
+
logger.debug("Ignoring ERROR_UNKNOWN_TOKEN in lenient mode.");
|
|
588
|
+
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (token.tokenKind === TokenKind.ERROR_MISSING_TOKEN) {
|
|
593
|
+
if (this.strict) {
|
|
594
|
+
throw new SemanticError(
|
|
595
|
+
"ERROR_MISSING_TOKEN encountered",
|
|
596
|
+
token.getLocation(),
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// In lenient mode, we simply ignore the ERROR_MISSING_TOKEN
|
|
601
|
+
logger.debug("Ignoring ERROR_MISSING_TOKEN in lenient mode.");
|
|
602
|
+
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Leaf nodes do not need to be visited further for analysis
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
afterVisit(node: AbstractCompositeNode): void {
|
|
611
|
+
if (this.handlersByNodeKind.has(node.nodeKind)) {
|
|
612
|
+
const handlers = this.handlersByNodeKind.get(node.nodeKind);
|
|
613
|
+
|
|
614
|
+
if (handlers && handlers.afterVisit) {
|
|
615
|
+
for (const handler of handlers.afterVisit) {
|
|
616
|
+
handler(node);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Exit any implicit scopes we entered for this node
|
|
622
|
+
if (this.implicitScopeNodes.has(node)) {
|
|
623
|
+
this.symbolTable.exitScope();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|