| @@ -0,0 +1,5 @@ | |||||
| *.o | |||||
| y.tab.h | |||||
| parser.c | |||||
| scanner.c | |||||
| vslc | |||||
| @@ -0,0 +1,13 @@ | |||||
| LEX=flex | |||||
| YACC=bison | |||||
| YFLAGS+=--defines=src/y.tab.h -o y.tab.c | |||||
| CFLAGS+=-std=c99 -g -Isrc -Iinclude -D_POSIX_C_SOURCE=200809L -DYYSTYPE="node_t *" | |||||
| LDLIBS+=-lc | |||||
| src/vslc: src/vslc.c src/parser.o src/scanner.o src/nodetypes.o src/tree.o src/ir.o src/tlhash.c | |||||
| src/y.tab.h: src/parser.c | |||||
| src/scanner.c: src/y.tab.h src/scanner.l | |||||
| clean: | |||||
| -rm -f src/parser.c src/scanner.c src/*.tab.* src/*.o | |||||
| purge: clean | |||||
| -rm -f src/vslc | |||||
| @@ -0,0 +1,30 @@ | |||||
| #ifndef IR_H | |||||
| #define IR_H | |||||
| /* This is the tree node structure */ | |||||
| typedef struct n { | |||||
| node_index_t type; | |||||
| void *data; | |||||
| struct s *entry; | |||||
| uint64_t n_children; | |||||
| struct n **children; | |||||
| } node_t; | |||||
| // Export the initializer function, it is needed by the parser | |||||
| void node_init ( | |||||
| node_t *nd, node_index_t type, void *data, uint64_t n_children, ... | |||||
| ); | |||||
| typedef enum { | |||||
| SYM_GLOBAL_VAR, SYM_FUNCTION, SYM_PARAMETER, SYM_LOCAL_VAR | |||||
| } symtype_t; | |||||
| typedef struct s { | |||||
| char *name; | |||||
| symtype_t type; | |||||
| node_t *node; | |||||
| size_t seq; | |||||
| size_t nparms; | |||||
| tlhash_t *locals; | |||||
| } symbol_t; | |||||
| #endif | |||||
| @@ -0,0 +1,33 @@ | |||||
| #ifndef NODETYPES_H | |||||
| #define NODETYPES_H | |||||
| typedef enum { | |||||
| PROGRAM, | |||||
| GLOBAL_LIST, | |||||
| GLOBAL, | |||||
| STATEMENT_LIST, | |||||
| PRINT_LIST, | |||||
| EXPRESSION_LIST, | |||||
| VARIABLE_LIST, | |||||
| ARGUMENT_LIST, | |||||
| PARAMETER_LIST, | |||||
| DECLARATION_LIST, | |||||
| FUNCTION, | |||||
| STATEMENT, | |||||
| BLOCK, | |||||
| ASSIGNMENT_STATEMENT, | |||||
| RETURN_STATEMENT, | |||||
| PRINT_STATEMENT, | |||||
| NULL_STATEMENT, | |||||
| IF_STATEMENT, | |||||
| WHILE_STATEMENT, | |||||
| EXPRESSION, | |||||
| RELATION, | |||||
| DECLARATION, | |||||
| PRINT_ITEM, | |||||
| IDENTIFIER_DATA, | |||||
| NUMBER_DATA, | |||||
| STRING_DATA | |||||
| } node_index_t; | |||||
| extern char *node_string[25]; | |||||
| #endif | |||||
| @@ -0,0 +1,28 @@ | |||||
| #ifndef TLHASH_H | |||||
| #define TLHASH_H | |||||
| #include <stddef.h> | |||||
| typedef struct el { | |||||
| void *key, *value; | |||||
| size_t key_length; | |||||
| struct el *next; | |||||
| } tlhash_element_t; | |||||
| typedef struct { | |||||
| size_t n_buckets, size; | |||||
| tlhash_element_t **buckets; | |||||
| } tlhash_t; | |||||
| int tlhash_init ( tlhash_t *tab, size_t n_buckets ); | |||||
| int tlhash_finalize ( tlhash_t *tab ); | |||||
| int tlhash_insert ( tlhash_t *tab, void *key, size_t keylen, void *val ); | |||||
| int tlhash_lookup ( tlhash_t *tab, void *key, size_t keylen, void **val ); | |||||
| int tlhash_remove ( tlhash_t *tab, void *key, size_t key_length ); | |||||
| size_t tlhash_size ( tlhash_t *tab ); | |||||
| void tlhash_keys ( tlhash_t *tab, void **keys ); | |||||
| void tlhash_values ( tlhash_t *tab, void **values ); | |||||
| #define TLHASH_SUCCESS 0 /* Success */ | |||||
| #define TLHASH_ENOMEM 1 /* No memory available */ | |||||
| #define TLHASH_ENOENT 2 /* No such table entry */ | |||||
| #define TLHASH_EEXIST 3 /* Table entry already exists */ | |||||
| #endif | |||||
| @@ -0,0 +1,22 @@ | |||||
| #ifndef VSLC_H | |||||
| #define VSLC_H | |||||
| #include <stdio.h> | |||||
| #include <stdlib.h> | |||||
| #include <string.h> | |||||
| #include <stdint.h> | |||||
| #include <stdbool.h> | |||||
| #include <stdarg.h> | |||||
| #include "tlhash.h" | |||||
| #include "nodetypes.h" | |||||
| #include "ir.h" | |||||
| #include "y.tab.h" | |||||
| int yyerror ( const char *error ); | |||||
| extern int yylineno; | |||||
| extern int yylex ( void ); | |||||
| extern char yytext[]; | |||||
| extern node_t *root; | |||||
| #endif | |||||
| @@ -0,0 +1,155 @@ | |||||
| #include <vslc.h> | |||||
| // Externally visible, for the generator | |||||
| extern tlhash_t *global_names; | |||||
| extern char **string_list; | |||||
| extern size_t n_string_list,stringc; | |||||
| /* External interface */ | |||||
| void create_symbol_table(void); | |||||
| void print_symbol_table(void); | |||||
| void print_symbols(void); | |||||
| void print_bindings(node_t *root); | |||||
| void destroy_symbol_table(void); | |||||
| void find_globals(void); | |||||
| void bind_names(symbol_t *function, node_t *root); | |||||
| void destroy_symtab(void); | |||||
| void | |||||
| create_symbol_table ( void ) | |||||
| { | |||||
| find_globals(); | |||||
| size_t n_globals = tlhash_size ( global_names ); | |||||
| symbol_t *global_list[n_globals]; | |||||
| tlhash_values ( global_names, (void **)&global_list ); | |||||
| for ( size_t i=0; i<n_globals; i++ ) | |||||
| if ( global_list[i]->type == SYM_FUNCTION ) | |||||
| bind_names ( global_list[i], global_list[i]->node ); | |||||
| } | |||||
| void | |||||
| print_symbol_table ( void ) | |||||
| { | |||||
| print_symbols(); | |||||
| print_bindings(root); | |||||
| } | |||||
| void | |||||
| print_symbols ( void ) | |||||
| { | |||||
| printf ( "String table:\n" ); | |||||
| for ( size_t s=0; s<stringc; s++ ) | |||||
| printf ( "%zu: %s\n", s, string_list[s] ); | |||||
| printf ( "-- \n" ); | |||||
| printf ( "Globals:\n" ); | |||||
| size_t n_globals = tlhash_size(global_names); | |||||
| symbol_t *global_list[n_globals]; | |||||
| tlhash_values ( global_names, (void **)&global_list ); | |||||
| for ( size_t g=0; g<n_globals; g++ ) | |||||
| { | |||||
| switch ( global_list[g]->type ) | |||||
| { | |||||
| case SYM_FUNCTION: | |||||
| printf ( | |||||
| "%s: function %zu:\n", | |||||
| global_list[g]->name, global_list[g]->seq | |||||
| ); | |||||
| if ( global_list[g]->locals != NULL ) | |||||
| { | |||||
| size_t localsize = tlhash_size( global_list[g]->locals ); | |||||
| printf ( | |||||
| "\t%zu local variables, %zu are parameters:\n", | |||||
| localsize, global_list[g]->nparms | |||||
| ); | |||||
| symbol_t *locals[localsize]; | |||||
| tlhash_values(global_list[g]->locals, (void **)locals ); | |||||
| for ( size_t i=0; i<localsize; i++ ) | |||||
| { | |||||
| printf ( "\t%s: ", locals[i]->name ); | |||||
| switch ( locals[i]->type ) | |||||
| { | |||||
| case SYM_PARAMETER: | |||||
| printf ( "parameter %zu\n", locals[i]->seq ); | |||||
| break; | |||||
| case SYM_LOCAL_VAR: | |||||
| printf ( "local var %zu\n", locals[i]->seq ); | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| break; | |||||
| case SYM_GLOBAL_VAR: | |||||
| printf ( "%s: global variable\n", global_list[g]->name ); | |||||
| break; | |||||
| } | |||||
| } | |||||
| printf ( "-- \n" ); | |||||
| } | |||||
| void | |||||
| print_bindings ( node_t *root ) | |||||
| { | |||||
| if ( root == NULL ) | |||||
| return; | |||||
| else if ( root->entry != NULL ) | |||||
| { | |||||
| switch ( root->entry->type ) | |||||
| { | |||||
| case SYM_GLOBAL_VAR: | |||||
| printf ( "Linked global var '%s'\n", root->entry->name ); | |||||
| break; | |||||
| case SYM_FUNCTION: | |||||
| printf ( "Linked function %zu ('%s')\n", | |||||
| root->entry->seq, root->entry->name | |||||
| ); | |||||
| break; | |||||
| case SYM_PARAMETER: | |||||
| printf ( "Linked parameter %zu ('%s')\n", | |||||
| root->entry->seq, root->entry->name | |||||
| ); | |||||
| break; | |||||
| case SYM_LOCAL_VAR: | |||||
| printf ( "Linked local var %zu ('%s')\n", | |||||
| root->entry->seq, root->entry->name | |||||
| ); | |||||
| break; | |||||
| } | |||||
| } else if ( root->type == STRING_DATA ) { | |||||
| size_t string_index = *((size_t *)root->data); | |||||
| if ( string_index < stringc ) | |||||
| printf ( "Linked string %zu\n", *((size_t *)root->data) ); | |||||
| else | |||||
| printf ( "(Not an indexed string)\n" ); | |||||
| } | |||||
| for ( size_t c=0; c<root->n_children; c++ ) | |||||
| print_bindings ( root->children[c] ); | |||||
| } | |||||
| void | |||||
| destroy_symbol_table ( void ) | |||||
| { | |||||
| destroy_symtab(); | |||||
| } | |||||
| void | |||||
| find_globals ( void ) | |||||
| { | |||||
| } | |||||
| void | |||||
| bind_names ( symbol_t *function, node_t *root ) | |||||
| { | |||||
| } | |||||
| void | |||||
| destroy_symtab ( void ) | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,31 @@ | |||||
| //#include "nodetypes.h" | |||||
| #define STRING(x) #x | |||||
| char *node_string[26] = { | |||||
| STRING(PROGRAM), | |||||
| STRING(GLOBAL_LIST), | |||||
| STRING(GLOBAL), | |||||
| STRING(STATEMENT_LIST), | |||||
| STRING(PRINT_LIST), | |||||
| STRING(EXPRESSION_LIST), | |||||
| STRING(VARIABLE_LIST), | |||||
| STRING(ARGUMENT_LIST), | |||||
| STRING(PARAMETER_LIST), | |||||
| STRING(DECLARATION_LIST), | |||||
| STRING(FUNCTION), | |||||
| STRING(STATEMENT), | |||||
| STRING(BLOCK), | |||||
| STRING(ASSIGNMENT_STATEMENT), | |||||
| STRING(RETURN_STATEMENT), | |||||
| STRING(PRINT_STATEMENT), | |||||
| STRING(NULL_STATEMENT), | |||||
| STRING(IF_STATEMENT), | |||||
| STRING(WHILE_STATEMENT), | |||||
| STRING(EXPRESSION), | |||||
| STRING(RELATION), | |||||
| STRING(DECLARATION), | |||||
| STRING(PRINT_ITEM), | |||||
| STRING(IDENTIFIER_DATA), | |||||
| STRING(NUMBER_DATA), | |||||
| STRING(STRING_DATA) | |||||
| }; | |||||
| #undef STRING | |||||
| @@ -0,0 +1,160 @@ | |||||
| %{ | |||||
| #include <vslc.h> | |||||
| #define N0C(n,t,d) do { \ | |||||
| node_init ( n = malloc(sizeof(node_t)), t, d, 0 ); \ | |||||
| } while ( false ) | |||||
| #define N1C(n,t,d,a) do { \ | |||||
| node_init ( n = malloc(sizeof(node_t)), t, d, 1, a ); \ | |||||
| } while ( false ) | |||||
| #define N2C(n,t,d,a,b) do { \ | |||||
| node_init ( n = malloc(sizeof(node_t)), t, d, 2, a, b ); \ | |||||
| } while ( false ) | |||||
| #define N3C(n,t,d,a,b,c) do { \ | |||||
| node_init ( n = malloc(sizeof(node_t)), t, d, 3, a, b, c ); \ | |||||
| } while ( false ) | |||||
| %} | |||||
| %left '+' '-' | |||||
| %left '*' '/' | |||||
| %nonassoc UMINUS | |||||
| %expect 1 | |||||
| %token FUNC PRINT RETURN CONTINUE IF THEN ELSE WHILE DO OPENBLOCK CLOSEBLOCK | |||||
| %token VAR NUMBER IDENTIFIER STRING | |||||
| %% | |||||
| program : | |||||
| global_list { N1C ( root, PROGRAM, NULL, $1 );} | |||||
| ; | |||||
| global_list : | |||||
| global { N1C ( $$, GLOBAL_LIST, NULL, $1 ); } | |||||
| | global_list global { N2C ( $$, GLOBAL_LIST, NULL, $1, $2 ); } | |||||
| ; | |||||
| global: | |||||
| function { N1C ( $$, GLOBAL, NULL, $1 ); } | |||||
| | declaration { N1C ( $$, GLOBAL, NULL, $1 ); } | |||||
| ; | |||||
| statement_list : | |||||
| statement { N1C ( $$, STATEMENT_LIST, NULL, $1 ); } | |||||
| | statement_list statement { N2C ( $$, STATEMENT_LIST, NULL, $1, $2 ); } | |||||
| ; | |||||
| print_list : | |||||
| print_item { N1C ( $$, PRINT_LIST, NULL, $1 ); } | |||||
| | print_list ',' print_item { N2C ( $$, PRINT_LIST, NULL, $1, $3 ); } | |||||
| ; | |||||
| expression_list : | |||||
| expression { N1C ( $$, EXPRESSION_LIST, NULL, $1 ); } | |||||
| | expression_list ',' expression { N2C($$, EXPRESSION_LIST, NULL, $1, $3); } | |||||
| ; | |||||
| variable_list : | |||||
| identifier { N1C ( $$, VARIABLE_LIST, NULL, $1 ); } | |||||
| | variable_list ',' identifier { N2C ( $$, VARIABLE_LIST, NULL, $1, $3 ); } | |||||
| ; | |||||
| argument_list : | |||||
| expression_list { N1C ( $$, ARGUMENT_LIST, NULL, $1 ); } | |||||
| | /* epsilon */ { $$ = NULL; } | |||||
| ; | |||||
| parameter_list : | |||||
| variable_list { N1C ( $$, PARAMETER_LIST, NULL, $1 ); } | |||||
| | /* epsilon */ { $$ = NULL; } | |||||
| ; | |||||
| declaration_list : | |||||
| declaration { N1C ( $$, DECLARATION_LIST, NULL, $1 ); } | |||||
| | declaration_list declaration { N2C ($$, DECLARATION_LIST, NULL, $1, $2); } | |||||
| ; | |||||
| function : | |||||
| FUNC identifier '(' parameter_list ')' statement | |||||
| { N3C ( $$, FUNCTION, NULL, $2, $4, $6 ); } | |||||
| ; | |||||
| statement : | |||||
| assignment_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | return_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | print_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | if_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | while_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | null_statement { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| | block { N1C ( $$, STATEMENT, NULL, $1 ); } | |||||
| ; | |||||
| block : | |||||
| OPENBLOCK declaration_list statement_list CLOSEBLOCK | |||||
| { N2C ($$, BLOCK, NULL, $2, $3); } | |||||
| | OPENBLOCK statement_list CLOSEBLOCK { N1C ($$, BLOCK, NULL, $2 ); } | |||||
| ; | |||||
| assignment_statement : | |||||
| identifier ':' '=' expression | |||||
| { N2C ( $$, ASSIGNMENT_STATEMENT, NULL, $1, $4 ); } | |||||
| ; | |||||
| return_statement : | |||||
| RETURN expression | |||||
| { N1C ( $$, RETURN_STATEMENT, NULL, $2 ); } | |||||
| ; | |||||
| print_statement : | |||||
| PRINT print_list | |||||
| { N1C ( $$, PRINT_STATEMENT, NULL, $2 ); } | |||||
| ; | |||||
| null_statement : | |||||
| CONTINUE | |||||
| { N0C ( $$, NULL_STATEMENT, NULL ); } | |||||
| ; | |||||
| if_statement : | |||||
| IF relation THEN statement | |||||
| { N2C ( $$, IF_STATEMENT, NULL, $2, $4 ); } | |||||
| | IF relation THEN statement ELSE statement | |||||
| { N3C ( $$, IF_STATEMENT, NULL, $2, $4, $6 ); } | |||||
| ; | |||||
| while_statement : | |||||
| WHILE relation DO statement | |||||
| { N2C ( $$, WHILE_STATEMENT, NULL, $2, $4 ); } | |||||
| ; | |||||
| relation: | |||||
| expression '=' expression | |||||
| { N2C ( $$, RELATION, strdup("="), $1, $3 ); } | |||||
| | expression '<' expression | |||||
| { N2C ( $$, RELATION, strdup("<"), $1, $3 ); } | |||||
| | expression '>' expression | |||||
| { N2C ( $$, RELATION, strdup(">"), $1, $3 ); } | |||||
| ; | |||||
| expression : expression '+' expression | |||||
| { N2C ( $$, EXPRESSION, strdup("+"), $1, $3 ); } | |||||
| | expression '-' expression | |||||
| { N2C ( $$, EXPRESSION, strdup("-"), $1, $3 ); } | |||||
| | expression '*' expression | |||||
| { N2C ( $$, EXPRESSION, strdup("*"), $1, $3 ); } | |||||
| | expression '/' expression | |||||
| { N2C ( $$, EXPRESSION, strdup("/"), $1, $3 ); } | |||||
| | '-' expression %prec UMINUS | |||||
| { N1C ( $$, EXPRESSION, strdup("-"), $2 ); } | |||||
| | '(' expression ')' { $$ = $2; } | |||||
| | number { N1C ( $$, EXPRESSION, NULL, $1 ); } | |||||
| | identifier | |||||
| { N1C ( $$, EXPRESSION, NULL, $1 ); } | |||||
| | identifier '(' argument_list ')' | |||||
| { N2C ( $$, EXPRESSION, NULL, $1, $3 ); } | |||||
| ; | |||||
| declaration : | |||||
| VAR variable_list { N1C ( $$, DECLARATION, NULL, $2 ); } | |||||
| ; | |||||
| print_item : | |||||
| expression | |||||
| { N1C ( $$, PRINT_ITEM, NULL, $1 ); } | |||||
| | string | |||||
| { N1C ( $$, PRINT_ITEM, NULL, $1 ); } | |||||
| ; | |||||
| identifier: IDENTIFIER { N0C($$, IDENTIFIER_DATA, strdup(yytext) ); } | |||||
| number: NUMBER | |||||
| { | |||||
| int64_t *value = malloc ( sizeof(int64_t) ); | |||||
| *value = strtol ( yytext, NULL, 10 ); | |||||
| N0C($$, NUMBER_DATA, value ); | |||||
| } | |||||
| string: STRING { N0C($$, STRING_DATA, strdup(yytext) ); } | |||||
| %% | |||||
| int | |||||
| yyerror ( const char *error ) | |||||
| { | |||||
| fprintf ( stderr, "%s on line %d\n", error, yylineno ); | |||||
| exit ( EXIT_FAILURE ); | |||||
| } | |||||
| @@ -0,0 +1,30 @@ | |||||
| %{ | |||||
| #include <vslc.h> | |||||
| %} | |||||
| %option noyywrap | |||||
| %option array | |||||
| %option yylineno | |||||
| WHITESPACE [\ \t\v\r\n] | |||||
| COMMENT \/\/[^\n]+ | |||||
| QUOTED \"([^\"\n]|\\\")*\" | |||||
| %% | |||||
| {WHITESPACE}+ { /* Eliminate whitespace */ } | |||||
| {COMMENT} { /* Eliminate comments */ } | |||||
| def { return FUNC; } | |||||
| print { return PRINT; } | |||||
| return { return RETURN; } | |||||
| continue { return CONTINUE; } | |||||
| if { return IF; } | |||||
| then { return THEN; } | |||||
| else { return ELSE; } | |||||
| while { return WHILE; } | |||||
| do { return DO; } | |||||
| begin { return OPENBLOCK; } | |||||
| end { return CLOSEBLOCK; } | |||||
| var { return VAR; } | |||||
| [0-9]+ { return NUMBER; } | |||||
| [A-Za-z_][0-9A-Za-z_]* { return IDENTIFIER; } | |||||
| {QUOTED} { return STRING; } | |||||
| . { return yytext[0]; } | |||||
| %% | |||||
| @@ -0,0 +1,281 @@ | |||||
| #include <string.h> | |||||
| #include <stdlib.h> | |||||
| #include <stdint.h> | |||||
| #include <tlhash.h> | |||||
| /********************************************************************* | |||||
| * Declarations of the utility functions for obtaining hashes, found * | |||||
| * at the bottom of this file. * | |||||
| *********************************************************************/ | |||||
| /* Little-endian, for x86-s */ | |||||
| #define CRC32_IEEE802_3 (0xedb88320) | |||||
| static const uint32_t crc32_ieee802_3[256]; | |||||
| static const uint32_t *crc_table = (uint32_t *)crc32_ieee802_3; | |||||
| static uint32_t crc32 ( void *input, size_t length ); | |||||
| /******************************** | |||||
| * External interface functions * | |||||
| ********************************/ | |||||
| /* Initializer | |||||
| * Returns | |||||
| * ENOMEM - if allocation of table entries fails. | |||||
| */ | |||||
| int | |||||
| tlhash_init ( tlhash_t *tab, size_t n_buckets ) | |||||
| { | |||||
| size_t i; | |||||
| tab->n_buckets = n_buckets; | |||||
| tab->size = 0; | |||||
| tab->buckets = (tlhash_element_t **) calloc ( | |||||
| n_buckets, sizeof(tlhash_element_t *) | |||||
| ); | |||||
| if ( tab->buckets == NULL ) | |||||
| return TLHASH_ENOMEM; | |||||
| for ( i=0; i<n_buckets; i++ ) | |||||
| tab->buckets[i] = NULL; | |||||
| return TLHASH_SUCCESS; | |||||
| } | |||||
| /* Finalizer | |||||
| * Returns | |||||
| * ENOENT - if there is no table to free. | |||||
| */ | |||||
| int | |||||
| tlhash_finalize ( tlhash_t *tab ) | |||||
| { | |||||
| size_t i; | |||||
| if ( tab == NULL ) | |||||
| return TLHASH_ENOENT; | |||||
| for ( i=0; i<tab->n_buckets; i++ ) | |||||
| { | |||||
| tlhash_element_t *element = tab->buckets[i], *next; | |||||
| while ( element != NULL ) | |||||
| { | |||||
| next = element->next; | |||||
| free ( element->key ); | |||||
| free ( element ); | |||||
| tab->size -= 1; | |||||
| element = next; | |||||
| } | |||||
| } | |||||
| free ( tab->buckets ); | |||||
| return TLHASH_SUCCESS; | |||||
| } | |||||
| /* Insert - find hash value, modulate over buckets, append to linked list | |||||
| * Returns | |||||
| * EEXIST - if an element is already indexed by this key | |||||
| * ENOMEM - if allocation of element or key copy fails | |||||
| */ | |||||
| int | |||||
| tlhash_insert ( | |||||
| tlhash_t *tab, void *key, size_t key_length, void *value | |||||
| ) | |||||
| { | |||||
| void *test_entry; | |||||
| int test = tlhash_lookup ( tab, key, key_length, &test_entry ); | |||||
| if ( test != TLHASH_ENOENT ) | |||||
| return TLHASH_EEXIST; | |||||
| uint32_t hash = crc32 ( key, key_length ); | |||||
| size_t bucket = hash % tab->n_buckets; | |||||
| tlhash_element_t *element = malloc ( sizeof(tlhash_element_t) ); | |||||
| if ( element == NULL ) | |||||
| return TLHASH_ENOMEM; | |||||
| void *key_copy = malloc ( key_length ); | |||||
| if ( key_copy == NULL ) | |||||
| { | |||||
| free ( element ); | |||||
| return TLHASH_ENOMEM; | |||||
| } | |||||
| memcpy ( key_copy, key, key_length ); | |||||
| element->key = key_copy; | |||||
| element->key_length = key_length; | |||||
| element->value = value; | |||||
| element->next = tab->buckets[bucket]; | |||||
| tab->buckets[bucket] = element; | |||||
| tab->size += 1; | |||||
| return TLHASH_SUCCESS; | |||||
| } | |||||
| /* Lookup - find hash value, modulate over buckets, search linked list | |||||
| * Returns | |||||
| * ENOENT - if no element is indexed by this key | |||||
| */ | |||||
| int | |||||
| tlhash_lookup ( | |||||
| tlhash_t *tab, void *key, size_t key_length, void **value | |||||
| ) | |||||
| { | |||||
| uint32_t hash = crc32 ( key, key_length ); | |||||
| size_t bucket = hash % tab->n_buckets; | |||||
| tlhash_element_t *el = tab->buckets[bucket]; | |||||
| *value = NULL; | |||||
| while ( el != NULL ) | |||||
| { | |||||
| if ( el->key_length == key_length && ! memcmp(el->key,key,key_length) ) | |||||
| { | |||||
| *value = el->value; | |||||
| break; | |||||
| } | |||||
| el = el->next; | |||||
| } | |||||
| if ( el != NULL ) | |||||
| return TLHASH_SUCCESS; | |||||
| else | |||||
| return TLHASH_ENOENT; | |||||
| } | |||||
| /* Removal - find hash value, modulate over buckets, delete entry | |||||
| * Returns | |||||
| * ENOENT - no such element to remove was found. | |||||
| */ | |||||
| int | |||||
| tlhash_remove ( tlhash_t *tab, void *key, size_t key_length ) | |||||
| { | |||||
| uint32_t hash = crc32 ( key, key_length ); | |||||
| size_t bucket = hash % tab->n_buckets; | |||||
| tlhash_element_t *el = tab->buckets[bucket], *prev = NULL; | |||||
| while ( el != NULL ) | |||||
| { | |||||
| if ( el->key_length == key_length && ! memcmp(el->key,key,key_length) ) | |||||
| { | |||||
| /* We have a match. */ | |||||
| if ( prev != NULL ) /* Remove from list if it's not the head */ | |||||
| prev->next = (void *)el->next; | |||||
| else /* Substitute it if it IS the head */ | |||||
| tab->buckets[bucket] = el->next; | |||||
| /* Free the container and key copy allocated by this lib */ | |||||
| free ( el->key ); | |||||
| free ( el ); | |||||
| break; | |||||
| } | |||||
| prev = el; | |||||
| el = el->next; | |||||
| } | |||||
| if ( el == NULL ) | |||||
| return TLHASH_ENOENT; | |||||
| else | |||||
| { | |||||
| tab->size -= 1; | |||||
| return TLHASH_SUCCESS; | |||||
| } | |||||
| } | |||||
| size_t | |||||
| tlhash_size ( tlhash_t *tab ) | |||||
| { | |||||
| return tab->size; | |||||
| } | |||||
| void | |||||
| tlhash_keys ( tlhash_t *tab, void **keys ) | |||||
| { | |||||
| size_t b, i = 0; | |||||
| for ( b=0; b<tab->n_buckets; b++ ) | |||||
| { | |||||
| tlhash_element_t *el = tab->buckets[b]; | |||||
| while ( el != NULL ) | |||||
| { | |||||
| keys[i] = el->key; | |||||
| i += 1; | |||||
| el = el->next; | |||||
| } | |||||
| } | |||||
| } | |||||
| void | |||||
| tlhash_values ( tlhash_t *tab, void **values ) | |||||
| { | |||||
| size_t b, i = 0; | |||||
| for ( b=0; b<tab->n_buckets; b++ ) | |||||
| { | |||||
| tlhash_element_t *el = tab->buckets[b]; | |||||
| while ( el != NULL ) | |||||
| { | |||||
| values[i] = el->value; | |||||
| i += 1; | |||||
| el = el->next; | |||||
| } | |||||
| } | |||||
| } | |||||
| /*************************************** | |||||
| * Hashing function and IEEE data blob * | |||||
| ***************************************/ | |||||
| static uint32_t | |||||
| crc32 ( void *input, size_t length ) | |||||
| { | |||||
| const uint8_t *data = (uint8_t *)input; | |||||
| size_t i = 0; | |||||
| uint32_t hash = 0xFFFFFFFF; | |||||
| for ( i = 0; i<length; i++ ) | |||||
| hash = (hash>>8) ^ crc_table [ data[i] ^ (uint8_t)hash ]; | |||||
| return (hash^0xFFFFFFFF); | |||||
| } | |||||
| static const uint32_t | |||||
| crc32_ieee802_3[256] = { | |||||
| 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, | |||||
| 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | |||||
| 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, | |||||
| 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | |||||
| 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, | |||||
| 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | |||||
| 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, | |||||
| 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | |||||
| 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, | |||||
| 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | |||||
| 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, | |||||
| 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | |||||
| 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, | |||||
| 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | |||||
| 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, | |||||
| 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | |||||
| 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, | |||||
| 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | |||||
| 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, | |||||
| 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | |||||
| 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, | |||||
| 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | |||||
| 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, | |||||
| 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | |||||
| 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, | |||||
| 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | |||||
| 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, | |||||
| 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | |||||
| 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, | |||||
| 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | |||||
| 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, | |||||
| 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | |||||
| 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, | |||||
| 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | |||||
| 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, | |||||
| 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | |||||
| 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, | |||||
| 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | |||||
| 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, | |||||
| 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | |||||
| 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, | |||||
| 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | |||||
| 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d | |||||
| }; | |||||
| @@ -0,0 +1,141 @@ | |||||
| #include <vslc.h> | |||||
| void | |||||
| node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) | |||||
| { | |||||
| va_list child_list; | |||||
| *nd = (node_t) { | |||||
| .type = type, | |||||
| .data = data, | |||||
| .entry = NULL, | |||||
| .n_children = n_children, | |||||
| .children = (node_t **) malloc ( n_children * sizeof(node_t *) ) | |||||
| }; | |||||
| va_start ( child_list, n_children ); | |||||
| for ( uint64_t i=0; i<n_children; i++ ) | |||||
| nd->children[i] = va_arg ( child_list, node_t * ); | |||||
| va_end ( child_list ); | |||||
| } | |||||
| /* Internal choices */ | |||||
| void node_print ( node_t *root, int nesting ) | |||||
| { | |||||
| if ( root != NULL ) | |||||
| { | |||||
| printf ( "%*c%s", nesting, ' ', node_string[root->type] ); | |||||
| if ( root->type == IDENTIFIER_DATA || | |||||
| root->type == STRING_DATA || | |||||
| root->type == EXPRESSION ) | |||||
| printf ( "(%s)", (char *) root->data ); | |||||
| else if ( root->type == NUMBER_DATA ) | |||||
| printf ( "(%ld)", *((int64_t *)root->data) ); | |||||
| putchar ( '\n' ); | |||||
| for ( int64_t i=0; i<root->n_children; i++ ) | |||||
| node_print ( root->children[i], nesting+1 ); | |||||
| } | |||||
| else | |||||
| printf ( "%*c%p\n", nesting, ' ', root ); | |||||
| } | |||||
| void node_finalize ( node_t *discard ) | |||||
| { | |||||
| if ( discard != NULL ) | |||||
| { | |||||
| free ( discard->data ); | |||||
| free ( discard->children ); | |||||
| free ( discard ); | |||||
| } | |||||
| } | |||||
| void destroy_subtree ( node_t *discard ) | |||||
| { | |||||
| if ( discard != NULL ) | |||||
| { | |||||
| for ( uint64_t i=0; i<discard->n_children; i++ ) | |||||
| destroy_subtree ( discard->children[i] ); | |||||
| node_finalize ( discard ); | |||||
| } | |||||
| } | |||||
| void simplify_tree ( node_t **simplified, node_t *root ) | |||||
| { | |||||
| if ( root == NULL ) | |||||
| return; | |||||
| /* Simplify subtrees before examining this node */ | |||||
| for ( uint64_t i=0; i<root->n_children; i++ ) | |||||
| simplify_tree ( &root->children[i], root->children[i] ); | |||||
| node_t *discard, *result = root; | |||||
| switch ( root->type ) | |||||
| { | |||||
| /* Structures of purely syntactic function */ | |||||
| case PARAMETER_LIST: case ARGUMENT_LIST: | |||||
| case STATEMENT: case PRINT_ITEM: case GLOBAL: | |||||
| result = root->children[0]; | |||||
| node_finalize ( root ); | |||||
| break; | |||||
| case PRINT_STATEMENT: | |||||
| result = root->children[0]; | |||||
| result->type = PRINT_STATEMENT; | |||||
| node_finalize(root); | |||||
| /* Flatten lists: | |||||
| * Take left child, append right child, substitute left for root. | |||||
| */ | |||||
| case STATEMENT_LIST: case DECLARATION_LIST: case GLOBAL_LIST: | |||||
| case PRINT_LIST: case EXPRESSION_LIST: case VARIABLE_LIST: | |||||
| if ( root->n_children >= 2 ) | |||||
| { | |||||
| result = root->children[0]; | |||||
| result->n_children += 1; | |||||
| result->children = realloc ( | |||||
| result->children, result->n_children * sizeof(node_t *) | |||||
| ); | |||||
| result->children[result->n_children-1] = root->children[1]; | |||||
| node_finalize ( root ); | |||||
| } | |||||
| break; | |||||
| case EXPRESSION: | |||||
| switch ( root->n_children ) | |||||
| { | |||||
| case 1: | |||||
| if ( root->children[0]->type == NUMBER_DATA ) | |||||
| { | |||||
| result = root->children[0]; | |||||
| if ( root->data != NULL ) | |||||
| *((int64_t *)result->data) *= -1; | |||||
| node_finalize (root); | |||||
| } | |||||
| else if ( root->data == NULL ) | |||||
| { | |||||
| result = root->children[0]; | |||||
| node_finalize (root); | |||||
| } | |||||
| break; | |||||
| case 2: | |||||
| if ( root->children[0]->type == NUMBER_DATA && | |||||
| root->children[1]->type == NUMBER_DATA | |||||
| ) { | |||||
| result = root->children[0]; | |||||
| int64_t | |||||
| *x = result->data, | |||||
| *y = root->children[1]->data; | |||||
| switch ( *((char *)root->data) ) | |||||
| { | |||||
| case '+': *x += *y; break; | |||||
| case '-': *x -= *y; break; | |||||
| case '*': *x *= *y; break; | |||||
| case '/': *x /= *y; break; | |||||
| } | |||||
| node_finalize ( root->children[1] ); | |||||
| node_finalize ( root ); | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| *simplified = result; | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| #include <vslc.h> | |||||
| void | |||||
| node_print ( node_t *root, int nesting ) | |||||
| { | |||||
| if ( root != NULL ) | |||||
| { | |||||
| printf ( "%*c%s", nesting, ' ', node_string[root->type] ); | |||||
| if ( root->type == IDENTIFIER_DATA || | |||||
| root->type == STRING_DATA || | |||||
| root->type == RELATION || | |||||
| root->type == EXPRESSION ) | |||||
| printf ( "(%s)", (char *) root->data ); | |||||
| else if ( root->type == NUMBER_DATA ) | |||||
| printf ( "(%ld)", *((int64_t *)root->data) ); | |||||
| putchar ( '\n' ); | |||||
| for ( int64_t i=0; i<root->n_children; i++ ) | |||||
| node_print ( root->children[i], nesting+1 ); | |||||
| } | |||||
| else | |||||
| printf ( "%*c%p\n", nesting, ' ', root ); | |||||
| } | |||||
| void | |||||
| node_init (node_t *nd, node_index_t type, void *data, uint64_t n_children, ...) | |||||
| { | |||||
| va_list child_list; | |||||
| *nd = (node_t) { | |||||
| .type = type, | |||||
| .data = data, | |||||
| .entry = NULL, | |||||
| .n_children = n_children, | |||||
| .children = (node_t **) malloc ( n_children * sizeof(node_t *) ) | |||||
| }; | |||||
| va_start ( child_list, n_children ); | |||||
| for ( uint64_t i=0; i<n_children; i++ ) | |||||
| nd->children[i] = va_arg ( child_list, node_t * ); | |||||
| va_end ( child_list ); | |||||
| } | |||||
| void | |||||
| node_finalize ( node_t *discard ) | |||||
| { | |||||
| if ( discard != NULL ) | |||||
| { | |||||
| free ( discard->data ); | |||||
| free ( discard->children ); | |||||
| free ( discard ); | |||||
| } | |||||
| } | |||||
| void | |||||
| destroy_subtree ( node_t *discard ) | |||||
| { | |||||
| if ( discard != NULL ) | |||||
| { | |||||
| for ( uint64_t i=0; i<discard->n_children; i++ ) | |||||
| destroy_subtree ( discard->children[i] ); | |||||
| node_finalize ( discard ); | |||||
| } | |||||
| } | |||||
| void | |||||
| simplify_tree ( node_t **simplified, node_t *root ) | |||||
| { | |||||
| *simplified = root; | |||||
| } | |||||
| @@ -0,0 +1,25 @@ | |||||
| #include <stdio.h> | |||||
| #include <stdlib.h> | |||||
| #include <vslc.h> | |||||
| node_t *root; // Syntax tree | |||||
| tlhash_t *global_names; // Symbol table | |||||
| char **string_list; // List of strings in the source | |||||
| size_t n_string_list = 8; // Initial string list capacity (grow on demand) | |||||
| size_t stringc = 0; // Initial string count | |||||
| int | |||||
| main ( int argc, char **argv ) | |||||
| { | |||||
| yyparse(); | |||||
| simplify_tree ( &root, root ); | |||||
| node_print ( root, 0 ); | |||||
| // call function to create symbol table | |||||
| // then call function to print symbol table | |||||
| destroy_subtree ( root ); | |||||
| // call function to destroy symbol table | |||||
| } | |||||
| @@ -0,0 +1,9 @@ | |||||
| TARGETS=$(shell ls *.vsl | sed s/\.vsl/\.tree/g) | |||||
| all: ${TARGETS} | |||||
| %: %.s | |||||
| %.tree: %.vsl | |||||
| ../src/vslc <$*.vsl > $*.tree | |||||
| clean: | |||||
| -rm -f *.tree | |||||
| purge: clean | |||||
| -rm -f ${TARGETS} | |||||
| @@ -0,0 +1,84 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(euclid) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(b) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(b) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(b) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(gcd) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| NUMBER_DATA(1) | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("Greatest common divisor of") | |||||
| IDENTIFIER_DATA(a) | |||||
| STRING_DATA("and") | |||||
| IDENTIFIER_DATA(b) | |||||
| STRING_DATA("is") | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(gcd) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| STRING_DATA("and") | |||||
| IDENTIFIER_DATA(b) | |||||
| STRING_DATA("are relative primes") | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(gcd) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(g) | |||||
| STATEMENT_LIST | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(b) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(g) | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(gcd) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(b) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(*) | |||||
| EXPRESSION(/) | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| IDENTIFIER_DATA(b) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(g) | |||||
| IDENTIFIER_DATA(a) | |||||
| RETURN_STATEMENT | |||||
| IDENTIFIER_DATA(g) | |||||
| @@ -0,0 +1,20 @@ | |||||
| def euclid ( a, b ) | |||||
| begin | |||||
| if a < 0 then a := -a | |||||
| if b < 0 then b := -b | |||||
| if gcd ( a, b ) > 1 then | |||||
| print "Greatest common divisor of", a, "and", b, "is", gcd ( a, b ) | |||||
| else | |||||
| print a, "and", b, "are relative primes" | |||||
| return 0 | |||||
| end | |||||
| def gcd( a, b ) | |||||
| begin | |||||
| var g | |||||
| if b > 0 then | |||||
| g := gcd ( b, a - ((a/b)*b) ) | |||||
| else | |||||
| g := a | |||||
| return g | |||||
| end | |||||
| @@ -0,0 +1,118 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(main) | |||||
| (nil) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STATEMENT_LIST | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("Hello, world!") | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("") | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("Hello, \"world\"!") | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| NUMBER_DATA(10) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a_2) | |||||
| NUMBER_DATA(2) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(+) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| STRING_DATA("+") | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STRING_DATA(":=") | |||||
| IDENTIFIER_DATA(a) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| STRING_DATA("-") | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STRING_DATA(":=") | |||||
| IDENTIFIER_DATA(a) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(+) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| STRING_DATA("+ (-") | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STRING_DATA(") :=") | |||||
| IDENTIFIER_DATA(a) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(*) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| STRING_DATA("*") | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STRING_DATA(":=") | |||||
| IDENTIFIER_DATA(a) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(/) | |||||
| IDENTIFIER_DATA(_a1) | |||||
| IDENTIFIER_DATA(a_2) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(_a1) | |||||
| STRING_DATA("/") | |||||
| IDENTIFIER_DATA(a_2) | |||||
| STRING_DATA(":=") | |||||
| IDENTIFIER_DATA(a) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(0) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| WHILE_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(0) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(3) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(1) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(1) | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("Skip...") | |||||
| NULL_STATEMENT | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| @@ -0,0 +1,47 @@ | |||||
| // This program doesn't do anything interesting, it's just to exercise | |||||
| // most of the lexical entities. | |||||
| def main() begin // def, identifier (func. def.) | |||||
| var a, _a1, a_2 // var, identifier, comma operator | |||||
| print "Hello, world!" // print keyword, string literal | |||||
| print "" // Whitespace: line starts on a tab character | |||||
| print "Hello, \"world\"!" // String literal with escaped double quotes | |||||
| _a1 := 10 // Assignment operator and number constant | |||||
| a_2 := 2 | |||||
| a := _a1 + a_2 // Plus operator | |||||
| print _a1, "+", a_2, ":=", a | |||||
| a := _a1 - a_2 // Minus operator | |||||
| print _a1, "-", a_2, ":=", a | |||||
| a := _a1 + (-a_2) // Parentheses, unary minus operator | |||||
| print _a1, "+ (-", a_2, ") :=", a | |||||
| a := _a1 * a_2 // Multiply operator | |||||
| print _a1, "*", a_2, ":=", a | |||||
| a := _a1 / a_2 // Divide operator | |||||
| print _a1, "/", a_2, ":=", a | |||||
| if a > 0 then // if, then, FI, single statement | |||||
| print a | |||||
| // This loop prints the integers 5 through 0, skipping 2 | |||||
| while a > 0 do // while/do, block statements | |||||
| begin | |||||
| if a - 3 > 0 then // if/then/else/FI | |||||
| a := a - 1 | |||||
| else | |||||
| begin | |||||
| a := a - 1 | |||||
| print "Skip..." | |||||
| continue // continue | |||||
| end | |||||
| print a | |||||
| end | |||||
| return 0 // return keyword and number constant | |||||
| end | |||||
| @@ -0,0 +1,59 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(newton) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(n) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("The square root of") | |||||
| IDENTIFIER_DATA(n) | |||||
| STRING_DATA("is") | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(improve) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(n) | |||||
| NUMBER_DATA(1) | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(improve) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(n) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(next) | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(next) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| EXPRESSION(/) | |||||
| EXPRESSION(-) | |||||
| EXPRESSION(*) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| IDENTIFIER_DATA(n) | |||||
| EXPRESSION(*) | |||||
| NUMBER_DATA(2) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(next) | |||||
| IDENTIFIER_DATA(estimate) | |||||
| NUMBER_DATA(0) | |||||
| RETURN_STATEMENT | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(next) | |||||
| NUMBER_DATA(1) | |||||
| RETURN_STATEMENT | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(improve) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(n) | |||||
| IDENTIFIER_DATA(next) | |||||
| @@ -0,0 +1,22 @@ | |||||
| // Approximate square root by the Newton/Raphson method for f(x) = x^2 - n | |||||
| // f(x) = x^2 - n = 0 | |||||
| // f'(x) = 2x | |||||
| // x{n+1} = x{n} - (x^2-n) / 2x | |||||
| def newton ( n ) | |||||
| begin | |||||
| print "The square root of", n, "is", improve ( n, 1 ) | |||||
| return 0 | |||||
| end | |||||
| def improve ( n, estimate ) | |||||
| begin | |||||
| var next | |||||
| next := estimate - ( (estimate * estimate - n) / ( 2 * estimate ) ) | |||||
| if next - estimate = 0 then | |||||
| // Integer precision converges at smallest int greater than the square | |||||
| return next-1 | |||||
| else | |||||
| return improve ( n, next ) | |||||
| end | |||||
| @@ -0,0 +1,20 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(unary_minus_precedence) | |||||
| (nil) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(-2) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(b) | |||||
| NUMBER_DATA(-2) | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| @@ -0,0 +1,7 @@ | |||||
| def unary_minus_precedence() | |||||
| begin | |||||
| var a, b | |||||
| a := -1*2 | |||||
| b := (-1)*2 | |||||
| return 0 | |||||
| end | |||||
| @@ -0,0 +1,71 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(main) | |||||
| (nil) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| RETURN_STATEMENT | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(factor) | |||||
| EXPRESSION_LIST | |||||
| NUMBER_DATA(1836311903) | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(factor) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(n) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(f) | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(f) | |||||
| EXPRESSION(/) | |||||
| IDENTIFIER_DATA(n) | |||||
| NUMBER_DATA(2) | |||||
| WHILE_STATEMENT | |||||
| RELATION | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(n) | |||||
| EXPRESSION(*) | |||||
| IDENTIFIER_DATA(f) | |||||
| EXPRESSION(/) | |||||
| IDENTIFIER_DATA(n) | |||||
| IDENTIFIER_DATA(f) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(f) | |||||
| EXPRESSION(-) | |||||
| IDENTIFIER_DATA(f) | |||||
| NUMBER_DATA(1) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(f) | |||||
| NUMBER_DATA(1) | |||||
| BLOCK | |||||
| DECLARATION_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(r) | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(r) | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(factor) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(f) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(r) | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(factor) | |||||
| EXPRESSION_LIST | |||||
| EXPRESSION(/) | |||||
| IDENTIFIER_DATA(n) | |||||
| IDENTIFIER_DATA(f) | |||||
| PRINT_STATEMENT | |||||
| IDENTIFIER_DATA(n) | |||||
| STRING_DATA("is a prime factor") | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| @@ -0,0 +1,26 @@ | |||||
| // VSL version of prime assembly exercise, courtesy | |||||
| // of J.H.Ø. Anthony (class of 2011) | |||||
| def main () | |||||
| begin | |||||
| return factor (1836311903) | |||||
| end | |||||
| def factor (n) | |||||
| begin | |||||
| var f | |||||
| f := n/2 | |||||
| while n - f*(n/f) > 0 do | |||||
| f := f - 1 | |||||
| if f > 1 then | |||||
| begin | |||||
| var r | |||||
| r := factor (f) | |||||
| r := factor (n/f) | |||||
| end | |||||
| else | |||||
| print n, "is a prime factor" | |||||
| return 0 | |||||
| end | |||||
| @@ -0,0 +1,36 @@ | |||||
| PROGRAM | |||||
| GLOBAL_LIST | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(a) | |||||
| IDENTIFIER_DATA(b) | |||||
| DECLARATION | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(c) | |||||
| IDENTIFIER_DATA(d) | |||||
| FUNCTION | |||||
| IDENTIFIER_DATA(simplify) | |||||
| VARIABLE_LIST | |||||
| IDENTIFIER_DATA(e) | |||||
| IDENTIFIER_DATA(f) | |||||
| BLOCK | |||||
| STATEMENT_LIST | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(-29) | |||||
| PRINT_STATEMENT | |||||
| STRING_DATA("a=") | |||||
| IDENTIFIER_DATA(a) | |||||
| IF_STATEMENT | |||||
| RELATION | |||||
| IDENTIFIER_DATA(a) | |||||
| NUMBER_DATA(0) | |||||
| ASSIGNMENT_STATEMENT | |||||
| IDENTIFIER_DATA(b) | |||||
| EXPRESSION((null)) | |||||
| IDENTIFIER_DATA(simplify) | |||||
| EXPRESSION_LIST | |||||
| IDENTIFIER_DATA(c) | |||||
| IDENTIFIER_DATA(d) | |||||
| RETURN_STATEMENT | |||||
| NUMBER_DATA(0) | |||||
| @@ -0,0 +1,9 @@ | |||||
| var a,b | |||||
| var c,d | |||||
| def simplify ( e, f ) | |||||
| begin | |||||
| a := - ( 5*5 + 20/4 - 3 + 2) | |||||
| print "a=", a | |||||
| if a=0 then b := simplify ( c, d ) | |||||
| return 0 | |||||
| end | |||||