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


7.1. Misc