FreeCalypso > hg > ueda-linux
diff ueda/sverp/lexer.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 20 Jul 2015 00:24:37 +0000 |
parents | |
children | 7b4f78fcca08 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ueda/sverp/lexer.c Mon Jul 20 00:24:37 2015 +0000 @@ -0,0 +1,215 @@ +/* + * This module contains the lexer underlying the parser for the minimal + * subset of Verilog we grok; the same lexer will be used to read and parse + * the primitives definition file. + */ + +#include <ctype.h> +#include <stdio.h> +#include "lexer.h" + +char *parser_filename; +FILE *parser_readF; +int parser_lineno; +char parser_read_word[MAXWORD+1]; +int parser_read_number; +int pushback_token; + +void +parse_error(msg) + char *msg; +{ + fprintf(stderr, "%s line %d: %s\n", parser_filename, parser_lineno, + msg); + exit(1); +} + +static +my_getchar() +{ + register int c; + + c = getc(parser_readF); + if (c < 0) + return(c); + if (!isascii(c)) + parse_error("non-ASCII character"); + if (iscntrl(c) && c != '\n' && c != '\t') + parse_error("invalid control character"); + return(c); +} + +static void +handle_trad_comment() +{ + register int c, flag; + + for (flag = 0; ; ) { + c = my_getchar(); + if (c < 0) + parse_error("/* comment ends in EOF"); + if (c == '\n') + parser_lineno++; + if (c == '/' && flag) + return; + flag = (c == '*'); + } +} + +static void +handle_line_comment() +{ + register int c; + + for (;;) { + c = my_getchar(); + if (c < 0) + parse_error("// comment ends in EOF"); + if (c == '\n') { + parser_lineno++; + return; + } + } +} + +static void +handle_comment() +{ + int c; + + c = my_getchar(); + switch (c) { + case '*': + /* traditional C comment style */ + handle_trad_comment(); + return; + case '/': + /* new-fangled double slash comment style */ + handle_line_comment(); + return; + default: + parse_error("character after '/' is not '*' or '/'"); + exit(1); + } +} + +static void +handle_num_token(first_digit) +{ + register int c, n; + + parser_read_number = first_digit - '0'; + for (n = 1; ; n++) { + c = my_getchar(); + if (!isdigit(c)) + break; + parser_read_number *= 10; + parser_read_number += c - '0'; + } + if (c >= 0) { + if (isalpha(c) || c == '_') + parse_error( + "digits followed by letters: neither word nor number"); + ungetc(c, parser_readF); + } + if (n > MAXDIGITS) + parse_error("number is too long (MAXDIGITS exceeded)"); +} + +static void +handle_word_token(first_char) +{ + register int c; + register char *cp; + register int len; + + cp = parser_read_word; + *cp++ = first_char; + for (len = 1; ; ) { + c = my_getchar(); + if (!isalnum(c) && c != '_' && c != '$') + break; + if (len >= MAXWORD) + parse_error("text token is too long"); + *cp++ = c; + len++; + } + *cp = '\0'; + if (c < 0) + return; + ungetc(c, parser_readF); +} + +static void +handle_qstr() +{ + register int c; + register char *cp; + register int len; + + cp = parser_read_word; + for (len = 0; ; ) { + c = my_getchar(); + if (c == EOF || c == '\n') +unterm: parse_error("unterminated quoted string"); + if (c == '"') + break; + if (c == '\\') { + c = my_getchar(); + if (c == EOF || c == '\n') + goto unterm; + } + if (len >= MAXWORD) + parse_error("quoted string is too long"); + *cp++ = c; + len++; + } + *cp = '\0'; +} + +get_token() +{ + register int c; + + if (c = pushback_token) { + pushback_token = 0; + return(c); + } +loop: c = my_getchar(); + switch (c) { + case EOF: + return(0); + case ' ': + case '\t': + goto loop; + case '\n': + parser_lineno++; + goto loop; + case '/': + handle_comment(); + goto loop; + case '(': + case ')': + case ',': + case '.': + case ':': + case ';': + case '[': + case ']': + return(c); + case '"': + handle_qstr(); + return(QSTRING); + } + if (isdigit(c)) { + handle_num_token(c); + return(NUMBER); + } + if (isalpha(c) || c == '_') { + handle_word_token(c); + return(WORD); + } + fprintf(stderr, "%s line %d: bad character \'%c\'\n", parser_filename, + parser_lineno, c); + exit(1); +}