Trailing Comments

February 23, 2021

Here is our solution, which puts a trailing comment on each line of code:

(define (tc? str)     ; true when a trailing comment is found, else false
   (let loop ((xs (string->list str)) (inquotes #f))     ; initialize loop
     (cond ((null? xs) #f)           ; reached end-of-line without comment
           ((and inquotes (char=? (car xs) #\"))            ; end of quote
             (loop (cdr xs) #f))       ; initialize for next quoted string
           ((and inquotes (char=? (car xs) #\) (pair? (cdr xs))) ; escape
             (loop (cddr xs) #t))   ; skip backslash and escaped character
           (inquotes (loop (cdr xs) #t))                  ; continue quote
           ((char=? (car xs) #\") (loop (cdr xs) #t))        ; start quote
           ((char=? (car xs) ##) #t)             ; found trailing comment
           (else (loop (cdr xs) #f)))))                   ; next character

And here are the three samples, which must be ugly to satisfy Scheme’s quoting rules:

   (tc? "x = \"# This is fine\"")
   f
   (tc? "\"This \# is fine too\"")
   f
   (tc? "x = \"\" # This is not\"")
   t 

You can run the program at https://ideone.com/AzDwgg

Pages: 1 2

6 Responses to “Trailing Comments”

  1. Daniel said

    @programmingpraxis, I believe the solution you posted considers full comment lines (those starting with a “#”, possibly preceded by whitespace) as trailing comments. For example, the line # comment would seemingly be counted as a trailing comment. Have I interpreted your code correctly, and should there be a distinction between 1) full comment lines and 2) lines that have code followed by a comment? I’ve assumed that a trailing comment detector would only detect the latter.

    Here’s a solution in Python, which takes a Python file as input and outputs the line numbers with trailing comments. I’ve utilized Python’s built-in tokenize module. This accommodates comment markers in either single or double quoted strings, and also handles trailing comments that occur at the end of multi-line strings after the triple quotes.

    trailing_comments.py
    
    import sys
    import tokenize
    
    assert len(sys.argv) == 2
    
    with tokenize.open(sys.argv[1]) as f:
        line = -1
        tokens = tokenize.generate_tokens(f.readline)
        for token in tokens:
            # A trailing comment is a comment token that starts on the same line that the
            # preceding token ended on.
            if token.type == tokenize.COMMENT and token.start[0] == line:
                print(line)
            line = token.end[0]
    

    Example usage:

    example.py
    

    [sourcode lang=”text”]
    x = ‘# this is not a trailing comment’
    “this # is not part of a trailing comment”
    x = “” # this is a trailing comment

    this is not (full comment line)

    x = “””
    :-) # this multi-line string text is not part of a trailing comment
    “”” # this text is
    [/sourcecode]

    [sourcode lang=”text”]
    $ python3 trailing_comments.py example.py
    [/sourcecode]

    Output:

    3
    7
    
  2. Daniel said

    I misspelled “sourcecode” in my example usage. Here’s another attempt.

    Example usage:

    example.py
    

    x = ‘# this is not a trailing comment’
    "this # is not part of a trailing comment"
    x = "" # this is a trailing comment
    # this is not (full comment line)
    x = """
    :-) # this multi-line string text is not part of a trailing comment
    """ # this text is

    $ python3 trailing_comments.py example.py

    Output:

    3
    7
    
  3. Daniel said

    Another attempt.

    example.py
    

    x = ‘# this is not a trailing comment’
    "this # is not part of a trailing comment"
    x = "" # this is a trailing comment
    # this is not (full comment line)
    x = """
    :-) # this multi-line string text is not part of a trailing comment
    """ # this text is

    $ python3 trailing_comments.py example.py

    Output:

    3
    7
    
  4. Daniel said

    A last attempt to correct formatting of my example usage.

    example.py
    
    x = '# this is not a trailing comment'
    "this # is not part of a trailing comment"
    x = ""  # this is a trailing comment
    # this is not (full comment line)
    x = """
    :-)  # this multi-line string text is not part of a trailing comment
    """ # this text is
    
    $ python3 trailing_comments.py example.py
    

    Output:

    3
    7
    
  5. Kevin said

    A solution in Racket:

    (define (trailing-comments path)
      (define shebang "#!")
      (let next ((lines (port->lines (open-input-file path))) (count 1) (out null))
        (if (null? lines)
            (display (~a "lines: " (if (null? out) "(none)" (string-join (map number->string (reverse out))))))
            (let ((line (car lines)))
              (let ((chars (reverse (string->list (if (and (= count 1) (string-prefix? line shebang)) (string-trim line shebang #:right? #f) line)))))
                (let ((icomm (index-of chars #\#)) (iquot (index-of chars #\")))
                  (next (cdr lines) (add1 count) (if (and icomm (or (not iquot) (< icomm iquot))) (cons count out) out))))))))
    

    Test source code file, trailing-comments.py:

    #!/usr/bin/env python
    
    # comments start with the octothorpe
    x = "But having one in a string, like this: #, doesn't count."
    "This one: \#, doesn't count either."
    
    # user input
    Fahrenheit = int(raw_input("Enter a temperature in Fahrenheit: "))
    Celsius = (Fahrenheit - 32) * 5.0/9.0 # convert to celsius
    print "Temperature:", Fahrenheit, "Fahrenheit = ", Celsius, " C"
    

    Testing:

    > (trailing-comments "trailing-comments.py")
    lines: 3 7 9
    
  6. Zack said

    Here is my take on this using Julia 1.5: https://pastebin.com/afzBbauw

    This solution works with a single line, but it’s not too difficult to adapt it to run on a whole program. Cheers

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: