home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
cs.rhul.ac.uk
/
www.cs.rhul.ac.uk.zip
/
www.cs.rhul.ac.uk
/
pub
/
rdp
/
rdp_cs3460.tar
/
rdp_supp
/
scan.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-07
|
5KB
|
176 lines
/*******************************************************************************
*
* RDP release 1.50 by Adrian Johnstone (A.Johnstone@rhbnc.ac.uk) 20 December 1997
*
* scan.c - support routines for the scanner
*
* This file may be freely distributed. Please mail improvements to the author.
*
*******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "graph.h"
#include "memalloc.h"
#include "symbol.h"
#include "set.h"
#include "textio.h"
#include "scan.h"
void * scan_table = NULL;
int scan_case_insensitive = 0;
int scan_newline_visible = 0;
int scan_show_skips = 0;
int scan_symbol_echo = 0;
char * scan_token_names = NULL;
void scan_init(const int case_insensitive, const int newline_visible, const int show_skips, const int symbol_echo, char * token_names)
{
scan_case_insensitive = case_insensitive;
scan_show_skips = show_skips;
scan_newline_visible = newline_visible;
scan_symbol_echo = symbol_echo;
scan_token_names = token_names;
text_scan_data = mem_malloc(sizeof(scan_data));
scan_table = symbol_new_table("scan table", 101, 31, symbol_compare_string, symbol_hash_string, symbol_print_string);
}
void scan_load_keyword(char * id1, const char * id2, const int token, const int extended)
{
scan_data * d =(scan_data *) symbol_new_symbol(sizeof(scan_data));
d->id = text_insert_string(id1);
if (id2 != NULL) /* If this has a secondary string */
text_insert_string(id2);
d->token = token;
d->extended = extended;
symbol_insert_symbol(scan_table, d);
}
void scan_prune_tree(scan_data * this_node)
{
void * this_edge = graph_get_next_edge(this_node);
/* text_message(TEXT_INFO, "Node: %s\n", this_node->id); */
/* Look at children. If they are NULL, delete them after bringing their children up to this level */
while (this_edge != NULL)
{
void * temp_edge = this_edge;
scan_data * child_node =(scan_data *) graph_get_edge_target(temp_edge);
scan_prune_tree((scan_data *) graph_get_edge_target(this_edge)); /* do lower levels first */
this_edge = graph_get_next_edge(this_edge); /* set up for next edge */
if (* child_node->id == 0) /* Child is epsilon? */
{
void * childs_edge = graph_get_next_edge(child_node);
while (childs_edge != NULL)
{
graph_insert_edge(0, graph_get_edge_target(childs_edge), temp_edge);
childs_edge = graph_get_next_edge(childs_edge);
}
graph_delete_node(child_node);
graph_delete_edge(temp_edge);
}
}
}
static void scan_skip(set_ * stop) /* scan until a token in stop set appears */
{
while (!set_includes_element(stop, SCAN_CAST->token))
scan_(); /* Don't add tokens to tree when skipping! */
if (scan_show_skips)
text_message(TEXT_ERROR_ECHO, "Skipping to...\n");
}
int scan_test(const char * production, const int valid, set_ * stop)
{
if (valid != SCAN_CAST->token)
{
if (stop != NULL)
{
if (production != NULL)
text_message(TEXT_ERROR_ECHO, "In rule \'%s\', scanned ", production);
else
text_message(TEXT_ERROR_ECHO, "Scanned ");
set_print_element(SCAN_CAST->token, scan_token_names);
text_printf(" whilst expecting ");
set_print_element(valid, scan_token_names);
text_printf("\n");
scan_skip(stop);
}
return 0;
}
else
return 1;
}
int scan_test_set(const char * production, set_ * valid, set_ * stop)
{
if (!set_includes_element(valid, SCAN_CAST->token))
{
if (stop != NULL)
{
if (production != NULL)
text_message(TEXT_ERROR_ECHO, "In rule \'%s\', scanned ", production);
else
text_message(TEXT_ERROR_ECHO, "Scanned ");
set_print_element(SCAN_CAST->token, scan_token_names);
text_printf(" whilst expecting %s", set_cardinality(valid)== 1 ? "": "one of ");
set_print_set(valid, scan_token_names, 60);
text_printf("\n");
scan_skip(stop);
}
return 0;
}
else
return 1;
}
void scan_vcg_print_node(const void * node)
{
text_printf("label:\"");
switch (((scan_data *) node)->token)
{
case SCAN_P_IGNORE:
case SCAN_P_ID: text_print_C_string(((scan_data *) node)->id); break;
case SCAN_P_INTEGER:
text_printf("INTEGER: %lu", ((scan_data *) node)->data.i); break;
case SCAN_P_REAL: text_printf("REAL: %lf", ((scan_data *) node)->data.r); break;
case SCAN_P_STRING:
case SCAN_P_STRING_ESC:
case SCAN_P_COMMENT:
case SCAN_P_COMMENT_VISIBLE:
case SCAN_P_COMMENT_NEST:
case SCAN_P_COMMENT_NEST_VISIBLE:
case SCAN_P_COMMENT_LINE:
case SCAN_P_COMMENT_LINE_VISIBLE: text_printf("\\\""); text_print_C_string(((scan_data *) node)->id); text_printf("\\\""); break;
case SCAN_P_EOF: text_printf("EOF"); break;
case SCAN_P_EOLN: text_printf("EOLN"); break;
default: text_printf("\'");
text_print_C_string(((scan_data *) node)->id);
text_printf("\'");
break;
}
text_printf("\" horizontal_order:%lu", graph_get_atom_number(node));
if (((scan_data *) node)->token == SCAN_P_IGNORE) /* make nonterminals round */
text_printf(" shape:ellipse ");
}
/* End of scan.c */