en:pfw:multiline-comments
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
en:pfw:multiline-comments [2023-09-04 18:17] – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | en:pfw:multiline-comments [2025-02-22 14:15] (current) – albert | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | {{pfw: | ||
+ | ===== Multiline comment using (* *) ===== | ||
+ | |||
+ | uho 2022-01-20 | ||
+ | |||
+ | < | ||
+ | Usage: | ||
+ | (* Start a comment. | ||
+ | Spans multiple lines. | ||
+ | ends at *) | ||
+ | </ | ||
+ | |||
+ | ===== Idea ===== | ||
+ | |||
+ | Standard Forth provides words to add comments to programs: | ||
+ | |||
+ | * '' | ||
+ | In principle these comments can span multiple lines (the '' | ||
+ | * '' | ||
+ | |||
+ | As Forth is extensible it is possible to define additional comment words. Many flavours are possible. Here we focus on Pascal like comments using '' | ||
+ | |||
+ | So we seek to define an new word ´(*` that skips the source text until it finds the end of comment. | ||
+ | |||
+ | Because the Forth input stream might only consist of the current line, this word '' | ||
+ | |||
+ | ===== Nested comments ===== | ||
+ | |||
+ | Sometimes you might want to comment parts of the source text that contains comments themselves. If comments nest, i.e. you can have comments inside comments, then this is possible without further issues. If however only a naive search for the next '' | ||
+ | |||
+ | < | ||
+ | (* outer comment | ||
+ | (* inner comment *) | ||
+ | still comment if comments can nest, but not a comment if they don't nest. | ||
+ | *) probably error when not nesting as *) is typically not a defined word. | ||
+ | </ | ||
+ | |||
+ | ===== Pseudo code ===== | ||
+ | |||
+ | === Naive implementation (non-nested) === | ||
+ | |||
+ | < | ||
+ | Function: (* ( -- ) | ||
+ | - Parse the rest of the input stream searching for *) | ||
+ | - If *) is found then end searching | ||
+ | - If *) is not found within the available source text, | ||
+ | load more source text and continue search. | ||
+ | </ | ||
+ | |||
+ | Using this algorithm, skipping text stops at the first occurance of '' | ||
+ | |||
+ | === Implementation with nested comments === | ||
+ | |||
+ | < | ||
+ | Function: (* ( -- ) | ||
+ | - Parse the rest of the input stream searching for *) | ||
+ | - If the current *) is found then end this searching and resume any delayed searches. | ||
+ | - If another (* is encountered then delay the search of the current *) | ||
+ | and start the search for another *). | ||
+ | - If *) is not found within the available source text, | ||
+ | load more source text and continue search. | ||
+ | </ | ||
+ | |||
+ | Using this algorithm the number of nested comments is counted by the number of delayed searches. | ||
+ | |||
+ | ===== Implementation ===== | ||
+ | |||
+ | A naive non nesting Forth-94 implementation may look like this: | ||
+ | |||
+ | < | ||
+ | : (* ( -- ) | ||
+ | BEGIN | ||
+ | BEGIN | ||
+ | cr bl word count dup \ next token available? | ||
+ | WHILE ( c-addr u ) | ||
+ | | ||
+ | REPEAT 2drop | ||
+ | refill 0= \ read more source code | ||
+ | UNTIL ; immediate | ||
+ | </ | ||
+ | |||
+ | A version that allows for nesting comments: | ||
+ | |||
+ | <code forth> | ||
+ | : (* ( -- ) | ||
+ | BEGIN | ||
+ | | ||
+ | | ||
+ | WHILE ( c-addr u ) | ||
+ | 2dup s" *)" compare 0= IF 2drop EXIT THEN \ stop if end of comment found | ||
+ | | ||
+ | | ||
+ | | ||
+ | UNTIL ; immediate | ||
+ | </ | ||
+ | |||
+ | Both implementations will extract tokens from the input stream. Thus both '' | ||
+ | |||
+ | < | ||
+ | (* this does not end the comment*) but this does *) | ||
+ | </ | ||
+ | |||
+ | In practice that does not impose serious limitations. | ||
+ | |||
+ | ===== Standard conformant labeling ===== | ||
+ | |||
+ | This is an ANS Forth Program with environmental dependencies, | ||
+ | |||
+ | * Requiring WORD WHILE UNTIL THEN REPEAT IF EXIT DUP COUNT BL BEGIN ; : 2DROP 0= S" ( from the Core word set. | ||
+ | * Requiring from the Core Extensions word set. | ||
+ | * Requiring REFILL from the File Access Extensions word set. | ||
+ | * Requiring COMPARE from the String word set. | ||
+ | |||
+ | ==== Required program documentation ==== | ||
+ | |||
+ | This program has the environmental dependencies to use lower case for standard definition. After loading this program, a Standard System still exists. | ||
+ | |||
+ | ===== Test ===== | ||
+ | |||
+ | The test for handling nested comments: | ||
+ | |||
+ | <code forth> | ||
+ | (* .( Start of outer comment ) | ||
+ | |||
+ | | ||
+ | .( inner comment ) | ||
+ | *) | ||
+ | |||
+ | .( This should not print if comments nest! ) | ||
+ | |||
+ | *) | ||
+ | </ | ||
+ | |||
+ | should not print anything. | ||
+ | |||
+ | < | ||
+ | |||
+ | If you face a resource constraint system you might want to further simplify the definition of '' | ||
+ | |||
+ | '' | ||
+ | |||
+ | The use of '' | ||
+ | |||
+ | Here is Albert Nijhof' | ||
+ | |||
+ | < | ||
+ | \ Tool - Multi-line comment - an 17jan2022 | ||
+ | \ (* starts a multi-line comment. Not nestable. | ||
+ | \ The delimiter | ||
+ | |||
+ | : (* ( -- ) | ||
+ | | ||
+ | begin begin begin drop | ||
+ | | ||
+ | bl word | ||
+ | | ||
+ | count [char] * = until | ||
+ | count [char] ) = until | ||
+ | drop ; immediate | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | 1. This simple code was intended for small systems. That's why I avoided the word '' | ||
+ | 2. The delimiter '' | ||
+ | '' | ||
+ | |||
+ | Compare this with: | ||
+ | |||
+ | '' | ||
+ | 1. This simple code was intended for small systems. That's why I avoided the word '' | ||
+ | 2. The delimiter '' | ||
+ | '' | ||
+ | |||
+ | This code has some interesting properties: | ||
+ | |||
+ | * It uses a character based comparison to detect '' | ||
+ | * It uses 3 nested BEGIN UNTIL loops to iterate the input stream.\\ | ||
+ | Each UNTIL has a condition | ||
+ | * the length of the parse word is 2 | ||
+ | * the first character is the character ' | ||
+ | * the second character is the character ' | ||
+ | |||
+ | * Only if all of the UNTIL conditions are met (first AND second AND third) the nested loops end, otherwise they branch back to one of the BEGINs and keep parsing the next line of the input stream. Essentially the code inspects the first token on each line (possible with leading white space). | ||
+ | * When testing the UNTIL conditions the address of the next character is left over on the stack and needs to be dropped somewhere.\\ | ||
+ | The code does this at the // | ||
+ | The address also must be dropped when all UNTIL conditions are satisfied, i.e. when '' | ||