7. Documentation generator

Parse and print doco.
Start data section to misc/flxdoc_style.css[1 /1 ]
     1: a:visited {color : #416DFF; text-decoration : none; }
     2: a:link {color : #416DFF; text-decoration : none;}
     3: a:hover {color : Red; text-decoration : none; background-color: #5FFF88}
     4: a:active {color : Red; text-decoration : underline; }
     5: .dcl { font-weight : bold ; color : Maroon }
     6: body { margin-left : 20px; margin-right: 20px }
     7: body .desc { color : Blue ; margin-bottom : 30px; margin-left: 20px }
     8: div.topentry {  margin-bottom : 0.2em; margin-left: 20px; margin-top : 0.2em }
     9: div.subentry { margin-left: 4ex; margin-bottom : 0.1em }
    10: div.topentry div.desc { color : Purple; margin-bottom : 5px; margin-left: 20px }
    11: .keyword { font-weight : bold ; color : Red }
    12: .ctype { color : Green }
    13: .keywordsign { color : #C04600 }
    14: .superscript { font-size : 4 }
    15: .subscript { font-size : 4 }
    16: .comment { font-size : 14pt ;  border: 1px solid #000000;
    17:   margin-top: 5px; margin-bottom: 2px;
    18:   margin-left -20px;
    19:   margin-right 20px;
    20:   text-align: left;
    21:   background-color: #90EDFF;
    22:   padding: 2px;
    23:   padding-left: 20px;
    24: }
    25: 
    26: .constructor { color : Blue }
    27: .type { color : #5C6585 }
    28: .string { color : Maroon }
    29: .warning { color : Red ; font-weight : bold }
    30: .info { margin-left : 3em; margin-right : 3em }
    31: .code { color : #465F91 ; }
    32: h1 { font-size : 20pt ; text-align: center; }
    33: h2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; }
    34: h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; }
    35: h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; }
    36: h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; }
    37: h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; }
    38: div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ; padding: 2px; }
    39: div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; }
    40: div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; }
    41: .typetable { border-style : hidden }
    42: .indextable { border-style : hidden }
    43: .paramstable { border-style : hidden ; padding: 5pt 5pt}
    44: body { background-color : White }
    45: tr { background-color : White }
    46: td.typefieldcomment { background-color : #FFFFFF }
    47: pre { margin-bottom: 4px }
    48: div.sig_block {margin-left: 2em}
    49: 
End data section to misc/flxdoc_style.css[1]
Start felix section to tools/flx_doc.flx[1 /1 ]
     1: #line 56 "./lpsrc/flx_docgen.ipk"
     2: include "std";
     3: include "flx_lex";
     4: include "flx_token";
     5: include "flx_grammar";
     6: 
     7: open flx_token;
     8: open flx_grammar;
     9: open Text_file;
    10: 
    11: use Lexer::sub;
    12: use Lexer::eq;
    13: 
    14: fun chop_directory (s:string)=
    15: {
    16:   var i = len s - 1;
    17:   until i == -1 do
    18:     if s.[i] == "/".[0] do return s.[i+1 to]; done;
    19:     --i;
    20:   done;
    21:   return s;
    22: }
    23: 
    24: fun chop_extension (s:string)=
    25: {
    26:   var i = len s - 1;
    27:   until i == -1 do
    28:     if s.[i] == ".".[0] do return s.[to i]; done;
    29:     --i;
    30:   done;
    31:   return s;
    32: }
    33: 
    34: keywords :=
    35: ("all",TOK_ALL),
    36: ("assert",TOK_ASSERT),
    37: ("axiom",TOK_AXIOM),
    38: ("body",TOK_BODY),
    39: ("call",TOK_CALL),
    40: ("case",TOK_CASE),
    41: ("caseno",TOK_CASENO),
    42: ("class",TOK_CLASS),
    43: ("comment",TOK_COMMENT_KEYWORD),
    44: ("compound",TOK_COMPOUND),
    45: ("const",TOK_CONST),
    46: ("cclass",TOK_CCLASS),
    47: ("cstruct",TOK_CSTRUCT),
    48: ("ctor",TOK_CTOR),
    49: ("ctypes",TOK_CTYPES),
    50: ("def",TOK_DEF),
    51: ("do",TOK_DO),
    52: ("done",TOK_DONE),
    53: ("elif",TOK_ELIF),
    54: ("else",TOK_ELSE),
    55: ("endif",TOK_ENDIF),
    56: ("endmatch",TOK_ENDMATCH),
    57: ("enum",TOK_ENUM),
    58: ("expect",TOK_EXPECT),
    59: ("export",TOK_EXPORT),
    60: ("for",TOK_FOR),
    61: ("forget",TOK_FORGET),
    62: ("fork",TOK_FORK),
    63: ("functor",TOK_FUNCTOR),
    64: ("fun",TOK_FUNCTION),
    65: ("goto",TOK_GOTO),
    66: ("header",TOK_HEADER),
    67: ("ident",TOK_IDENT),
    68: ("include",TOK_INCLUDE),
    69: ("incomplete",TOK_INCOMPLETE),
    70: ("inf",TOK_INF),
    71: ("in",TOK_IN),
    72: ("is",TOK_IS),
    73: ("inherit",TOK_INHERIT),
    74: ("inline",TOK_INLINE),
    75: ("jump",TOK_JUMP),
    76: ("let",TOK_LET),
    77: ("loop",TOK_LOOP),
    78: ("lval",TOK_LVAL),
    79: ("macro",TOK_MACRO),
    80: ("module",TOK_MODULE),
    81: ("NaN",TOK_NAN),
    82: ("new",TOK_NEW),
    83: ("noinline",TOK_NOINLINE),
    84: ("nonterm",TOK_NONTERM),
    85: ("noreturn",TOK_NORETURN),
    86: ("not",TOK_NOT),
    87: ("obj",TOK_OBJECT),
    88: ("open",TOK_OPEN),
    89: ("package",TOK_PACKAGE),
    90: ("pod",TOK_POD),
    91: ("private",TOK_PRIVATE),
    92: ("proc",TOK_PROCEDURE),
    93: ("property",TOK_PROPERTY),
    94: ("reduce",TOK_REDUCE),
    95: ("rename",TOK_RENAME),
    96: ("requires",TOK_REQUIRES),
    97: ("return",TOK_RETURN),
    98: ("struct",TOK_STRUCT),
    99: ("then",TOK_THEN),
   100: ("todo",TOK_TODO),
   101: ("to",TOK_TO),
   102: ("typedef",TOK_TYPEDEF),
   103: ("type",TOK_TYPE),
   104: ("union",TOK_UNION),
   105: ("use",TOK_USE),
   106: ("val",TOK_VAL),
   107: ("var",TOK_VAR),
   108: ("when",TOK_WHEN),
   109: ("with",TOK_WITH),
   110: ("_",TOK_UNDERSCORE),
   111: ("_gc_pointer",TOK_GC_POINTER),
   112: ("_gc_type",TOK_GC_TYPE),
   113: ("_svc",TOK_SVC),
   114: ("_deref",TOK_DEREF),
   115: ("and",TOK_AND),
   116: ("as",TOK_AS),
   117: ("callback",TOK_CALLBACK),
   118: ("code",TOK_CODE),
   119: ("if",TOK_IF),
   120: ("isin",TOK_ISIN),
   121: ("match",TOK_MATCH),
   122: ("noexpand",TOK_NOEXPAND),
   123: ("of",TOK_OF),
   124: ("or",TOK_OR),
   125: ("parse",TOK_PARSE),
   126: ("regexp",TOK_REGEXP),
   127: ("reglex",TOK_REGLEX),
   128: ("regmatch",TOK_REGMATCH),
   129: ("the",TOK_THE),
   130: ("typematch",TOK_TYPEMATCH),
   131: #line 92 "./lpsrc/flx_docgen.ipk"
   132:   ("",TOK_EOF) // terminal
   133: ;
   134: 
   135: fun find_keyword(k:string) =
   136: {
   137:   var i=0;
   138:   var key = keywords.[i];
   139:   until key.(0) == k or key.(0) == "" do
   140:     ++i;
   141:     key = keywords.[i];
   142:   done;
   143:   return key.(1);
   144: }
   145: 
   146: fun get_pretoken() =
   147: {
   148:   open Flx_lex;
   149:   def var j, var des = pre_flx_lex (i1, i2);
   150:   match des with
   151:   | qQuote =>        { j,des = parse_q_string (j,i2); }
   152:   | qqqQuote =>      { j,des = parse_qqq_string (j,i2); }
   153:   | dQuote =>        { j,des = parse_d_string (j,i2); }
   154:   | dddQuote =>      { j,des = parse_ddd_string (j,i2); }
   155:   | rqQuote =>       { j,des = parse_rq_string (j,i2); }
   156:   | rqqqQuote =>     { j,des = parse_rqqq_string (j,i2); }
   157:   | rdQuote =>       { j,des = parse_rd_string (j,i2); }
   158:   | rdddQuote =>     { j,des = parse_rddd_string (j,i2); }
   159:   | Preprocessor =>  { j = to_eol(j,i2) - 1; }
   160:   | Cpp_comment =>   { j = to_eol(j,i2) - 1; }
   161:   | C_comment =>     { j = to_end_c_comment (j,i2); }
   162:   | _ => {}
   163:   endmatch;
   164:   lexeme := Lexer::string_between(i1,j);
   165:   i1 = j;
   166:   return
   167:     match des with
   168:     | Eol => TOK_EOF
   169:     | Ident =>
   170:       match find_keyword lexeme with
   171:       | TOK_EOF => TOK_NAME lexeme
   172:       | ?k => k
   173:       endmatch
   174: 
   175:     // not really right, we should get the string
   176:     // but enough for documentation processor
   177: 
   178:     | qQuote => TOK_STRING lexeme.[1 to -1]
   179:     | qqqQuote => TOK_STRING lexeme.[3 to -3]
   180:     | dQuote => TOK_STRING lexeme.[1 to -1]
   181:     | dddQuote => TOK_STRING lexeme.[3 to -3]
   182: 
   183:     | wqQuote => TOK_STRING lexeme.[1 to -1]
   184:     | wqqqQuote => TOK_STRING lexeme.[3 to -3]
   185:     | wdQuote => TOK_STRING lexeme.[1 to -1]
   186:     | wdddQuote => TOK_STRING lexeme.[3 to -3]
   187: 
   188:     | uqQuote => TOK_STRING lexeme.[1 to -1]
   189:     | uqqqQuote => TOK_STRING lexeme.[3 to -3]
   190:     | udQuote => TOK_STRING lexeme.[1 to -1]
   191:     | udddQuote => TOK_STRING lexeme.[1 to -1]
   192: 
   193:     | rqQuote => TOK_STRING lexeme.[1 to -1]
   194:     | rqqqQuote => TOK_STRING lexeme.[3 to -3]
   195:     | rdQuote => TOK_STRING lexeme.[1 to -1]
   196:     | rdddQuote => TOK_STRING lexeme.[3 to -3]
   197: 
   198: 
   199:     | DOLLAR => TOK_DOLLAR
   200:     | QUEST => TOK_QUEST
   201:     | EXCLAMATION => TOK_EXCLAMATION
   202:     | LPAR => TOK_LPAR
   203:     | RPAR => TOK_RPAR
   204:     | LSQB => TOK_LSQB
   205:     | RSQB => TOK_RSQB
   206:     | LBRACE => TOK_LBRACE
   207:     | RBRACE => TOK_RBRACE
   208:     | COLON => TOK_COLON
   209:     | COMMA => TOK_COMMA
   210:     | SEMI => TOK_SEMI
   211:     | PLUS => TOK_PLUS
   212:     | MINUS => TOK_MINUS
   213:     | STAR => TOK_STAR
   214:     | SLASH => TOK_SLASH
   215:     | VBAR => TOK_VBAR
   216:     | AMPER => TOK_AMPER
   217:     | LESS => TOK_LESS
   218:     | GREATER => TOK_GREATER
   219:     | EQUAL => TOK_EQUAL
   220:     | DOT => TOK_DOT
   221:     | PERCENT => TOK_PERCENT
   222:     | BACKQUOTE => TOK_BACKQUOTE
   223:     | TILDE => TOK_TILDE
   224:     | CIRCUMFLEX => TOK_CIRCUMFLEX
   225:     | HASH => TOK_HASH
   226:     | ANDLESS => TOK_ANDLESS
   227:     | ANDGREATER => TOK_ANDGREATER
   228:     | EQEQUAL => TOK_EQEQUAL
   229:     | NOTEQUAL => TOK_NOTEQUAL
   230:     | LESSEQUAL => TOK_LESSEQUAL
   231:     | GREATEREQUAL => TOK_GREATEREQUAL
   232:     | LEFTSHIFT => TOK_LEFTSHIFT
   233:     | RIGHTSHIFT => TOK_RIGHTSHIFT
   234:     | STARSTAR => TOK_STARSTAR
   235:     | LESSCOLON => TOK_LESSCOLON
   236:     | COLONGREATER => TOK_COLONGREATER
   237:     | DOTDOT => TOK_DOTDOT
   238:     | COLONCOLON => TOK_COLONCOLON
   239:     | PLUSPLUS => TOK_PLUSPLUS
   240:     | MINUSMINUS => TOK_MINUSMINUS
   241:     | PLUSEQUAL => TOK_PLUSEQUAL
   242:     | MINUSEQUAL => TOK_MINUSEQUAL
   243:     | STAREQUAL => TOK_STAREQUAL
   244:     | SLASHEQUAL => TOK_SLASHEQUAL
   245:     | PERCENTEQUAL => TOK_PERCENTEQUAL
   246:     | CARETEQUAL => TOK_CARETEQUAL
   247:     | VBAREQUAL => TOK_VBAREQUAL
   248:     | AMPEREQUAL => TOK_AMPEREQUAL
   249:     | TILDEEQUAL => TOK_TILDEEQUAL
   250:     | COLONEQUAL => TOK_COLONEQUAL
   251:     | RIGHTARROW => TOK_RIGHTARROW
   252:     | EQRIGHTARROW => TOK_EQRIGHTARROW
   253:     | LEFTARROW => TOK_LEFTARROW
   254:     | LSQANGLE => TOK_LSQANGLE
   255:     | RSQANGLE => TOK_RSQANGLE
   256:     | LSQBAR => TOK_LSQBAR
   257:     | RSQBAR => TOK_RSQBAR
   258:     | AMPERAMPER => TOK_AMPERAMPER
   259:     | VBARVBAR => TOK_VBARVBAR
   260:     | SLOSHAMPER => TOK_SLOSHAMPER
   261:     | SLOSHVBAR => TOK_SLOSHVBAR
   262:     | SLOSHCIRCUMFLEX => TOK_SLOSHCIRCUMFLEX
   263:     | HASHBANG => TOK_HASHBANG
   264:     | LEFTSHIFTEQUAL => TOK_LEFTSHIFTEQUAL
   265:     | RIGHTSHIFTEQUAL => TOK_RIGHTSHIFTEQUAL
   266:     | LEFTRIGHTARROW => TOK_LEFTRIGHTARROW
   267:     | ANDEQEQUAL => TOK_ANDEQEQUAL
   268:     | ANDNOTEQUAL => TOK_ANDNOTEQUAL
   269:     | ANDLESSEQUAL => TOK_ANDLESSEQUAL
   270:     | ANDGREATEREQUAL => TOK_ANDGREATEREQUAL
   271:     | DOTDOTDOT => TOK_DOTDOTDOT
   272:     | DOTRIGHTARROW => TOK_DOTRIGHTARROW
   273:     | LONGRIGHTARROW => TOK_LONGRIGHTARROW
   274:     | PARSE_ACTION => TOK_PARSE_ACTION
   275:     | HASHBANGSLASH => TOK_HASHBANGSLASH
   276: #line 168 "./lpsrc/flx_docgen.ipk"
   277:     | Preprocessor =>  TOK_EOF
   278:     | Cpp_comment =>   TOK_EOF
   279:     | C_comment =>     TOK_EOF
   280:     | White => TOK_EOF
   281: 
   282:     // cheat again
   283:     | Int => TOK_INTEGER (lexeme,"")
   284:     | Float => TOK_FLOAT lexeme
   285:     | _ => TOK_ERROR lexeme
   286:     endmatch
   287:   ;
   288: }
   289: 
   290: endmarker := caseno TOK_ENDMARKER;
   291: eol := '\n';
   292: 
   293: var eof = false;
   294: 
   295: kfun := keywrd "fun ";
   296: kproc := keywrd "proc ";
   297: ktype := keywrd "type ";
   298: kctype := keywrd "ctype ";
   299: 
   300: 
   301: var outdir = "doc_out/";
   302: 
   303: var i = 1;
   304: var filename = System::argv 1;
   305: if filename.[to 9] == "--outdir=" do
   306:  outdir = filename.[9 to];
   307:  ++i;
   308:  filename = System::argv i;
   309: done;
   310: 
   311: // make the output directory
   312: C_hack::ignore(System::system("mkdir -p " + outdir));
   313: 
   314: 
   315: mfile := outdir + "/index.html";
   316: mf := fopen_output mfile;
   317: writeln (mf, start_page "Felix Library");
   318: writeln (mf,"<H1>"+outdir+"</H1>");
   319: 
   320: until filename == "" do
   321:   handle_file filename;
   322:   ++i;
   323:   filename = System::argv i;
   324: done;
   325: writeln (mf,"</HTML></BODY>");
   326: fclose mf;
   327: 
   328: var data: string;
   329: var i1:Lexer::iterator;
   330: var i2:Lexer::iterator;
   331: 
   332: proc handle_file(filename: string)
   333: {
   334:   print "Filename "; print filename; endl;
   335:   data = load filename;
   336:   eof = false;
   337: 
   338:   i2 = Lexer::end_iterator data;
   339:   i1 = Lexer::start_iterator data;
   340:   var x =
   341:     parse the get_token with
   342:     | cu: flx_grammar::top => cu
   343:     endmatch
   344:   ;
   345: 
   346:   d :=
   347:     match x with
   348:     | case 1 => "Failure"
   349:     | case 2 _ => "Success"
   350:     endmatch
   351:   ;
   352: 
   353:   print d; endl;
   354: 
   355:   if caseno x == 0 return;
   356: 
   357:   statements :=
   358:     match x with
   359:     | case 2 ?cu =>
   360:       match cu with
   361:       | compilation_unit_1 ?sts => sts
   362:       endmatch
   363:     endmatch
   364:   ;
   365: 
   366:   basename := chop_extension (chop_directory filename);
   367:   fn := outdir+'/'+basename+'_flx.html';
   368:   f := fopen_output fn;
   369:   writeln (f, start_page basename);
   370:   writeln (f,"<H1>"+filename+"</H1>");
   371:   writeln (mf,
   372:     '<div class="toc_entry">'
   373:     (keywrd 'File ') '<A HREF="' basename '_flx.html">' filename '</A>'
   374:     '</div>'
   375:   );
   376:   handle_statements (f, statements);
   377:   writeln (f,"</HTML></BODY>");
   378:   fclose f;
   379: }
   380: 
   381: fun get_token(): flx_token_t =
   382: {
   383: retry:>
   384:   if i1 == i2 do
   385:     if eof do
   386:       return TOK_EOF;
   387:     else
   388:       eof = true;
   389:       return TOK_ENDMARKER;
   390:     done;
   391:   else
   392:     t := get_pretoken();
   393:     if caseno t == caseno TOK_EOF goto retry;
   394:     return t;
   395:   done;
   396: }
   397: 
   398: 
   399: fun start_page(title:string)=>
   400:   '<html>' eol
   401:   '<head>' eol
   402:   '<meta http-equiv="Content-Type" content="text/html; charset="utf-8">' eol
   403:   '<link rel="stylesheet" href="flxdoc_style.css" type="text/css">' eol
   404:   '<title>' title '</title>' eol
   405:   '</head>' eol
   406:   '<body>' eol
   407: ;
   408: 
   409: fun dcl (name:string) =>
   410:   '<span class="dcl">' name '</span>'
   411: ;
   412: 
   413: fun keywrd (kwd:string) =>
   414:   '<span class="keyword">' kwd '</span>'
   415: ;
   416: 
   417: 
   418: proc handle_statements (f:text_file, sts:statement_aster_t)
   419: {
   420:   match sts with
   421:   | statement_aster_1 (?s,?sts) =>
   422:     {
   423:       handle_statement (f,s,"");
   424:       handle_statements (f,sts);
   425:     }
   426: 
   427:   | statement_aster_2 => {}
   428:   endmatch
   429:   ;
   430: }
   431: 
   432: 
   433: proc handle_statement (f:text_file, s:statement_t,desc:string) {
   434:   match s with
   435:   | statement_1 ?s =>
   436:     {
   437:       writeln(f,'<div class="topentry">');
   438:       handle_binding_definition (f,s,desc);
   439:       writeln(f,'</div>');
   440:      }
   441:   | statement_2 ?s =>
   442:     {
   443:       writeln(f,'<div class="topentry">');
   444:       handle_declarative (f,s,desc);
   445:       writeln(f,'</div>');
   446:     }
   447:   | statement_3 ?s => {}
   448:   | statement_4 ?s =>
   449:     let inclusion_1 ?s = s in
   450:     {
   451:       writeln(f,'<div class="topentry">');
   452:       writeln(f, keywrd "include "+ s);
   453:       writeln(f,'</div>');
   454:     }
   455: 
   456: 
   457:   | statement_5 ?s => { handle_directive (f,s); }
   458:   | statement_6 ?s => { handle_publish (f,s); }
   459:   | statement_7 ?s =>
   460:     let comment_1 ?s = s in
   461:     { writeln(f,'<div class="comment">' s '</div>'); }
   462: 
   463:   | statement_8 ?s => {} // null
   464:   endmatch;
   465: }
   466: 
   467: proc handle_publish(f:text_file, p:publish_t)
   468: {
   469:   match p with
   470:   | publish_1  (?desc,?bd) =>
   471:     {
   472:       writeln(f,'<div class="topentry">');
   473:       handle_binding_definition (f,bd,desc);
   474:       writeln(f,'</div>');
   475:     }
   476:   | publish_2 (?desc,?dcl) =>
   477:     {
   478:       writeln(f,'<div class="topentry">');
   479:       handle_declarative (f,dcl,desc);
   480:       writeln(f,'</div>');
   481:     }
   482:   | publish_3 ?dcl  => {} // private
   483:   | publish_4 ?bd => {} // private
   484:   endmatch;
   485: }
   486: 
   487: proc print_description (f:text_file,desc:string)
   488: {
   489:   if desc != "" do
   490:     writeln(f,'<div class="desc">' desc "</div>");
   491:   done;
   492: }
   493: 
   494: proc handle_directive (f:text_file, t:directive_t)
   495: {
   496:   match t with
   497:   | directive_1 _ => {}
   498:   | directive_2 _ => {}
   499:   | directive_3 ?r =>
   500:     {
   501:       writeln(f,'<div class="topentry">');
   502:       handle_regdef (f,r);
   503:       writeln(f,'</div>');
   504:    }
   505:   | directive_4 ?g =>
   506:     {
   507:       writeln(f,'<div class="topentry">');
   508:       handle_glr_production (f,g);
   509:       writeln(f,'</div>');
   510:     }
   511:   | directive_5 ?m => {}
   512:   endmatch;
   513: }
   514: 
   515: proc handle_glr_production(f:text_file, t:glr_production_t)
   516: {
   517:   proc handle_glr_matching (g:glr_matching_t)
   518:   {
   519:     match g with
   520:     | glr_matching_1 (?ges,_) =>
   521:       {
   522:         writeln(f,
   523:           '<div class="subentry">' +
   524:           keywrd "| " +
   525:           str ges +
   526:           '</div>'
   527:         );
   528:       }
   529:     | glr_matching_2 _ =>
   530:       {
   531:         writeln(f,
   532:           '<div class="subentry">'
   533:           (keywrd "| ")
   534:           '<span class="desc">epsilon</span>'
   535:           '</div>'
   536:         );
   537:       }
   538:     endmatch;
   539:   }
   540: 
   541:   proc handle_glr_matchings (t:glr_matchings_t)
   542:   {
   543:     match t with
   544:     | glr_matchings_1 (?g,?gs) =>
   545:       {
   546:         handle_glr_matching g;
   547:         handle_glr_matchings gs;
   548:       }
   549:     | glr_matchings_2 ?g =>
   550:       {
   551:         handle_glr_matching g;
   552:       }
   553:     endmatch;
   554:   }
   555: 
   556:   match t with
   557:   | glr_production_1 (?nt, ?t,?ms) =>
   558:     {
   559:       writeln (f,keywrd "nonterm "+ dcl nt+' : ' + str t+" = ");
   560:       handle_glr_matchings ms;
   561:     }
   562:   endmatch;
   563: }
   564: 
   565: proc handle_regdef (f:text_file, t:regdef_t)
   566: {
   567:   match t with
   568:   | regdef_1 (?name,?re) =>
   569:     {
   570:       writeln (f,keywrd "regexp "+ dcl name+' = ' + str re);
   571:     }
   572:   endmatch;
   573: }
   574: 
   575: proc handle_binding_definition (f:text_file, s:binding_definition_t, desc:string)
   576: {
   577:   match s with
   578:   | binding_definition_1 ?s => { handle_abstract_type (f,s); }
   579:   | binding_definition_2 ?s => { handle_const_def (f,s); }
   580:   | binding_definition_3 ?s => { handle_binding_header (f,s); }
   581:   | binding_definition_4 ?s => { handle_export (f,s); }
   582:   endmatch;
   583:   print_description (f,desc);
   584: }
   585: 
   586: proc handle_export (f:text_file, t:export_statement_t)
   587: {
   588:   match t with
   589:   | export_statement_1 (?sn,?s) =>
   590:     { writeln(f,keywrd "export fun " + str sn + " as " + dcl s); }
   591: 
   592:   | export_statement_2 (?sn,?s) =>
   593:     { writeln(f,keywrd "export proc " + str sn + " as " + dcl s); }
   594: 
   595:   | export_statement_3 (?t,?s) =>
   596:     { writeln(f,keywrd "export type " + "(" + str t + ") as " + dcl s); }
   597:   endmatch;
   598: }
   599: 
   600: proc handle_binding_header (f:text_file, t:binding_header_t)
   601: {
   602:   match t with
   603:   | binding_header_1 (_,_) =>  {}
   604:   | binding_header_2 (_,_) => {}
   605:   | binding_header_3 (_,_) => {}
   606:   | binding_header_4 (_,_) => {}
   607:   | binding_header_5 (?name,?tvs,?h,_) =>
   608:    { writeln(f,keywrd "header " + dcl name + str tvs); }
   609: 
   610:   | binding_header_6 (?name,?tvs,?b,_) =>
   611:    { writeln(f,keywrd "body " + dcl name + str tvs); }
   612: 
   613:   | binding_header_7 _ => {}
   614:   | binding_header_8 _ => {}
   615:   endmatch;
   616: }
   617: 
   618: proc handle_const_def (f:text_file, t:const_def_t)
   619: {
   620:   match t with
   621:   | const_def_1 (?name,?tvs,?typ,?ct,_) =>
   622:     { handle_const (f,name,tvs,typ); }
   623: 
   624:   | const_def_2 (?name,?tvs,?typ,_) =>
   625:     { handle_const (f,name,tvs,typ); }
   626:   endmatch;
   627: }
   628: 
   629: 
   630: proc handle_const (f:text_file, name:string, tvs:tvarlist_t, typ:type_expr_t)
   631: {
   632:   writeln(f,keywrd "const " + dcl name + str tvs + " : " + str typ);
   633: }
   634: 
   635: proc handle_declarative (f:text_file, dcl:declarative_t, desc:string)
   636: {
   637:   match dcl with
   638:   | declarative_1 ?fn => { handle_function_definition (f,fn); }
   639:   | declarative_2 ?o => { print "object"; endl; }
   640:   | declarative_3 ?p => { handle_procedure_definition (f,p); }
   641:   | declarative_4 ?m => { handle_module (f,m,desc); }
   642:   | declarative_5 ?u => { handle_union (f,u); }
   643:   | declarative_6 ?s => { handle_struct (f,s); }
   644:   | declarative_7 ?t => { handle_type_alias (f,t); }
   645:   endmatch;
   646:   print_description (f,desc);
   647: }
   648: 
   649: proc handle_type_alias (f:text_file, t:type_alias_t)
   650: {
   651:   match t with
   652:   | type_alias_1 (?name, ?tvs,?typ) =>
   653:     { handle_typedef (f,name,tvs,typ); }
   654: 
   655:   | type_alias_2 (?name, ?tvs, ?args,?rt,?te) =>
   656:     { handle_typefun (f,name,tvs,args,rt,te); }
   657: 
   658:   | type_alias_3 (?name, ?tvs, ?qn) =>
   659:     { handle_rename(f,name,tvs,qn); }
   660: 
   661:   | type_alias_4 (?name,?tvs,?qn) =>
   662:     { handle_fun_rename(f,name,tvs,qn); }
   663: 
   664:   | type_alias_5 ?qn =>
   665:     { handle_inherit(f,qn); }
   666: 
   667:   endmatch;
   668: }
   669: 
   670: proc handle_typedef (f:text_file, name:string, tvs:tvarlist_t,typ:type_expr_t)
   671: {
   672:   s := keywrd "typedef " + dcl name + str tvs + " = " + str typ;
   673:   writeln(f,s);
   674: }
   675: 
   676: // WARNING: hacked, the function value is expressed using
   677: // parameter names that aren't printed ..
   678: proc handle_typefun (f:text_file, name:string, tvs:tvarlist_t, args:fun_args_t, rt:type_expr_t, typ:type_expr_t)
   679: {
   680:   s := keywrd "typedef fun " + dcl name + str tvs + str args + " : " + str rt + " = " + str typ;
   681:   writeln(f,s);
   682: }
   683: 
   684: proc handle_rename (f:text_file, name:string, tvs:tvarlist_t, qn:qualified_name_t)
   685: {
   686:   s := keywrd "rename " + dcl name + str tvs + " = " + str qn;
   687:   writeln(f,s);
   688: }
   689: 
   690: proc handle_fun_rename (f:text_file, name:string, tvs:tvarlist_t, qn:qualified_name_t)
   691: {
   692:   s := keywrd "rename fun " + dcl name + str tvs + " = " + str qn;
   693:   writeln(f,s);
   694: }
   695: 
   696: proc handle_inherit (f:text_file, qn:qualified_name_t)
   697: {
   698:   writeln(f,keywrd "inherit " + str qn);
   699: }
   700: 
   701: proc handle_union (f:text_file, t:union_decl_t)
   702: {
   703:   match t with
   704:   | union_decl_1 (?name,?es) =>
   705:     {
   706:       writeln(f,keywrd "enum " + dcl name);
   707:       handle_enum_items (f,es);
   708:     }
   709:   | union_decl_2 (?name,?tvs,?sms) =>
   710:     {
   711:       writeln(f,keywrd "union " + dcl name+ str tvs);
   712:       handle_sum_items(f,sms);
   713:     }
   714: 
   715:   | union_decl_3 (?name,?tvs,?sms) =>
   716:     {
   717:       writeln(f,keywrd "union " + dcl name+str tvs);
   718:       handle_sum_items(f,sms);
   719:     }
   720:   endmatch;
   721: }
   722: 
   723: proc handle_struct (f:text_file, t:struct_decl_t)
   724: {
   725:   match t with
   726:   | struct_decl_1 (?name,?tvs,?scs) =>
   727:     {
   728:       writeln(f,keywrd "struct " + dcl name+str tvs);
   729:       handle_struct_items(f,scs);
   730:     }
   731: 
   732:   | struct_decl_2 (?name,?tvs,?scs) =>
   733:     {
   734:       writeln(f,keywrd "struct " + dcl name+str tvs);
   735:       handle_struct_items(f,scs);
   736:     }
   737: 
   738:   | struct_decl_3 (?name,?scs) =>
   739:     {
   740:       writeln(f,keywrd "struct " + dcl name);
   741:       handle_struct_items(f,scs);
   742:     }
   743:   endmatch;
   744: }
   745: 
   746: proc handle_struct_items (f:text_file, t:struct_component_aster_t)
   747: {
   748:   match t with
   749:   | struct_component_aster_1 (?e,?es) =>
   750:     {
   751:       handle_struct_item (f,e);
   752:       handle_struct_items(f,es);
   753:     }
   754:   | struct_component_aster_2 => {}
   755:   endmatch;
   756: }
   757: 
   758: proc handle_struct_item (f:text_file, t:struct_component_t)
   759: {
   760:   match t with
   761:   | struct_component_1 (?s,?t) =>
   762:     {
   763:       writeln(f,
   764:         '<div class="subentry">' +
   765:         keywrd "var " + (dcl s)+" : "+str t +
   766:         '</div>'
   767:      );
   768:     }
   769:   endmatch;
   770: }
   771: 
   772: proc handle_enum_items (f:text_file, t:enum_items_t)
   773: {
   774:   match t with
   775:   | enum_items_1 (?es,?e) =>
   776:     let enum_item_1 ?name = e in
   777:     {
   778:       handle_enum_items(f,es);
   779:       writeln(f,
   780:         '<div class="subentry">' +
   781:         keywrd "| " + (dcl name) +
   782:         '</div>'
   783:       );
   784:     }
   785:   | enum_items_2 ?e =>
   786:     let enum_item_1 ?name = e in
   787:     {
   788:       writeln(f,
   789:         '<div class="subentry">' +
   790:         keywrd "| " + (dcl name) +
   791:         '</div>'
   792:       );
   793:     }
   794:   endmatch;
   795: }
   796: 
   797: proc handle_sum_items (f:text_file, t:type_sum_items_t)
   798: {
   799:   match t with
   800:   | type_sum_items_1 (?es,?e) =>
   801:     {
   802:       handle_sum_items(f,es);
   803:       handle_sum_item (f,e);
   804:     }
   805:   | type_sum_items_2 ?e =>
   806:     {
   807:       handle_sum_item (f,e);
   808:     }
   809:   endmatch;
   810: }
   811: 
   812: proc handle_sum_item(f:text_file, t:type_sum_item_t)
   813: {
   814:   match t with
   815:   | type_sum_item_1 (?name,?typ) =>
   816:     {
   817:       writeln(f,
   818:         '<div class="subentry">' +
   819:         keywrd "| " + (dcl name)+" of " + str typ +
   820:         '</div>'
   821:       );
   822:     }
   823: 
   824:   | type_sum_item_2 ?name =>
   825:     {
   826:       writeln(f,
   827:         '<div class="subentry">' +
   828:         keywrd "| " + (dcl name) +
   829:         '</div>'
   830:       );
   831:     }
   832:   endmatch;
   833: }
   834: 
   835: proc handle_function_definition (f:text_file, t:function_definition_t)
   836: {
   837:   match t with
   838:   | function_definition_1 (?adjs,?name,?tvs,?args,?ote,_) =>
   839:     { handle_felix_function (f,adjs,name,tvs,args,ote); }
   840: 
   841:   | function_definition_2 (?adjs,?name,?tvs,?args,?ote,_) =>
   842:     { handle_felix_function (f,adjs,name,tvs,args,ote); }
   843: 
   844:   | function_definition_3 (?adjs,?name,?tvs,?t,_,_,_) =>
   845:     { handle_primitive_function (f,adjs,name,tvs,t); }
   846: 
   847:   | function_definition_4 (?adjs,?name,?tvs,?t,_) =>
   848:     { handle_primitive_function (f,adjs,name,tvs,t); }
   849:   endmatch;
   850: }
   851: 
   852: proc handle_procedure_definition (f:text_file, t:procedure_definition_t)
   853: {
   854:   match t with
   855:   | procedure_definition_1 (?name, ?tvs,?oargs,_) =>
   856:     let ?adjs = adjectives_2 in
   857:     { handle_felix_procedure (f,adjs,name,tvs,oargs); }
   858: 
   859:   | procedure_definition_2 (?adj,?name,?tvs,_) =>
   860:     let ?adjs = adjectives_1 (adj,adjectives_2) in
   861:     let ?oargs = opt_fun_args_2 in
   862:     { handle_felix_procedure (f,adjs,name,tvs,oargs); }
   863: 
   864:   | procedure_definition_3 (?name,?tvs,?t,_,_) =>
   865:     { handle_primitive_procedure (f,name,tvs,t); }
   866: 
   867:   endmatch;
   868: }
   869: 
   870: proc handle_felix_function
   871: (
   872:   f:text_file,
   873:   adjs:adjectives_t,
   874:   name:string,
   875:   tvs:tvarlist_t,
   876:   args:fun_args_t,
   877:   ote:opt_type_expr_t
   878: )
   879: {
   880:   s:= kfun (str adjs) (dcl name) (str tvs) " : " (str args) (str ote);
   881:   writeln(f,s);
   882: }
   883: 
   884: proc handle_felix_procedure
   885: (
   886:   f:text_file,
   887:   adjs:adjectives_t,
   888:   name:string,
   889:   tvs:tvarlist_t,
   890:   oargs:opt_fun_args_t
   891: )
   892: {
   893:   s:= kproc (str adjs) (dcl name) (str tvs) " : " (str oargs);
   894:   writeln(f,s);
   895: }
   896: 
   897: proc handle_primitive_function
   898: (
   899:   f:text_file,
   900:   adjs:adjectives_t,
   901:   name:string,
   902:   tvs:tvarlist_t,
   903:   t:type_expr_t
   904: )
   905: {
   906:   s :=kfun (str adjs) (dcl name) (str tvs) " : " (str t);
   907:   writeln(f,s);
   908: }
   909: 
   910: proc handle_primitive_procedure
   911: (
   912:   f:text_file,
   913:   name:string,
   914:   tvs:tvarlist_t,
   915:   t:type_expr_t
   916: )
   917: {
   918:   s := kproc (dcl name) (str tvs) " : " (str t);
   919:   writeln(f,s);
   920: }
   921: 
   922: proc handle_module (f:text_file, m:module_definition_t, desc:string)
   923: {
   924:   (let module_definition_1 (?name, ?tvs,?sts) = m in
   925:   let compound_1 ?sts = sts in
   926:   {
   927:     s:= keywrd "module"  " <A HREF=" name ".html>" name "</A>" (str tvs);
   928:     writeln(f,s);
   929:     g := fopen_output (outdir + '/'+name + ".html");
   930:     writeln(g,start_page name);
   931:     writeln(g,"<H1>Module " name (str tvs) "</H1>");
   932:     print_description (g,desc);
   933:     handle_statements (g,sts);
   934:     writeln(g,"</HTML></BODY>");
   935:     fclose g;
   936:   });
   937: }
   938: 
   939: proc handle_abstract_type (f:text_file, s: abstract_type_t)
   940: {
   941:   match s with
   942:   | abstract_type_1 (?qs, ?bncl, ?rqs) =>
   943:     { handle_ctypes (f,qs,bncl); }
   944: 
   945:   | abstract_type_2 (?qs, ?name, ?tvl, ?ct,?rqs) =>
   946:     { handle_ctype (f,qs,name,tvl); }
   947: 
   948:   endmatch;
   949: }
   950: 
   951: proc handle_ctypes (f:text_file, qs:type_quals_t, bncl: basic_name_comma_list_t)
   952: {
   953:   sqs := str qs;
   954: 
   955:   proc handle_inner_ctype (name:basic_name_t)
   956:   {
   957:     s := sqs "  " kctype (dcl (str name));
   958:     writeln(f,s);
   959:   }
   960: 
   961:   proc handle_bncl(bncl: basic_name_comma_list_t)
   962:   {
   963:     match bncl with
   964:     | basic_name_comma_list_1 (?name,?bncl') =>
   965:       {
   966:         handle_inner_ctype name;
   967:         handle_bncl bncl';
   968:       }
   969:     | basic_name_comma_list_2 ?name =>
   970:       {
   971:         handle_inner_ctype name;
   972:       }
   973:     | basic_name_comma_list_3 => {}
   974:     endmatch;
   975:   }
   976: 
   977:   handle_bncl bncl;
   978: }
   979: 
   980: proc handle_ctype (f:text_file, qs:type_quals_t,name:string,tvl:tvarlist_t)
   981: {
   982:   sqs := str qs;
   983:   s:= sqs " " ktype (dcl name) + (str tvl);
   984:   writeln(f,s);
   985: }
   986: 
   987: fun html(s:string):string =
   988: {
   989:   var s' = "";
   990:   n := len s;
   991:   var i =0; until i == n do
   992:     ch := s.[i];
   993:     if ch == '<'.[0] do s' += '&lt;';
   994:     elif ch == '>'.[0] do s' += '&gt;';
   995:     elif ch == '&'.[0] do s' += '&amp;';
   996:     else s' += ch;
   997:     done;
   998:     ++i;
   999:   done;
  1000:   return s';
  1001: }
  1002: 
  1003: //-----------------------------------------------
  1004: // strings representing small sub-terms
  1005: fun str : expr_t -> string =
  1006:   | expr_1 (?p,?e1,?e2) => "let <pattern> = " + str e1 " in " + str e2
  1007:   | expr_2 ?r => let rvalue_1 ?l = r in str l
  1008: ;
  1009: 
  1010: fun str : lambda_t -> string =
  1011:   | lambda_1 ?t => str t
  1012:   | lambda_2 _ => "(fun ...)"
  1013:   | lambda_3 _ => "(fun ...)"
  1014:   | lambda_4 _ => "(fun ...)"
  1015:   | lambda_5 ?c => "{ ... }"
  1016: ;
  1017: 
  1018: fun str: dollar_apply_t -> string =
  1019:   | dollar_apply_1 (?a,?b) => (str a) " (" (str b) ")"
  1020:   | dollar_apply_2 ?x => str x
  1021: ;
  1022: 
  1023: fun str : tuple_t -> string =
  1024:   | tuple_1 (?o,?t) => str o + str t
  1025:   | tuple_2 ?o => str o
  1026: ;
  1027: 
  1028: fun str : tuple_suffix_t -> string =
  1029:   | tuple_suffix_1 (?o,?t) => ", " + str o + str t
  1030:   | tuple_suffix_2 ?o => ", " + str o
  1031: ;
  1032: 
  1033: fun str : or_condition_t -> string =
  1034:   | or_condition_1 (?s,?sl) => str s + " + " + str sl
  1035:   | or_condition_2 ?s => str s
  1036: ;
  1037: 
  1038: fun str : or_list_t -> string =
  1039:   | or_list_1 (?s,?sl) => str s + " + " + str sl
  1040:   | or_list_2 ?s => str s
  1041: ;
  1042: 
  1043: fun str : and_condition_t -> string =
  1044:   | and_condition_1 (?s,?sl) => str s + " + " + str sl
  1045:   | and_condition_2 ?s => str s
  1046: ;
  1047: 
  1048: fun str : and_list_t -> string =
  1049:   | and_list_1 (?s,?sl) => str s + " + " + str sl
  1050:   | and_list_2 ?s => str s
  1051: ;
  1052: 
  1053: fun str : not_condition_t -> string =
  1054:   | not_condition_1 (_,?a) => " not "+ str a
  1055:   | not_condition_2 ?a => str a
  1056: ;
  1057: 
  1058: fun str (t:comparison_t)=> 'comparison .. endcomparison';
  1059: 
  1060: fun str: opt_type_expr_t -> string =
  1061:   | opt_type_expr_1 (?t,?e) => " : " + str t + " expect " + str e
  1062:   | opt_type_expr_2 ?t => " : " + str t
  1063:   | opt_type_expr_3 ?e => " exprect " + str e
  1064:   | opt_type_expr_4 => ""
  1065: ;
  1066: 
  1067: fun str (t: type_expr_t):string =>
  1068:   let type_expr_1 ?t = t in str t
  1069: ;
  1070: 
  1071: fun str : arrow_t -> string =
  1072:   | arrow_1 (?cl,?a) => str cl + " → "+str a
  1073:   | arrow_2 ?cl => str cl
  1074: ;
  1075: 
  1076: fun str : case_literal_t -> string =
  1077:   | case_literal_1 ?i => "case " + strint i
  1078:   | case_literal_2 (?i,?s) => "case " + strint i + str s
  1079:   | case_literal_3 ?s => str s
  1080: ;
  1081: 
  1082: fun str : sum_t -> string =
  1083:   | sum_1 (?s,?sl) => str s + " + " + str sl
  1084:   | sum_2 ?s => str s
  1085: ;
  1086: 
  1087: fun str : sum_list_t -> string =
  1088:   | sum_list_1 (?s,?sl) => str s + " + " + str sl
  1089:   | sum_list_2 ?s => str s
  1090: ;
  1091: 
  1092: fun str: subtraction_t -> string =
  1093:   | subtraction_1 (?s,?p) => str s + " - " + str p
  1094:   | subtraction_2 ?p => str p
  1095: ;
  1096: 
  1097: fun str : product_t -> string =
  1098:   | product_1 (?s,?sl) => str s + " * " + str sl
  1099:   | product_2 ?s => str s
  1100: ;
  1101: 
  1102: fun str : product_list_t -> string =
  1103:   | product_list_1 (?s,?sl) => str s + " * " + str sl
  1104:   | product_list_2 ?s => str s
  1105: ;
  1106: 
  1107: fun str : term_t -> string =
  1108:   | term_1 (?t,?p) => str t + " / " + str p
  1109:   | term_2 (?t,?p) => str t + " % " + str p
  1110:   | term_3 ?pr => str pr
  1111: ;
  1112: 
  1113: fun str : power_t -> string =
  1114:   | power_1( ?ss, ?pr) => str ss + " ** " + str pr
  1115:   | power_2 ?ss => str ss
  1116: ;
  1117: 
  1118: fun str : prefixed_t -> string =
  1119:   | prefixed_1 ?p => "lvalue[" + str p + "]"
  1120:   | prefixed_2 ?p => "+"+str p
  1121:   | prefixed_3 ?p => "-"+str p
  1122:   | prefixed_4 ?p => "~"+str p
  1123:   | prefixed_5 ?p => str p
  1124: ;
  1125: 
  1126: fun str : superscript_t -> string =
  1127:   | superscript_1 (?s,?r) => str s + " ^ " + str r
  1128:   | superscript_2 ?r => str r
  1129: ;
  1130: 
  1131: fun str : refr_t -> string =
  1132:   | refr_1 ?r => "&" + str r
  1133:   | refr_2 ?r => "*" + str r
  1134:   | refr_3 ?a => str a
  1135: ;
  1136: 
  1137: fun str : application_t -> string =
  1138:   | application_1 (?a,?c) => str a + " " + str c
  1139:   | application_2 ?c => "caseno " + str c
  1140:   | application_3 ?c => str c
  1141: ;
  1142: 
  1143: fun str : coercion_t -> string =
  1144:   | coercion_1 (?c,?f) => str c + " : " + str f
  1145:   | coercion_2 ?sn => str sn
  1146:   | coercion_3 ?f => str f
  1147: ;
  1148: 
  1149: 
  1150: fun str : factor_t -> string =
  1151:   | factor_1 ?dn => str dn
  1152:   | factor_2 (?f,?e) => str f + ".["+str e+"]"
  1153:   | factor_3 (?f,?e1,?e2) => str f + ".["+str e1+" to "+str e2+"]"
  1154:   | factor_4 (?f,?e) => str f + ".["+str e+" to]"
  1155:   | factor_5 (?f,?e) =>str f + ".[to "+str e+"]"
  1156:   | factor_6 (?f,?s) => str f + "." + str s
  1157:   | factor_7 (?f,(?s1,?s2)) => str f ".(" + s1+s2+")"
  1158: ;
  1159: 
  1160: fun str : dollar_name_t -> string =
  1161:   | dollar_name_1 ?qn => "$" + str qn
  1162:   | dollar_name_2 ?qn => "the " + str qn
  1163:   | dollar_name_3 ?qn => str qn
  1164:   | dollar_name_4 ?atom => str atom
  1165: ;
  1166: 
  1167: fun str: qualified_name_t -> string =
  1168:   | qualified_name_1 (?qn,?snp) => str qn + "::" + str snp
  1169:   | qualified_name_2 ?snp => str snp
  1170: ;
  1171: 
  1172: fun str : simple_name_parts_t -> string =
  1173:   | simple_name_parts_1 (?s,?ts) => s + "[" + str ts + "]"
  1174:   | simple_name_parts_2 ?s => s
  1175: ;
  1176: 
  1177: /*
  1178: fun str : type_expr_comma_list_t -> string =
  1179:   | type_expr_comma_list_1 (?t,?ts) => str t + ", " + str ts
  1180:   | type_expr_comma_list_2 ?t => str t
  1181:   | type_expr_comma_list_3 => ""
  1182: ;
  1183: */
  1184: 
  1185: fun str : suffixed_name_t -> string =
  1186:   | suffixed_name_1 (?qn,?t) => str qn + " of (" + str t + ")"
  1187: ;
  1188: 
  1189: fun str : atom_t -> string =
  1190:   | atom_1 => "..."
  1191:   | atom_2 _ => "typematch .. endmatch"
  1192:   | atom_3 (?e,?s) => "code["+str e + "] "+s
  1193:   | atom_4 (?e,?s) => "code["+str e + "] "+str s
  1194:   | atom_5 ?e => "["+str e+"]"
  1195:   | atom_6 ?e => "{"+str e+"]"
  1196:   | atom_7 _ => "parse .. endmatch"
  1197:   | atom_8 _ => "match .. endmatch"
  1198:   | atom_9 _ => "regmatch .. endmatch"
  1199:   | atom_10 _ => "{ ... }"
  1200:   | atom_11 ?e => "("+str e+")"
  1201:   | atom_12 => "()"
  1202:   | atom_13 ?e => str e
  1203:   | atom_14 _ => "if .. endif"
  1204: ;
  1205: 
  1206: fun str (t:expr_code_prefix_t):string =>
  1207:   let expr_code_prefix_1 ?e = t in str e
  1208: ;
  1209: 
  1210: fun str : literal_t -> string =
  1211:   | literal_1 (?s1,?s2) => s1 + s2
  1212:   | literal_2 ?s => s
  1213:   | literal_3 ?s => str s
  1214:   | literal_4 ?s => "c"+str s
  1215: ;
  1216: 
  1217: fun str (s:string):string => '"' + s '"'; // hacky .. fix
  1218: 
  1219: fun strint(i:string * string):string =>
  1220:   let ?i,?j = i in i+j
  1221: ;
  1222: 
  1223: fun str: opt_fun_args_t -> string =
  1224:   | opt_fun_args_1 ?a => str a
  1225:   | opt_fun_args_2 => "()"
  1226: ;
  1227: 
  1228: fun str: fun_args_t -> string =
  1229:   | fun_args_1 (?a,?args) => "(" (str a)  ") → " + str args
  1230:   | fun_args_2 ?a =>  str a
  1231: ;
  1232: 
  1233: fun str: fun_arg_t -> string =
  1234:   | fun_arg_1 (?ps,?traint) => str ps + " when " + str traint
  1235:   | fun_arg_2 ?ps => str ps
  1236:   | fun_arg_3 ?s => s
  1237: ;
  1238: 
  1239: fun str: parameter_comma_list_t -> string =
  1240:   | parameter_comma_list_1 (?a,?ps) => str a + " * " + str ps
  1241:   | parameter_comma_list_2 ?p => str p
  1242:   | parameter_comma_list_3 => ""
  1243: ;
  1244: 
  1245: fun str: parameter_t -> string =
  1246:   | parameter_1 (?name,?t) => str t
  1247:   | parameter_2 ?name => "'" + name
  1248:   | parameter_3 (?name,?t) => "var " + str t
  1249:   | parameter_4 ?name => "var " + "'" + name
  1250: ;
  1251: 
  1252: fun str: type_qual_t -> string =
  1253:   | type_qual_1 => "incomplete "
  1254:   | type_qual_2 => "pod "
  1255: ;
  1256: 
  1257: fun str: type_quals_t -> string =
  1258:   | type_quals_1 (?q,?qs') => str q + str qs'
  1259:   | type_quals_2 => ""
  1260: ;
  1261: 
  1262: fun str (name:basic_name_t): string =>
  1263:   let basic_name_1 ?name = name in name
  1264: ;
  1265: 
  1266: fun str :  basic_name_comma_list_t -> string =
  1267:   | basic_name_comma_list_1 (?name,?bncl) =>
  1268:         str name + ", " + str bncl
  1269:   | basic_name_comma_list_2 ?name => str name
  1270:   | basic_name_comma_list_3 => ""
  1271: ;
  1272: 
  1273: fun str : tvar_t -> string =
  1274:   | tvar_1 ?s => s
  1275:   | tvar_2 (?s,_) => s
  1276: ;
  1277: 
  1278: fun str :  tvar_comma_list_t -> string =
  1279:   | tvar_comma_list_1 (?name,?bncl) =>
  1280:         str name + ", " + str bncl
  1281:   | tvar_comma_list_2 ?name => str name
  1282:   | tvar_comma_list_3 => ""
  1283: ;
  1284: 
  1285: fun str : tvarlist_t -> string =
  1286:   | tvarlist_1 ?bncl => "[" + str bncl + "]"
  1287:   | tvarlist_2 => ""
  1288: ;
  1289: 
  1290: fun str : adjectives_t -> string =
  1291:   | adjectives_1 (?adj,?adjs) => str adj + str adjs
  1292:   | adjectives_2 => ""
  1293: ;
  1294: 
  1295: fun str : adjective_t -> string =
  1296:   | adjective_1 => "inline "
  1297:   | adjective_2 => "noinline "
  1298: ;
  1299: 
  1300: // regexps
  1301: fun str : re1_t -> string = // alternatives
  1302:   | re1_1 (?r1,?r2) => str r1 + " | " + str r2
  1303:   | re1_2 ?r => str r
  1304: ;
  1305: 
  1306: fun str : re2_t -> string = // concatenation
  1307:   | re2_1 (?r1,?r2) => str r1 + " " + str r2
  1308:   | re2_2 ?r => str r
  1309: ;
  1310: 
  1311: fun str : re3_t -> string = // postfix
  1312:   | re3_1 ?r => str r + "*"
  1313:   | re3_2 ?r => str r + "+"
  1314:   | re3_3 ?r => str r + "?"
  1315:   | re3_4 ?r => str r
  1316: ;
  1317: 
  1318: fun str : re4_t -> string =  // regexp atom
  1319:   | re4_1 ?s => str s
  1320:   | re4_2 => '_'
  1321:   | re4_3 => '.'
  1322:   | re4_4 ?r => '(' + str r + ")"
  1323:   | re4_5 ?cs => '[' + str cs + ']'
  1324:   | re4_6 ?cs => '[^' + str cs + ']'
  1325:   | re4_7 ?name => str name
  1326: ;
  1327: 
  1328: fun str : re_name_t -> string =
  1329:   | re_name_1 (?r,?s) => str r + "::" + str s
  1330:   | re_name_2 ?s => s
  1331: ;
  1332: 
  1333: fun str: charset_t -> string =
  1334:   | charset_1 (?cs,?cs0) => str cs + " " + str cs0
  1335:   | charset_2 ?cs0 => str cs0
  1336: ;
  1337: 
  1338: fun str: charset0_t -> string =
  1339:   | charset0_1 (?i1,?i2) => strint i1 + " - " + strint i2
  1340:   | charset0_2 (?s1,?s2) => str s1 + " - " + str s2
  1341:   | charset0_3 ?s => str s
  1342:   | charset0_4 ?i => strint i
  1343: ;
  1344: 
  1345: fun str: glr_entries_t -> string =
  1346:   | glr_entries_1 (?g,?gs) => str g + " " + str gs
  1347:   | glr_entries_2 ?g => str g
  1348: ;
  1349: 
  1350: fun str: glr_entry_t -> string =
  1351:   | glr_entry_1 (?name,?nt) => name + " : " + str nt
  1352:   | glr_entry_2 ?qn => str qn
  1353: ;
  1354: 
  1355: fun str: glr_term_t -> string =
  1356:   | glr_term_1 ?qn => str qn
  1357:   | glr_term_2 ?alts => "(" + "..." + "}"
  1358:   | glr_term_3 ?seq => "(" + "..." + ")"
  1359:   | glr_term_4 ?quest => "(" + str quest+ ")?"
  1360:   | glr_term_5 ?star => "(" + str star + ")*"
  1361:   | glr_term_6 ?plus => "(" + str plus + ")+"
  1362: ;
  1363: 
End felix section to tools/flx_doc.flx[1]


7.1. Misc