| @@ -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 | |||