/*
 * javafx.ft -- experimental Pretzel token file for Java
 *
 * based on original version by Lee Wittenberg and enhanced
 * for use with noweb
 *
 * History at end
 *
 * $Header$
 *
 */

ALPH		[a-zA-Z_$]
ALPHNUM		[a-zA-Z0-9_$]
DIGIT		[0-9]
DECDIGIT	[0-9]
OCTDIGIT	[0-7]
HEXDIGIT	[0-9A-Fa-f]
EXP			([eE][+-]?[0-9]+)

%{

#include<assert.h>

  // forward declaration of a function that replaces `_'
  // with `\_' in a copy of s (don't need it here though)

static char* escaped_underlines(char* s);

%}


%%

	//
	// symbols

"{"		LBRACE	{"\\{"}
"}"		RBRACE	{"\\}"}
"("		LPAR
")"		RPAR
"["		LBRACK
"]"		RBRACK
";"		SEMI	{"\\mathout; "}
":"		COLON	{":"}
","		COMMA	{"\\mathout, "}
"."		DOT		{"{.}"}

"+"		|
"-"		UNORBINOP
"="		BINOP	{"\\gets"}
"<"		|
">"		BINOP
"!"		UNOP	{"\\lnot"}
"~"		UNOP	{"\\~{}"} // Lee said: {"\\mathord{\\sim}"}
"?"		QUESTION	{"\\mathrel?"}
"=="		BINOP	{"\\equiv"}
"<="		BINOP	{"\\leq"}
">="		BINOP	{"\\geq"}
"!="		BINOP	{"\\neq"}
"||"		BINOP	{"\\lor"}
"&&"		BINOP	{"\\land"}
"++"		|
"--"		INCROP	{"\\mbox{\\tt" + ** + "}"}
"*"		BINOP	{"\\times"}
"/"		BINOP	{"\\div"}
"&"		BINOP	{"\\mathrel{\\&}"}
"|"		BINOP	{"\\mid"}
"^"		BINOP	{"\\oplus"}
"%"		BINOP	{"\\mathbin{\\%}"}
"<<"		BINOP	{"\\ll"}
">>"		BINOP	{"\\gg"}
">>>"		BINOP	{"\\ggg"}				// needs amssymb package
"+="		BINOP	{"\\buildrel\\;+\\over{\\gets}"}
"-="		BINOP	{"\\buildrel\\;-\\over{\\gets}"}
"*="		BINOP	{"\\buildrel\\;\\times\\over{\\gets}"}
"/="		BINOP	{"\\buildrel\\;\\div\\over{\\gets}"}
"&="		BINOP	{"\\buildrel\\;\\&\\over{\\gets}"}
"|="		BINOP	{"\\buildrel\\;\\mid\\over{\\gets}"}
"^="		BINOP	{"\\buildrel\\;\\oplus\\over{\\gets}"}
"%="		BINOP	{"\\buildrel\\;\\%\\over{\\gets}"}
"<<="		BINOP	{"\\buildrel\\;\\ll\\over{\\gets}"}
">>="		BINOP	{"\\buildrel\\;\\gg\\over{\\gets}"}
">>>="		BINOP	{"\\buildrel\\;\\ggg\\over{\\gets}"}	// needs amssymb package

  // try to mimic CWEB explicit format commands:

"//@/"		|
"//@force"	IGNORE { force }
"//@#"		|
"//@big_force"  IGNORE { big_force }
"//@cancel"	IGNORE { cancel }


"//".*		COMMENT	{"\\mbox{" ** "}" force }

	//
	// keywords


"new"		UNOP		{"\\mbox{\\bf " + ** + "}\\ "}
"instanceof" BINOP		{"\\in"}
		// alternate:	{"\\mathrel{\\mbox{\\bf " + ** + "}}"}

  // make INT_LIKE (not ID_LIKE) to avoid indexing:

"null"		INT_LIKE		{"\\mathin\\Lambda"}

"class"		CLASS
"interface"	CLASS

"boolean"	|
"byte"		|
"char"		|
"double"	|
"float"		|
"int"		|
"long"		|
"String"	|               // is also a simple type!
"short"		INT_LIKE	{"\\mbox{\\bf " + ** + "}"}

				// to catch void function definitions
				// (Lee said: ID_LIKE)
"void"		INT_LIKE        {"\\mbox{\\bf " + ** + "}"}

  // modifiers were ID_LIKE, make them INT_LIKE to avoid indexing

"abstract"	|
"final"		|
"native"	|
"protected"	|
"private"	|
"public"	|
"static"	|
"transient"	|
"volatile"	INT_LIKE		{ "\\mbox{\\bf " ** "}" }

"true"		|
"false"		|
"super"		|    // for Lee, all these were ID_LIKE.
"this"		INT_LIKE			{"\\mbox{\\bf " + ** + "}"}

