*/
Stuck? Need help? Ask questions on our forums.
*/

View \LEXER.C

An 8031/8051 assembler win source

Submitted By: Unknown
Rating: starstarstarstar (Rate It)


/*
 * lexer.c
 * PACKAGE: as31 - 8031/8051 Assembler.
 *
 * DESCRIPTION:
 *      This file contains the lexical tokenizer for the assembler.
 *      Since yacc is being used the lexer is called yylex().
 *
 *      In order to produce a listing, some record of the users
 *      source line must be kept. This is done by adding
 *      get_ch(), and unget_ch() routine which returns/ungets a character
 *      but also places information into a secret array.
 *
 *      When a newline is encountered the text line is returned as
 *      an attribute on the '\n' character.
 *
 * REVISION HISTORY:
 *      Jan. 19, 1990 - Created. (Ken Stauffer)
 *
 * AUTHOR:
 *      All code in this file written by Ken Stauffer (University of Calgary).
 *      January, 1990.
 */


#include <stdio.h>
#include <ctype.h>

#include "as31.h"

extern union ystack yylval;
extern int pass;

struct symbol *looksym();
struct opcode *lookop();
char    *malloc();
int     lineno;

static char line[100], *lineptr = line;

/*
 * get_ch:
 *      Get a character from stdin, place char in line[]
 */


int get_ch()
{
        register int    c;

        c = getchar();
        if (c != EOF && lineptr - line < sizeof(line))
                *lineptr++ = c;

        return(c);
}

/*
 * unget_ch:
 *      Unget a character and move lineptr back by one.
 */


void unget_ch(c)
int     c;
{
        ungetc(c, stdin);

        if (lineptr > line)
                lineptr--;
}

/*
 * yylex:
 *      The tokens themselves are returned via return(token)
 *
 *      Some tokens have attributes. These attributes are returned
 *      by setting a global variable yylval:
 *
 *            yylval.value
 *                  numbers (any base)
 *                  strings (in pass 1).
 *                  bit positions .0, .1, .2, ...
 *
 *            yylval.str
 *                  strings (in pass 2).
 *                  '\n' (both passes).
 *
 *            yylval.sym
 *                  User defined symbols.
 *
 *            yylval.op
 *                  Reserved keyword (opcode/directive/misc.)
 *
 *            No other fields in yylval are used by yylex().
 *
 *            Characters that do not have an attribute do
 *            not set anything in the yylval variable.
 */


