# Assembled with the script 'compile.pss' 
start:

#
#ABOUT 
#
# Show bash functions in a file and the descriptive comments 
# above them.
#
# I often write comments above bash functions to explain what they do.
# These can be multiple lines and may even have blank lines in them
# of before the function name. The following script uses a line-by-line
# parsing technique with the nom nom://until command to concatenate the 
# comments and associate them with the bash function name which follows
# them. This is the sort of example that becomes tricky with [sed] 
# because there is multiline recognition taking place.
#
# Adding the line* parse token below (which is any not 'function' bash
# statement) complicates the grammar but is necessary because other 
# wise every comment above a function name will be regarded as pertaining
# to that function.
#
#NOTES
#
#  This [nom] script obviously doesn't completely parse bash syntax. 
#  Just # comments and function names in a pretty 'maybe-just-good-enough'
#  sort of way.
#
#HISTORY 
#
#  1 march 2025
#    created this script in nomlang.org/doc/scripts/nom.linebyline.txt
#    as an example. It seems to work ok.
#
#
# print bash function names and comments above them 
# just ignore empty lines
until "\n"
testclass [:space:]
jumpfalse block.end.1214
  clear
block.end.1214:
testis ""
jumptrue block.end.1809
  put
  # remove upto 5 leading/trailing spaces, a bit primitive, 
  # or parse with whilenot [\n] etc
  testbegins "  "
  jumpfalse block.end.1355
    clop
    clop
  block.end.1355:
  testbegins "  "
  jumpfalse block.end.1377
    clop
    clop
  block.end.1377:
  testbegins " "
  jumpfalse block.end.1392
    clip
  block.end.1392:
  testends "  "
  jumpfalse block.end.1417
    clip
    clip
  block.end.1417:
  testends "  "
  jumpfalse block.end.1439
    clip
    clip
  block.end.1439:
  testends " "
  jumpfalse block.end.1454
    clip
  block.end.1454:
  testbegins "#"
  jumpfalse block.end.1540
    replace "#" " "
    put
    clear
    add "comment*"
    push
    jump parse
  block.end.1540:
  testbegins "function"
  jumptrue 8
  testends "()  {"
  jumptrue 6
  testends "() {"
  jumptrue 4
  testends "(){"
  jumptrue 2 
  jump block.end.1702
    replace "function " ""
    replace "{" ""
    replace "()" ""
    put
    clear
    add "function*"
    push
    jump parse
  block.end.1702:
  # comments above none function lines should be ignored
  testis ""
  jumptrue block.end.1806
    clear
    add "line*"
    push
    jump parse
  block.end.1806:
block.end.1809:
parse:
# for debugging
# unstack; print; stack; add "\n"; print; clear;
pop
pop
# ignore comments before non-function bash statement 
testis "comment*line*"
jumptrue 4
testis "line*line*"
jumptrue 2 
jump block.end.1991
  clear
block.end.1991:
# concatenate comment lines
testis "comment*comment*"
jumpfalse block.end.2122
  clear
  get
  ++
  get
  --
  put
  clear
  add "comment*"
  push
  jump parse
block.end.2122:
# print and delete function token 
testis "*function*comment*"
jumpfalse block.end.2307
  clear
  get
  print
  # transfer comment text
  clear
  ++
  get
  --
  put
  clear
  add "comment*"
  push
  jump parse
block.end.2307:
# just print, no need to reduce
testis "function*function*"
jumpfalse block.end.2415
  clear
  get
  ++
  get
  --
  print
  clear
block.end.2415:
testis "function*line*"
jumpfalse block.end.2464
  clear
  get
  print
  clear
block.end.2464:
testis "line*function*"
jumpfalse block.end.2520
  clear
  ++
  get
  --
  print
  clear
block.end.2520:
# just print, no need to reduce? but print in order 
# function name with comment as description after (indented)
testis "comment*function*"
jumpfalse block.end.2888
  clear
  # a swap trick to indent the (mulitline) comment and then
  # prepend the function name.
  #add "  "; get; replace "\n" "\n  ";
  #++; swap; get; --; print; 
  add "\n"
  ++
  get
  --
  get
  print
  clear
block.end.2888:
push
push
testeof 
jumpfalse block.end.2918
  quit
block.end.2918:
jump start