297 lines
5.3 KiB
C
297 lines
5.3 KiB
C
#include "Lpars.h"
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
|
|
/* This file contains the function mylex() which recognizes the following
|
|
* tokens :
|
|
* EOFILE
|
|
* C_INSTR - 'C_loc', 'C_lol', etc.
|
|
* DEF_C_INSTR - 'C_loe..', 'C_ste..', '..icon, '..fcon', etc
|
|
* CONDITION - C-expression, for example: '$1 == 481'
|
|
* ARROW - '==>'
|
|
* CALL - C-style functioncall, for example: 'error( 17)'
|
|
* ASSEM_INSTR - C-style string, for example: '"mov r0, (r1)"'
|
|
* DEFAULT - 'default'
|
|
* ERROR - An error occured in one of the tokens.
|
|
*
|
|
* If the input matches non of these tokens the next character will be returned.
|
|
*
|
|
* Besides mylex() the following variable is exported :
|
|
*
|
|
* char yytext[]; - Contains the string representation of the current
|
|
* token.
|
|
* char *next; - Points to the first free position in yytext[].
|
|
*/
|
|
|
|
|
|
#define YYTEXT 4096
|
|
char yytext[YYTEXT], /* string-buffer for the token */
|
|
*next; /* points to the first free posistion in yytext[] */
|
|
extern char scanc();
|
|
|
|
#define FALSE 0
|
|
#define TRUE 1
|
|
|
|
int CD_pos = FALSE; /* 'CD_pos' is used as a flag to signal if it is
|
|
* possible to match a CONDITION or DEFAULT-token at
|
|
* this moment. Thus mylex() knows about the grammar
|
|
* of the "EM_table"!!
|
|
* This flag is needed because CALL is a subset of
|
|
* CONDITION.
|
|
*/
|
|
int CALL_pos = FALSE; /* Needed to distinguish between
|
|
* C_INSTR CONDITION and CALL
|
|
*/
|
|
|
|
|
|
|
|
int mylex()
|
|
{
|
|
char c, skip_space();
|
|
|
|
static int special = FALSE; /* rule with conditions + default ? */
|
|
|
|
next = yytext;
|
|
c = *next++ = skip_space();
|
|
switch ( c) {
|
|
case EOF : next = yytext;
|
|
return( 0);
|
|
|
|
case '"' : read_string();
|
|
return( ASSEM_INSTR);
|
|
|
|
case '.' : c = scanc();
|
|
backc( c);
|
|
if ( c != '.') { /* Just a plain '.', not something like
|
|
* '..icon'.
|
|
*/
|
|
if ( special)
|
|
CD_pos = TRUE;
|
|
CALL_pos = FALSE;
|
|
return( '.');
|
|
}
|
|
break;
|
|
|
|
case ';' : return( ';');
|
|
|
|
case '=' : if ( arrow()) {
|
|
CD_pos = FALSE;
|
|
CALL_pos = TRUE;
|
|
return( ARROW);
|
|
}
|
|
break;
|
|
|
|
case 'd' : if ( CD_pos && _default()) {
|
|
CD_pos = FALSE;
|
|
special = FALSE;
|
|
return( DEFAULT);
|
|
}
|
|
break;
|
|
}
|
|
/* Possible tokens at this place : CONDITION, CALL, C_INSTR,
|
|
* DEF_C_INSTR
|
|
*/
|
|
|
|
if ( CD_pos) {
|
|
read_condition();
|
|
CD_pos = FALSE;
|
|
special = TRUE;
|
|
return( CONDITION);
|
|
}
|
|
if ( isalpha( c)) {
|
|
read_ident();
|
|
if ( CALL_pos) {
|
|
c = skip_space();
|
|
if ( c == '(') {
|
|
*next++ = c;
|
|
read_call();
|
|
return( CALL);
|
|
}
|
|
else {
|
|
backc( c);
|
|
return( ERROR);
|
|
}
|
|
}
|
|
else {
|
|
if ( is_DEF_C_INSTR( yytext)) {
|
|
CD_pos = TRUE;
|
|
return( DEF_C_INSTR);
|
|
}
|
|
if ( is_C_INSTR( yytext)) {
|
|
CD_pos = TRUE;
|
|
return( C_INSTR);
|
|
}
|
|
return( ERROR);
|
|
}
|
|
}
|
|
if ( c == '.') {
|
|
c = scanc();
|
|
if ( c == '.') {
|
|
*next++ = '.';
|
|
read_ident();
|
|
if ( is_DEF_C_INSTR( yytext)) {
|
|
CD_pos = TRUE;
|
|
return( DEF_C_INSTR);
|
|
}
|
|
return( ERROR);
|
|
}
|
|
else {
|
|
backc( c);
|
|
return( '.');
|
|
}
|
|
}
|
|
return( c);
|
|
}
|
|
|
|
static int isletter( c)
|
|
char c;
|
|
{
|
|
return( isalpha( c) || isdigit( c) || c == '_');
|
|
}
|
|
|
|
static char skip_space()
|
|
{
|
|
char c;
|
|
|
|
while ( isspace( c = scanc()))
|
|
;
|
|
return( c);
|
|
}
|
|
|
|
|
|
/* first character has been read */
|
|
|
|
|
|
static read_string()
|
|
|
|
/* match something like "mov r0, (r1)".
|
|
* strip the double quotes off! Inside a string, the character '"' must
|
|
* be preceded by a '\'.
|
|
*/
|
|
{
|
|
next--;
|
|
while( ( *next = scanc()) != '"' || *(next-1) == '\\')
|
|
next++;
|
|
}
|
|
|
|
int arrow() /* '==>' */
|
|
{
|
|
if ( ( *next++ = scanc()) == '=')
|
|
if ( ( *next++ = scanc()) == '>')
|
|
return( TRUE);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
return( FALSE);
|
|
}
|
|
|
|
int _default() /* 'default' */
|
|
{
|
|
char c, skip_space();
|
|
|
|
if ( ( *next++ = scanc()) == 'e')
|
|
if ( ( *next++ = scanc()) == 'f')
|
|
if ( ( *next++ = scanc()) == 'a')
|
|
if ( ( *next++ = scanc()) == 'u')
|
|
if ( ( *next++ = scanc()) == 'l')
|
|
if ( ( *next++ = scanc()) == 't')
|
|
if ( !isletter( c = skip_space())) {
|
|
backc( c);
|
|
return( TRUE);
|
|
}
|
|
else
|
|
backc( c);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
return( FALSE);
|
|
}
|
|
|
|
read_ident()
|
|
{
|
|
char c;
|
|
|
|
while ( isletter( c = scanc()))
|
|
*next++ = c;
|
|
backc( c);
|
|
}
|
|
|
|
read_call()
|
|
{
|
|
int n = 1;
|
|
|
|
while ( TRUE)
|
|
switch( *next++ = scanc()) {
|
|
case EOF : return;
|
|
|
|
case '(' : n++;
|
|
break;
|
|
|
|
case ')' : n--;
|
|
if ( n == 0)
|
|
return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
read_condition()
|
|
|
|
/* A CONDITION is followed by '==>'
|
|
*/
|
|
{
|
|
while ( TRUE) {
|
|
switch ( *next++ = scanc()) {
|
|
case EOF : return;
|
|
|
|
case '=' : if ( arrow()) {
|
|
backc( '>');
|
|
backc( '=');
|
|
backc( '=');
|
|
next -= 3;
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
is_C_INSTR( str)
|
|
char *str;
|
|
{
|
|
if ( *str == 'C' && *(str+1) == '_') /* C_xxx */
|
|
return( TRUE);
|
|
else
|
|
return( FALSE);
|
|
}
|
|
|
|
is_DEF_C_INSTR( str)
|
|
char *str;
|
|
|
|
/* yytext[] contains either '..[letter]*' ( 2 dots possibly followed by an
|
|
* identifer) * or '[letter]+' ( just an identifier)
|
|
* Try to match something like 'C_loe..' or '..icon'
|
|
*/
|
|
{
|
|
if ( *str == '.' && *(str+1) == '.')
|
|
return( next > yytext+1);
|
|
|
|
if ( ( *next++ = scanc()) == '.')
|
|
if ( ( *next++ = scanc()) == '.')
|
|
return( next > yytext+1);
|
|
else
|
|
backc( *--next);
|
|
else
|
|
backc( *--next);
|
|
return( FALSE);
|
|
}
|