abaplint implements a custom ABAP parser and other language related topics like scoping and syntax check.
This document describes the overall design of abaplint, and aim to persist design decisions and help new developers into the code-base.
left to right direction skinparam monochrome true frame "@abaplint/abaplint" as abaplint rectangle "3rd Party Tooling" as tooling tooling --> abaplint rectangle "vscode-abaplint" as vscode vscode --> abaplint rectangle "abaplint-cloud-foundry" as cf cf --> abaplint frame "@abaplint/cli" as cli cli --> abaplint rectangle "CI Tooling" as ci ci --> abaplint ci -left-> cli frame "@abaplint/transpiler" as transpiler abaplint -down-> transpiler frame "@abaplint/runtime" as runtime transpiler --> runtime rectangle "Serverless Tooling" as serverless serverless -left-> transpiler serverless -left-> runtime
The Registry is the main entry point to abaplint, files are added to the registry which then are mapped to objects, and the registry also keeps track of the configuration.
skinparam monochrome true rectangle "Registry" as registry usecase object1 usecase object2 registry -down-> object1 registry -down-> object2 rectangle "Configuration" as config registry -down-> config usecase file1 usecase file2 usecase file3 usecase file4 object1 -down-> file1 object1 -down-> file2 object2 -down-> file3 object2 -down-> file4
left to right direction skinparam monochrome true package "@abaplint/abaplint" as abaplint { rectangle "Lexer" as lexer rectangle "Statement Parser" as statement_parser rectangle "Structure Parser" as structure_parser rectangle "Object Information" as object_information rectangle "Syntax & Scoping" as syntax rectangle "Rules" as rules rectangle "Downport (WIP)" as downport rectangle "Quick fixes (WIP)" as quick_fixes rectangle "LSP" as lsp lexer -left-> statement_parser statement_parser -left-> structure_parser structure_parser -left-> object_information object_information -left-> syntax syntax -left-> rules lexer -[hidden]-> downport statement_parser -[hidden]-> quick_fixes structure_parser -[hidden]-> lsp }
-
immutable ⇒ possible multi-threading and structure
-
output of each stage is simple classes or interfaced making it simple typed, limiting cyclic dependencies
-
avoid cyclic dependencies, each step can use the previous, use interfaces
DO 5 TIMES.
WRITE 'hello'.
ENDDO.
Based on rules, the string is split into tokens,
skinparam monochrome true usecase "DO" as token1 usecase "5" as token2 usecase "TIMES" as token3 usecase "." as token4 usecase "WRITE" as token5 usecase "'hello'" as token6 usecase "." as token7 usecase "ENDDO" as token8 usecase "." as token9
Categorizes tokens into statements
skinparam monochrome true usecase "ENDDO" as token8 usecase "." as token9 rectangle "Statement ENDDO" as enddo token8 <-up- enddo token9 <-up- enddo usecase "WRITE" as token5 usecase "'hello'" as token6 usecase "." as token7 rectangle "Statement WRITE" as write token5 <-up- write token6 <-up- write token7 <-up- write usecase "DO" as token1 usecase "5" as token2 usecase "TIMES" as token3 usecase "." as token4 rectangle "Statement DO" as do token1 <-up- do token2 <-up- do token3 <-up- do token4 <-up- do
Not completely correct, but the idea…
skinparam monochrome true usecase "ENDDO" as token8 usecase "." as token9 rectangle "Statement ENDDO" as enddo token8 <-up- enddo token9 <-up- enddo usecase "WRITE" as token5 usecase "'hello'" as token6 usecase "." as token7 rectangle "Statement WRITE" as write token5 <-up- write token6 <-up- write token7 <-up- write usecase "DO" as token1 usecase "5" as token2 usecase "TIMES" as token3 usecase "." as token4 rectangle "Statement DO" as do token1 <-up- do token2 <-up- do token3 <-up- do token4 <-up- do collections "Structure DO" as sdo do <-up- sdo write <-up- sdo enddo <-up- sdo
-
CALL FUNCTION EXCEPTIONS must be well formed
-
Macros are only scoped to current file, current workaround is adding the constants to
abaplint.json
, and are not expanded -
Identifieres with dashes as last character "variable-" does not work well