FreeCalypso > hg > ueda-linux
view ueda/sverp/lexer.c @ 139:bf188727e606
donl-rename-parts reader: no tEDAx-style escapes
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 07 Sep 2020 04:25:11 +0000 |
parents | 7b4f78fcca08 |
children |
line wrap: on
line source
/* * 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 <stdlib.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); }