Initial revision
This commit is contained in:
309
util/ceg/as_parser/eval/eval.c
Normal file
309
util/ceg/as_parser/eval/eval.c
Normal file
@@ -0,0 +1,309 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "states.h"
|
||||
|
||||
|
||||
#define is_letter( c) ( isalpha( c) || isdigit( c) || c == '_')
|
||||
#define save_or_put(c) if(previous_state==TEXT)putchar(c);else *bufptr++=c
|
||||
|
||||
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
char buffer[256], *bufptr = buffer;
|
||||
int c, state = TEXT, previous_state = TEXT, depth = 0;
|
||||
|
||||
pr_header();
|
||||
while ( ( c = getchar()) != EOF)
|
||||
switch ( state) {
|
||||
case TEXT :
|
||||
switch ( c) {
|
||||
case '/' : state = SLASH;
|
||||
previous_state = TEXT;
|
||||
save_or_put( c);
|
||||
break;
|
||||
case '"' : state = STRING;
|
||||
previous_state = TEXT;
|
||||
save_or_put( c);
|
||||
break;
|
||||
case '\'': state = CHAR_CONST;
|
||||
previous_state = TEXT;
|
||||
save_or_put( c);
|
||||
break;
|
||||
case '@' : state = AT;
|
||||
break;
|
||||
default : putchar( c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case SLASH :
|
||||
state = ( c == '*' ? COMMENT : TEXT);
|
||||
save_or_put( c);
|
||||
break;
|
||||
case COMMENT :
|
||||
if ( c == '*')
|
||||
state = STAR;
|
||||
save_or_put( c);
|
||||
break;
|
||||
case STAR :
|
||||
if ( c == '/')
|
||||
state = previous_state;
|
||||
else if ( c != '*')
|
||||
state = COMMENT;
|
||||
save_or_put( c);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case STRING :
|
||||
if ( c == '"')
|
||||
state = previous_state;
|
||||
else if ( c == '\\')
|
||||
state = BACKSLASH_in_STRING;
|
||||
save_or_put( c);
|
||||
break;
|
||||
|
||||
case BACKSLASH_in_STRING :
|
||||
state = STRING;
|
||||
save_or_put( c);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
case CHAR_CONST :
|
||||
if ( c == '\'')
|
||||
state = previous_state;
|
||||
else if ( c == '\\')
|
||||
state = BACKSLASH_in_CHAR_CONST;
|
||||
save_or_put( c);
|
||||
break;
|
||||
|
||||
case BACKSLASH_in_CHAR_CONST :
|
||||
state = CHAR_CONST;
|
||||
save_or_put( c);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case AT : /* @if '(' <CONDITION> ')'
|
||||
* @elsif '(' <CONDITION> ')'
|
||||
* @else
|
||||
* @fi
|
||||
* @<IDENTIFIER> '(' <PARAM_LIST> ')'
|
||||
*/
|
||||
if ( is_letter( c))
|
||||
*bufptr++ = c;
|
||||
else {
|
||||
ungetc( c, stdin);
|
||||
state = WHITE_SPACE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WHITE_SPACE :
|
||||
if ( isspace( c))
|
||||
*bufptr++ = c;
|
||||
else if ( c == '(') {
|
||||
*bufptr++ = c;
|
||||
depth = 1;
|
||||
state = CAL_or_QUEST;
|
||||
}
|
||||
else {
|
||||
*bufptr = '\0';
|
||||
pr_ELSE_or_FI( buffer);
|
||||
bufptr = buffer;
|
||||
ungetc( c, stdin);
|
||||
state = TEXT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CAL_or_QUEST : /* match ')' */
|
||||
*bufptr++ =c;
|
||||
switch ( c) {
|
||||
case '(' : depth++;
|
||||
break;
|
||||
case ')' : depth--;
|
||||
if ( depth == 0) {
|
||||
*bufptr = '\0';
|
||||
pr_CALL_or_QUEST( buffer);
|
||||
bufptr = buffer;
|
||||
state = TEXT;
|
||||
}
|
||||
break;
|
||||
case '/' : state = SLASH;
|
||||
previous_state = CAL_or_QUEST;
|
||||
break;
|
||||
case '"' : state = STRING;
|
||||
previous_state = CAL_or_QUEST;
|
||||
break;
|
||||
case '\'': state = CHAR_CONST;
|
||||
previous_state = CAL_or_QUEST;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
fprintf( stderr, "Unknown state : %d\n", state);
|
||||
break;
|
||||
}
|
||||
exit( 0);
|
||||
}
|
||||
|
||||
pr_header()
|
||||
{
|
||||
printf( "#include \"as_parser.h\"\n");
|
||||
printf( "#line 1 \"as.c\"\n");
|
||||
}
|
||||
|
||||
|
||||
pr_ELSE_or_FI( str)
|
||||
char *str;
|
||||
{
|
||||
if ( strncmp( str, "else", 4) == 0)
|
||||
printf( "fprint( outfile, \"}\else {\");%s", str+4);
|
||||
else if ( strncmp( str, "fi", 2) == 0)
|
||||
printf( "fprint( outfile, \"}\");%s", str+2);
|
||||
else
|
||||
fprintf( stderr, "%s unexpected!!\n", str);
|
||||
}
|
||||
|
||||
|
||||
pr_CALL_or_QUEST( str)
|
||||
char *str;
|
||||
{
|
||||
if ( strncmp( str, "if", 2) == 0 && !(is_letter( *(str+2))))
|
||||
pr_if( str);
|
||||
else if ( strncmp( str, "elsif", 5) == 0 && !(is_letter( *(str+5))))
|
||||
pr_elsif( str);
|
||||
else
|
||||
pr_call( str);
|
||||
}
|
||||
|
||||
|
||||
pr_call( call)
|
||||
char *call;
|
||||
{
|
||||
if ( strncmp( "text", call, 4) == 0 && isdigit( *(call+4)))
|
||||
printf( "cur_pos += %d;", *(call+4) - '0');
|
||||
else if ( strncmp( "reloc", call, 5) == 0 && isdigit( *(call+5)))
|
||||
printf( "cur_pos += %d;", *(call+5) - '0');
|
||||
|
||||
pr_text_with_conversions( call);
|
||||
printf( "fprint( outfile, \";\")");
|
||||
}
|
||||
|
||||
pr_elsif( quest)
|
||||
char *quest;
|
||||
{
|
||||
printf( "fprint( outfile, \"}\else if\");");
|
||||
pr_text_with_conversions( quest+5);
|
||||
printf( "fprint( outfile, \"{\");");
|
||||
}
|
||||
|
||||
pr_if( quest)
|
||||
char *quest;
|
||||
{
|
||||
pr_text_with_conversions( quest);
|
||||
printf( "fprint( outfile, \"{\");");
|
||||
}
|
||||
|
||||
|
||||
pr_text_with_conversions( str)
|
||||
char *str;
|
||||
{
|
||||
char *ptr, *next_conversion(), *pr_conversion();
|
||||
|
||||
while ( ptr = next_conversion( str)) {
|
||||
/* ptr points to '%'-sign */
|
||||
*ptr = '\0';
|
||||
printf( "fprint( outfile, \"%s\");", str);
|
||||
*ptr = '%';
|
||||
str = pr_conversion( ptr);
|
||||
}
|
||||
printf( "fprint( outfile, \"%s\");", str);
|
||||
}
|
||||
|
||||
char *next_conversion( str)
|
||||
char *str;
|
||||
{
|
||||
char *match();
|
||||
|
||||
while ( *str && *str != '%') {
|
||||
switch ( *str++) {
|
||||
case '\'' : str = match( '\'', str) + 1;
|
||||
break;
|
||||
case '"' : str = match( '"', str) + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return( *str == '%' ? str : (char *)0);
|
||||
}
|
||||
|
||||
char *match( c, str)
|
||||
char c, *str;
|
||||
{
|
||||
while ( *str && ( *str != c || *(str-1) == '\\'))
|
||||
str++;
|
||||
return( *str ? str : str-1);
|
||||
}
|
||||
|
||||
char *match_bracket( str)
|
||||
char *str;
|
||||
|
||||
/* find ')', but look at nesting '('-')' pairs, return position of ')'.
|
||||
*/
|
||||
{
|
||||
int depth;
|
||||
char *match();
|
||||
|
||||
depth = 1;
|
||||
while ( *str && depth != 0) {
|
||||
switch ( *str++) {
|
||||
case '\'' : str = match( '\'', str+1) + 1;
|
||||
break;
|
||||
case '"' : str = match( '"', str+1) + 1;
|
||||
break;
|
||||
case '(' : depth++;
|
||||
break;
|
||||
case ')' : depth--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return( str-1);
|
||||
}
|
||||
|
||||
|
||||
char *find( c, str)
|
||||
char c, *str;
|
||||
{
|
||||
while ( *str && *str != c)
|
||||
str++;
|
||||
return( str);
|
||||
}
|
||||
|
||||
char *pr_conversion( str)
|
||||
char *str;
|
||||
|
||||
/* str points to '%'-sign, returns pointer to first character AFTER the
|
||||
* conversion
|
||||
*/
|
||||
{
|
||||
char *start, *ptr, *match_bracket(), *find();
|
||||
|
||||
start = find( '(', str+1);
|
||||
*start++ = '\0';
|
||||
|
||||
ptr = match_bracket( start);
|
||||
*ptr = '\0';
|
||||
|
||||
if ( *(str+1) == '$')
|
||||
printf( "eval( %s);", start);
|
||||
else if ( strncmp( str+1, "dist", 4) == 0)
|
||||
printf( "dist( %s);", start);
|
||||
else
|
||||
printf( "fprint( outfile, \"%%%s\", %s);", str+1, start);
|
||||
|
||||
return( ptr+1);
|
||||
}
|
||||
Reference in New Issue
Block a user