"case"		CASE_LIKE		{"\\mbox{\\bf " + ** + "}"}
"default"	DEFAULT_LIKE	{"\\mbox{\\bf " + ** + "}"}

"synchronized"	SYNC_LIKE	{"\\mbox{\\bf " + ** + "}"}


"try"		TRY_LIKE		{"\\mbox{\\bf " + ** + "}"}
"catch"		CATCH_LIKE		{"\\mbox{\\bf " + ** + "}"}
"finally"	FINALLY_LIKE	{"\\mbox{\\bf " + ** + "}"}

"if"		|
"switch"	|
"while"		IF_LIKE			{"\\mbox{\\bf " + ** + "}"}

"else"		ELSE_LIKE		{"\\mbox{\\bf " + ** + "}"}

"for"		FOR_LIKE		{"\\mbox{\\bf " + ** + "}"}
"do"		DO_LIKE			{"\\mbox{\\bf " + ** + "}"}

"break"		|
"continue"	|
"return"	|
"throw"		BREAK_LIKE		{"\\mbox{\\bf " + ** + "}"}

"throws"	|
"extends"	|
"implements" 	EXTENDS_LIKE	{"\\mbox{\\bf " + ** + "}"}

"package"	|
"import"	IMPORT_LIKE		{"\\mbox{\\bf " + ** + "}"}
".*"		DOT_STAR	{ ".*" }
			// Lee said: {"\\mathin.\\mathord{\\ast}"}

	//
	// misc

^"@use\ ".*	CHUNK	{ "\n" + ** + "\n" }
^"@".*		IGNORE	{ "\n" + ** + "\n" }

0[lL]?					|
[1-9]{DECDIGIT}*[lL]?			|
0{OCTDIGIT}+[lL]?			|
0[xX]{HEXDIGIT}{HEXDIGIT}*[lL]?		|
{DECDIGIT}+"."{DECDIGIT}*{EXP}?[fdFD]?	|
"."{DECDIGIT}+{EXP}?[fdFD]?		|
{DECDIGIT}+{EXP}[fdFD]?			NUM

  // identifiers are passed `as is' to the parser.
  // We could escape underlines here, but we'll better leave
  // that to the parser.


  // a distinction between short ids and long ids is made to spare
  // short identifiers from getting into the index. This is done
  // here because it's easiest to check the length here. SHORT_IDs
  // will be treated just like ID_LIKEs from now on except indexing.

{ALPH}			SHORT_ID


{ALPH}{ALPHNUM}*	ID_LIKE


'([^']|\\')*'		|
\"([^\"]|\\\")*\"	STRING	{"\\verb*\013" + ** + "\013"}

[\ \t\n]				// gobble up whitespace

.						// ignore all non-standard chars
						// (bug in Pretzel?)
%%

  // escaped_underines replaces every occurrence of `_' by
  // the two characters `\_' in a copy of the string pointed to
  // by s
  //
  // the implementation first counts the number of underlines in
  // the string s and allocates new memory for the string. It then
  // copies the string byte after byte into the new place and
  // takes care to insert a `\' before any underline.
  //
  // this is a bit dirty as we don't have a chance to free the
  // allocated space later on, but it's still better than messing
  // around with yytext. To minimize the amount of memory I have
  // added a test whether copying is needed or not.

static char* escaped_underlines(char* s)
{
    char* tmp = s;
    int number_of_ul = 0;
    int left = 0;   // s[left] is the next char to copy
    int right = 0;  // place s[left] in tmp[right]

    // fprintf(stderr, "call of escaped_underlines\n");

    // count underlines in s
    while (*tmp != 0) {
        if (*tmp == '_') number_of_ul++;
        tmp++;
    }

    // fprintf(stderr, "escaped_underlines: Number of ul's in %s is %d\n", s, number_of_ul);

    if (number_of_ul == 0) {
      tmp = s;  // skip copying
    } else {

      tmp = new char[strlen(s) + number_of_ul + 1];
      assert(tmp!=NULL);

      // now start to copy
      while (s[left] != 0) { // should be `!= NULL', shouldn,t it, but
                             // some compilers choke on it
          if (s[left] == '_') {
              tmp[right] = '\\';
              right++;
          }
          tmp[right] = s[left];
          left++; right++;
      }
      tmp[right] = s[left];  /* terminate string */
    }

    // fprintf(stderr, "escaped_underlines: in: %s, out: %s\n", s, tmp);

    return(tmp);
}

/*
 * $Log: javafx.ft,v $
 * Revision 1.1  1997/07/09 14:24:27  gaertner
 * Initial revision
 *
 * Revision 1.2  1997/07/08 18:48:34  theedge
 * Versions that work.
 *
 * Revision 1.1  1997/06/26 16:23:56  theedge
 * Initial revision
 *
 */
