diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2017-01-01 19:31:12 +0100 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2017-01-01 19:31:12 +0100 |
commit | 69fe7b182a1eedfb75c611f7dd35fa60200426f4 (patch) | |
tree | 329a0c6cc9b06c23d8782ece09f0f7dfa9b16b13 /test2 | |
download | compilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.gz compilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.bz2 |
initial checkin
Diffstat (limited to 'test2')
-rw-r--r-- | test2/Makefile | 11 | ||||
-rw-r--r-- | test2/parse.c | 226 |
2 files changed, 237 insertions, 0 deletions
diff --git a/test2/Makefile b/test2/Makefile new file mode 100644 index 0000000..d96ad26 --- /dev/null +++ b/test2/Makefile @@ -0,0 +1,11 @@ +CFLAGS=-std=c99 -Wall -Werror -g + +all: parse + +test: parse + printf "9-5+2" | ./parse + printf "9 - 5 + 2" | ./parse + printf "91 - 35 + 23" | ./parse + +clean: + -rm -f parse diff --git a/test2/parse.c b/test2/parse.c new file mode 100644 index 0000000..6c3aa7a --- /dev/null +++ b/test2/parse.c @@ -0,0 +1,226 @@ +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <stdbool.h> + +/// scanner + +// constants + +enum { + MAX_IDENT_LEN = 10 +}; + +// token types + +typedef enum { + S_undef, + S_token, + S_number, + S_identifier, + S_false, + S_true, + S_eof +} Sym; + +typedef struct { + Sym sym; + union { + char s[MAX_IDENT_LEN]; + int n; + bool b; + }; + int tag; +} Symbol; + +char *symbol_tostr( Symbol s, char *buf, size_t buflen ) +{ + switch( s.sym ) { + case S_undef: + snprintf( buf, buflen, "UNDEF" ); + break; + + case S_token: + if( isprint( s.tag ) ) { + snprintf( buf, buflen, "TOK(%c)", s.tag ); + } else { + snprintf( buf, buflen, "TOK(0x%dx)", s.tag ); + } + break; + + case S_number: + snprintf( buf, buflen, "NUMBER(%d)", s.n ); + break; + + case S_identifier: + snprintf( buf, buflen, "IDENT(%s)", s.s ); + break; + + case S_eof: + snprintf( buf, buflen, "EOF" ); + break; + + default: + snprintf( buf, buflen, "ILLEGAL(%d)", s.sym ); + + } + + return buf; +} + +typedef struct { + int peek; + int row; + int col; + FILE *f; + Symbol s; +} Scanner; + +void scanner_init( Scanner *s, FILE *f ) +{ + s->peek = ' '; + s->row = 1; + s->col = 1; + s->f = f; + s->s.sym = S_undef; +} + +void scanner_skip_whitespace( Scanner *s ) +{ + for( ; ; s->peek = getc( s->f ) ) { + s->col++; + if( s->peek == ' ' || s->peek == '\t' ) { + continue; + } else if( s->peek == '\n' ) { + s->row++; + s->col = 1; + } else if( s->peek == EOF ) { + break; + } else { + break; + } + } +} + +Symbol scanner_get_int( Scanner *s ) +{ + Symbol sym; + + sym.sym = S_number; + sym.n = 0; + + do { + sym.n = sym.n * 10 + ( s->peek - '0' ); + s->peek = getc( s->f ); + } while( isdigit( s->peek ) && ( s->peek != EOF ) ); + + return sym; +} + +Symbol scanner_scan( Scanner *s ) +{ + Symbol sym; + + if( s->peek == EOF ) { + sym.sym = S_eof; + return sym; + } + + scanner_skip_whitespace( s ); + + if( isdigit( s->peek ) ) { + sym = scanner_get_int( s ); + return sym; + } + + sym.sym = S_token; + sym.tag = s->peek; + s->peek = ' '; + + return sym; +} + +/// parser + +typedef struct { + Scanner *s; +} Parser; + +void parser_init( Parser *p, Scanner *s ) +{ + p->s = s; +} + +void parser_error( Parser *p, const char *s, Symbol sym ) +{ + char errbuf[255]; + fprintf( stderr, "\nERR: %s at symbol '%s' at line %d, column %d\n", + s, symbol_tostr( sym, errbuf, 255 ), p->s->row, p->s->col ); + exit( 1 ); +} + +void parser_term( Parser *p ) +{ + Symbol s = scanner_scan( p->s ); + + if( s.sym == S_number ) { + printf( "%d ", s.n ); + } else { + parser_error( p, "expecting number", s ); + } +} + +void parser_rest( Parser *p ) +{ + Symbol s = scanner_scan( p->s ); + + if( s.sym == S_token ) { + switch( s.tag ) { + case '+': + parser_term( p ); + putchar( '+' ); putchar( ' ' ); + parser_rest( p ); + break; + + case '-': + parser_term( p ); + putchar( '-' ); putchar( ' ' ); + parser_rest( p ); + break; + default: + parser_error( p, "expecting operator '+' or '-'", s ); + } + } else if( s.sym == S_eof ) { + return; + } else { + parser_error( p, "expecting an operator '+' or '-'", s ); + } +} + +void parser_expr( Parser *p ) +{ + parser_term( p ); + parser_rest( p ); +} + +void parser_parse( Parser *p ) +{ + parser_expr( p ); +} + +/// main + +int main( void ) +{ + Scanner s; + Parser p; + + scanner_init( &s, stdin ); + parser_init( &p, &s ); + + parser_parse( &p ); + + puts( "" ); + + exit( 0 ); +} |