summaryrefslogtreecommitdiff
path: root/test2
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-01-01 19:31:12 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2017-01-01 19:31:12 +0100
commit69fe7b182a1eedfb75c611f7dd35fa60200426f4 (patch)
tree329a0c6cc9b06c23d8782ece09f0f7dfa9b16b13 /test2
downloadcompilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.gz
compilertests-69fe7b182a1eedfb75c611f7dd35fa60200426f4.tar.bz2
initial checkin
Diffstat (limited to 'test2')
-rw-r--r--test2/Makefile11
-rw-r--r--test2/parse.c226
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 );
+}