int yylex()
{
        static int      nl_flag = 0/* sync. error messages and the cur. line */
        int          c;
        char        buf[120];   /* temporary buffer */
        char        *p;  /* general pointer */
        struct symbol   *sym;
        struct opcode   *op;
        int          octal = 0, hex = 0, decimal = 0, binary = 0;
        long        value = 0L;

        if (nl_flag)  {
                nl_flag = 0;
                lineno++;
        }

        for (;;)  {
                c = get_ch();
                switch (c)  {
                case EOF:
                        return(EOF);
                case ' ':
                case '\t':
                        break;
                case '\n':
                        nl_flag = 1;
                        yylval.str = line;
                        *lineptr = '\0';
                        lineptr = line;

                        return('\n');
                case ';':
                        while ((c = get_ch()) != EOF && c != '\n')
                                ;
                        nl_flag= 1;
                        yylval.str = line;
                        *lineptr = '\0';
                        lineptr = line;

                        return(c);
                case '"':
                        p = buf;
                        while ((c = get_ch()) != EOF && c!='"' && c!='\n') {
                                if ( c == '\\' ) {
                                        switch (c = get_ch())  {
                                        case 'n':
                                                c = '\n';
                                                break;
                                        case 'r':
                                                c = '\r';
                                                break;
                                        case 't':
                                                c = '\t';
                                                break;
                                        case 'b':
                                                c = '\b';
                                                break;
                                        case '"':
                                                c = '"';
                                                break;
                                        case '\\':
                                                c = '\\';
                                                break;
                                        default:
                                                error("Invalid escape character: \\%c", c);
                                                break;
                                        }
                                }

                                if ( p-buf < sizeof(buf)-1 )
                                        *p++ = c;
                                else {
                                        error("String constant longer than %d bytes", sizeof(buf));
                                }
                        }

                        *p = '\0';
                        if ( c == '\n' || c == EOF )  {
                                error("String terminated improperly.");
                                unget_ch(c);
                        }

                        if (pass1)
                                yylval.value = strlen(buf);
                        else {
                                if ( (p = malloc(strlen(buf)+1)) == NULL )
                                        error("Cannot allocate %d bytes", strlen(buf)+1);

                                strcpy(p, buf);
                                yylval.str = p;
                        }

                        return(STRING);
                case '.':
                        if ( (c = get_ch()) >= '0' && c <= '7' )  {
                                yylval.value = c - '0';
                                return(BITPOS);
                        }

                        unget_ch(c);
                        return('.');

                case '\'':
                        c = get_ch();
                        if ( c == '\\' )  {
                                switch (c = get_ch())  {
                                case 'n':
                                        c = '\n';
                                        break;
                                case 'r':
                                        c = '\r';
                                        break;
                                case 't':
                                        c = '\t';
                                        break;
                                case 'b':
                                        c = '\b';
                                        break;
                                case '\\':
                                        c = '\\';
                                        break;
                                case '\'':
                                        c = '\'';
                                        break;
                                default:
                                        error("Invalid escape character: \\%c", c);
                                }
                        }

                        if ( get_ch() != '\'' )
                                error("Missing quote in character constant");

                        yylval.value = c;
                        return(VALUE);

                case '0':       /* parse a number                  */
                case '1':       /* could be followed by a:          */
                case '2':       /*     'b','B' - Binary          */
                case '3':       /*     'h','H' - Hex                        */
                case '4':       /*     'd','D' - Decimal        */
                case '5':       /*     'o','O' - Octal                  */
                case '6':       /* *** Numbers must start with a digit */
                case '7':       /* Numbers could be also preceeded by:  */
                case '8':       /*     0x   - Hex,     0b     - binary */
                case '9':       /*     0    - Octal               */

                        p = buf;
                        do {
                                if ( p-buf<sizeof(buf)-1 )
                                        *p++ = c;

                                c = get_ch();
                        } while ( c == 'H' || c == 'h' || c == 'O' || c == 'o' ||
                                c == 'x' || c == 'X' || isxdigit(c) );

                        unget_ch(c);
                        *p = '\0';

                        /* Check any preceeding chars */

                        if ( buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X') )  {
                                hex++;
                                buf[1] = '0';
                        } else if ( buf[0] == '0' && (buf[1] == 'b' || buf[1] == 'B') )  {
                                binary++;
                                buf[1] = '0';
                        } else if ( buf[0] == '0' )
                                octal++;

                        /* check any trailing chars */

                        c = *(p-1);
                        if ( !hex && (c == 'b' || c == 'B') )  {
                                binary++;
                                *(p-1) = '\0';
                        } else if ( c == 'H' || c == 'h' )  {
                                hex++;
                                *(p-1) = '\0';
                        } else if ( !hex && (c == 'D' || c == 'd') )  {
                                decimal++;
                                *(p-1) = '\0';
                        } else if ( c == 'O' || c == 'o' )  {
                                octal++;
                                *(p-1) = '\0';
                        } else if ( !hex && !octal && !binary)
                                decimal++;

                        if ( binary )  {
                                for (p = buf; *p; p++ )  {
                                        if ( *p == '1' )
                                                value = value << 1 + 1;
                                        else if ( *p == '0' )
                                                value = value << 1;
                                        else
                                                error("Invalid binary digit: %c", *p);
                                }

                                yylval.value = value;
                                return(VALUE);
                        }

                        if ( hex )  {
                                for (p = buf; *p; p++ )  {
                                        value <<= 4;

                                        if (isdigit(*p))
                                                value += *p-'0';
                                        else if( *p>='a' && *p<='f' )
                                                value += *p-'a'+ 10;
                                        else if( *p>='A' && *p<='F' )
                                                value += *p-'A'+ 10;
                                        else
                                                error("Invalid hex digit: %c", *p);
                                }

                                yylval.value = value;
                                return(VALUE);
                        }

                        if (decimal)  {
                                for (p = buf; *p; p++)  {
                                        if (isdigit(*p))
                                                value = value*10 + *p-'0';
                                        else
                                                error("Invalid decimal digit: %c", *p);
                                }

                                yylval.value = value;
                                return(VALUE);
                        }

                        if (octal)  {
                                for (p = buf; *p; p++)  {
                                        if (*p >= '0' && *p <= '7')
                                                value = value << 3 + *p - '0';
                                        else
                                                error("Invalid octal digit: %c", *p);
                                }

                                yylval.value = value;
                                return(VALUE);
                        }

                default:
                        if (isalpha(c) || c == '_')  {
                                p = buf;

                                do {
                                        if (p - buf < sizeof(buf) - 1)
                                                *p++ = c;

                                        c = get_ch();
                                } while (isalnum(c) || c == '_');

                                *p = '\0';
                                unget_ch(c);

                                if (op = lookop(buf))  {
                                        yylval.op = op;
                                        return(op->type);
                                }

                                sym = looksym(buf);
                                yylval.sym = sym;
                                return(SYMBOL);
                        } else
                                return(c);
                } /* switch */
        } /* for */
} /* yylex */

corner
© 1996-2008 CommunityHeaven LLC. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
North American business development: Nicolai Wadstrom. Publisher: Lars Hagelin.