File:  [NeXTSTEP 3.3 examples] / Examples / AppKit / Graph / token.lm
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:48:25 2018 UTC (8 years, 1 month ago) by root
Branches: NeXT, MAIN
CVS tags: NeXTSTEP33, HEAD
Sample Programs from NeXSTEP 3.3


%{
/*
    token.lm

    This file defines the tokens that the Expression grammar is built on.  To
    fully understand this file, you will need to understand lex.  The basic
    idea is that lex scans a text stream and breaks that stream up into tokens
    which are then fed to the grammar (defined in yacc).  Whitespace is ignored
    so the grammar is just fed a steady stream of significant tokens.
*/

/*
 * These are the routines lex calls to get another character as it parses.
 * By default they are macros which read from stdin. We toss the default
 * macro definitions and supply our own versions of these, which will feed
 * lex characters from the expression string we are parsing.
 */
#undef input
#undef unput
#undef output
static int input();
static void unput(char c);
static void output(char c);

#import <stdlib.h>
#import <string.h>
#import <math.h>
#import "exprDefs.h"
#import "y.tab.h"

/* global which holds the string we are parsing */
static const char *CurrText;

/* glue to get rid of compiler warnings */
extern yylook(), yyback();
static int yywrap();
%}

DIGIT    ([0-9])
EXP      ([Ee][+-]?[0-9]+)

%%


[ \t\n]+ {		/* whitespace - we ignore it */
	;
}

{DIGIT}+ {		/* an integer */
	yylval.integer = atoi(yytext);
	return INTEGER;
}

(({DIGIT}+"."{DIGIT}*{EXP}?)|([+-]?{DIGIT}*"."{DIGIT}+{EXP}?)|({DIGIT}+{EXP})) {                   /* a float */
	yylval.real = atof(yytext);
	return NUMBER;
}

{DIGIT}+"#"[a-zA-Z0-9]+ {	/* a radix number */
	int radix;
	register int mult = 1;
	register char *c, *stop;
	register unsigned int accum = 0;
	register int charVal;

	sscanf( yytext, "%d#", &radix );
	for( stop = yytext; *stop++ != '#'; ); /* skip the pound sign */
	for( c = yytext+yyleng-1; c >= stop; c--, mult *= radix ) {
	    if( *c >= '0' && *c <= '9' )
		charVal = *c - '0';
	    else if( *c >= 'A' && *c <= 'Z' )
		charVal = *c - 'A' + 10;
	    else
		charVal = *c - 'a' + 10;
	    accum += mult * charVal;
	}
	yylval.real = accum;
	return NUMBER;
}

pi {			/* the constant pi */
	yylval.real = M_PI;
	return NUMBER;
}

e {			/* the constant e */
	yylval.real = M_E;
	return NUMBER;
}

[-+*/%^(),]  {			/* a single char that must be recognized */
	return yytext[0];
}

[A-Za-z_][A-Za-z_0-9]* {	/* an identifier */
	yylval.string = NXZoneMalloc(NXDefaultMallocZone(), yyleng+1); 
	bcopy(yytext, yylval.string, yyleng);
	yylval.string[yyleng] = '\0';
	return IDENTIFIER;
}

. {		/* other garbage chars (last rule is the default) */
	yylval.character = yytext[0];
	return BADCHAR;
}


%%

/* inits the global string to the one we will parse */
void _EXPPrepareToScan(const char *text) {
    CurrText = text;
}

/* tells lex there's really no more input when we're done */
static int yywrap() {
    return 1;
}

/* returns the next char of the string we're parsing */
static int input() {
    return *CurrText++;
}

/* lets lex back up one char in the string we're parsing */
static void unput(char c) {
    --CurrText;
}

/* called by lex when it wants to output a char.  This should never happen. */
static void output(char c) {
    fprintf(stderr, "lex output function called with char '%c'\n", c);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.