Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Everything running on a Mac OS X Lion, GCC 4.8 got from macports, CLang from recent repository.
- GCC 4.8 -O0: TODO! [gypsy.c, line 433]
- GCC 4.8 -01: Parses the file successfully.
- GCC 4.8 -O2: Unexpected high byte on file (0xE0).
- GCC 4.8 -O3: Unexpected high byte on file (0xE0).
- CLang, last version (3.3, trunk 173610), -Wno-return-type, -O0: Parses the file successfully.
- CLang, last version (3.3, trunk 173610), -Wno-return-type, -O1: Unexpected high byte on file (0xE0).
- CLang, last version (3.3, trunk 173610), -Wno-return-type, -O2: Unexpected high byte on file (0xE0).
- CLang, last version (3.3, trunk 173610), -Wno-return-type, -O3: Unexpected high byte on file (0xE0).
- CLang, last version (3.3, trunk 173610), -Wno-return-type, -O4: Unexpected high byte on file (0xE0).
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #define fallthrough
- char *strtrim(str) char *str; {
- /* Declarations */
- static char buf[64];
- auto i, x, len;
- /* Statements */
- len = strlen(str);
- x = 0;
- for(i = 0; i < len; i++) {
- if((!x) && (str[i] == ' ' || str[i] == '\t'))
- continue;
- buf[x++] = str[i];
- }
- buf[x] = 0;
- while(--x)
- if(buf[x] == ' ' || buf[x] == '\t')
- buf[x] = 0;
- else break;
- return buf;
- }
- char *zalloc(size) size_t size; {
- /* Declarations */
- char *result;
- /* Statements */
- result = malloc(size);
- if(result) {
- memset(result, 0, size);
- return result;
- } else {
- printf("Memory exausted: aborting.\n");
- exit(-1);
- }
- }
- //----------------------------------
- /* Needed constants for the GYPSY parser, plus a default buffer size */
- #define GYPSY_ASSURE 0x101 /**< */
- #define GYPSY_THAT 0x102 /**< */
- #define GYPSY_COMPILES 0x103 /**< */
- #define GYPSY_LINKS 0x104 /**< */
- #define GYPSY_INTO 0x105 /**< */
- #define GYPSY_SUCCEEDS 0x106 /**< */
- #define GYPSY_FAILS 0x107 /**< */
- #define GYPSY_RETURNS 0x108 /**< */
- #define GYPSY_EXISTS 0x109 /**< */
- #define GYPSY_OUTPUTS 0x10A /**< */
- #define GYPSY_SET 0x10B /**< */
- #define GYPSY_TO 0x10C /**< */
- #define GYPSY_UNSET 0x10D /**< */
- #define GYPSY_BLOCK 0x10E /**< */
- #define GYPSY_TEXT 0x10F /**< */
- #define GYPSY_FILE 0x110 /**< */
- #define GYPSY_EOF 0x111 /**< */
- #define GYPSY_BUF 0x800 /**< */
- /** GYPSY Token Str: returns a string representation of a GYPSY parser token. */
- char *gypsy_token_str(token) {
- /* Declarations */
- static char buf[64];
- /* Statements */
- switch(token) {
- #define TOKEN(x, s) case x: strcpy(buf, #x); strcat(buf, s); break
- TOKEN(GYPSY_ASSURE, "");
- TOKEN(GYPSY_THAT, "");
- TOKEN(GYPSY_COMPILES, "");
- TOKEN(GYPSY_LINKS, "");
- TOKEN(GYPSY_INTO, "");
- TOKEN(GYPSY_SUCCEEDS, "");
- TOKEN(GYPSY_FAILS, "");
- TOKEN(GYPSY_RETURNS, "");
- TOKEN(GYPSY_OUTPUTS, "");
- TOKEN(GYPSY_SET, "");
- TOKEN(GYPSY_UNSET, "");
- TOKEN(GYPSY_BLOCK, "");
- TOKEN(GYPSY_TEXT, "");
- TOKEN(GYPSY_FILE, "");
- #undef TOKEN
- default:
- /* If we fall here, the token is an ASCII character */
- sprintf(buf, "`%c' (0x%02X)", token, token);
- }
- /* Return the temporary buffer... note that this function is not reentrant */
- return buf;
- }
- /**
- *
- */
- static struct {
- char *name;
- int token;
- } gypsy_keywords[] = {
- {"assure", GYPSY_ASSURE},
- {"that", GYPSY_THAT},
- {"compiles", GYPSY_COMPILES},
- {"links", GYPSY_LINKS},
- {"into", GYPSY_INTO},
- {"succeeds", GYPSY_SUCCEEDS},
- {"fails", GYPSY_FAILS},
- {"returns", GYPSY_RETURNS},
- {"exists", GYPSY_EXISTS},
- {"outputs", GYPSY_OUTPUTS},
- {"set", GYPSY_SET},
- {"to", GYPSY_TO},
- {"unset", GYPSY_UNSET}
- };
- /**
- *
- */
- gypsy_cmd_compiles(input, output) char *input, *output; {
- }
- /**
- *
- */
- gypsy_cmd_links(input, output) char *input, *output; {
- }
- /**
- *
- */
- gypsy_cmd_succeeds(command, foo) char *command, *foo; {
- }
- /**
- *
- */
- gypsy_cmd_fails(command, foo) char *command, *foo; {
- }
- /**
- *
- */
- gypsy_cmd_returns(command, exit_code) char *command, *exit_code; {
- }
- /**
- *
- */
- gypsy_cmd_exists(filename, foo) char *filename, *foo; {
- }
- /**
- *
- */
- gypsy_cmd_outputs(command, text) char *command, *text; {
- }
- /** */
- typedef struct gypsy_command {
- char argument1[64];
- char argument2[64];
- int (*callback)(char *, char *);
- struct gypsy_command *next;
- } gypsy_command;
- /** */
- typedef struct gypsy_parser {
- char filename[64];
- FILE *file;
- int line;
- int ahead_line;
- int token;
- int ahead;
- int behind;
- gypsy_command *head;
- gypsy_command *tail;
- int sol;
- char buf[GYPSY_BUF];
- char aux[GYPSY_BUF];
- char err[GYPSY_BUF];
- } gypsy_parser;
- /** */
- gypsy_chain_command(parser, command) gypsy_parser *parser;
- gypsy_command *command; {
- if(parser->head) {
- printf("todo lol lol lol\n");
- exit(-1);
- } else {
- parser->head = command;
- parser->tail = command;
- }
- }
- /** */
- gypsy_lacking_newline(parser) gypsy_parser *parser; {
- printf("Warning: no newline at the end of file (%s).\n", parser->filename);
- }
- /** */
- gypsy_parse_error(parser) gypsy_parser *parser; {
- printf("GYPSY Error (%s, line %d)! ", parser->filename, parser->line);
- puts(parser->err);
- exit(-1);
- }
- /** GYPSY To Do: helper function to show an error for some missing part. */
- gypsy_todo(parser, file, line) gypsy_parser *parser; char *file; {
- sprintf(parser->err, "TODO! [%s, line %d]", file, line);
- gypsy_parse_error(parser);
- }
- /** Simplify the task by automatically adding the position of the call. */
- #define gypsy_todo(parser) gypsy_todo(parser, __FILE__, __LINE__)
- /** */
- gypsy_try_keyword(peek, parser, real) gypsy_parser *parser; {
- /* Declarations */
- auto i, j;
- char buf[32];
- /* Statements */
- for(i = 0; i < sizeof(gypsy_keywords) / sizeof(gypsy_keywords[0]); i++) {
- #define keyword gypsy_keywords[i]
- /* */
- if(keyword.name[0] == tolower(peek)) {
- for(j = 1; j < strlen(keyword.name); j++) {
- buf[j] = fgetc(parser->file);
- if(keyword.name[j] != tolower(buf[j])) {
- while(j) {
- ungetc(buf[j], parser->file);
- j--;
- }
- goto next;
- }
- }
- /* Matches! */
- parser->ahead = keyword.token;
- if(real)
- parser->aux[0] = 0;
- else {
- /* If we were just checking ahead, unget everything */
- while(j) {
- ungetc(buf[j], parser->file);
- j--;
- }
- ungetc(peek, parser->file);
- }
- return 1;
- }
- /* */
- next: fallthrough;
- #undef keyword
- }
- /* */
- return 0;
- }
- /** */
- gypsy_get_lookahead(parser) gypsy_parser *parser; {
- /* Declarations */
- auto peek, prev, i, j;
- /* Statements */
- peek = fgetc(parser->file);
- if(peek > 0x7F) {
- sprintf(parser->err, "Unexpected high byte on file (0x%02X).", peek);
- gypsy_parse_error(parser);
- }
- /* */
- switch(peek) {
- case -1:
- if(!parser->sol)
- gypsy_lacking_newline(parser);
- parser->ahead = GYPSY_EOF;
- break;
- /* Check for possible comments */
- case '(':
- peek = fgetc(parser->file);
- if(peek == '*') {
- /* We started a comment */
- parser->sol = 0;
- /* Eat it up */
- peek = fgetc(parser->file);
- do {
- prev = peek;
- peek = fgetc(parser->file);
- if(prev == '*' && peek == ')')
- return gypsy_get_lookahead(parser);
- if(peek == '\n' || ((prev == '\r' && peek != '\n')))
- parser->ahead_line++;
- } while(peek > 0);
- /* Unterminated comment found */
- sprintf(parser->err, "Unterminated comment.");
- gypsy_parse_error(parser);
- } else stray: {
- sprintf(parser->err, "Stray '%c' (0x%02X) on file.", peek, peek);
- gypsy_parse_error(parser);
- };
- /* */
- case ' ':
- case '\t':
- parser->sol = 0;
- do {
- strcat(parser->aux, peek == ' ' ? " " : "\t");
- peek = fgetc(parser->file);
- } while(peek == ' ' || peek == '\t');
- ungetc(peek, parser->file);
- return gypsy_get_lookahead(parser);
- case '\r':
- /* Special check for \r\n to count as one single line */
- peek = fgetc(parser->file);
- if(peek != '\n')
- ungetc(peek, parser->file);
- fallthrough;
- case '\n':
- parser->sol = 1;
- /* Increase the line counter, and warn the newline (only once!) */
- parser->ahead_line++;
- /* Clean the auxiliar buffer */
- parser->aux[0] = 0;
- /* Resume the procedure */
- return gypsy_get_lookahead(parser);
- /* */
- case '[':
- if(parser->sol) {
- i = 0;
- do {
- prev = peek;
- peek = fgetc(parser->file);
- parser->aux[i] = peek;
- if(prev == ']') {
- if(peek == -1)
- gypsy_lacking_newline(parser);
- else
- if(peek == '\n' || peek == '\r')
- ungetc(peek, parser->file);
- else {
- sprintf(parser->err, "Unexpected `%c', expected newline.",
- peek);
- gypsy_parse_error(parser);
- }
- /* */
- parser->aux[i] = 0;
- /* */
- parser->ahead = GYPSY_BLOCK;
- /* We are done here */
- return;
- } else
- /*
- We should increase the counter if the current character isn't
- the end of the block
- */
- if(peek != ']')
- i++;
- } while(peek > 0);
- /* Falling here, the file has ended */
- sprintf(parser->err, "Unterminated block.");
- gypsy_parse_error(parser);
- } else {
- gypsy_todo(parser);
- }
- case ';':
- case '.':
- parser->aux[0] = 0;
- parser->ahead = peek;
- break;
- default:
- if(gypsy_try_keyword(peek, parser, 1))
- return;
- else
- for(i = strlen(parser->aux); peek > 0; i++) {
- parser->aux[i] = peek;
- peek = fgetc(parser->file);
- if(peek == -1) finish_text: {
- parser->aux[i] = 0;
- parser->ahead = GYPSY_TEXT;
- return;
- }
- if(gypsy_try_keyword(peek, parser, 0)) {
- goto finish_text;
- }
- if(peek == '\n' || peek == '\r' || peek == ';') {
- ungetc(peek, parser->file);
- i++;
- goto finish_text;
- }
- if(peek == '.') {
- peek = fgetc(parser->file);
- if(!peek)
- break;
- if(peek == '\n' || peek == '\r') {
- /* Dot token instead of part of the text */
- ungetc(peek, parser->file);
- ungetc('.', parser->file);
- i++;
- goto finish_text;
- }
- parser->aux[i++] = peek;
- }
- }
- gypsy_todo(parser);
- };
- }
- /** */
- gypsy_get_token(parser) gypsy_parser *parser; {
- parser->behind = parser->token;
- /* If running for the first time, get two tokens */
- if(!parser->token)
- gypsy_get_lookahead(parser);
- /* Move the previous lookahead to the current token */
- parser->line = parser->ahead_line;
- parser->token = parser->ahead;
- strcpy(parser->buf, parser->aux);
- /* And get a new lookahead */
- if(parser->token != GYPSY_EOF)
- gypsy_get_lookahead(parser);
- return parser->token;
- }
- gypsy_get_compiles(parser, command) gypsy_parser *parser;
- gypsy_command *command; {
- switch(parser->token) {
- case GYPSY_INTO:
- gypsy_get_token(parser);
- if(parser->token == GYPSY_TEXT) {
- strcpy(command->argument2, strtrim(parser->buf));
- gypsy_chain_command(parser, command);
- gypsy_get_token(parser);
- if(parser->token == ';' || parser->token == '.')
- return;
- free(command);
- sprintf(parser->err, "Expected ';' or '.' at line %d; got %s instead.",
- parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- } else {
- free(command);
- sprintf(parser->err, "Expected GYPSY_TEXT at line %d; got %s instead.",
- parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- case ';':
- case '.':
- gypsy_chain_command(parser, command);
- return;
- default:
- free(command);
- sprintf(parser->err, "Expected GYPSY_INTO at line %d; got %s instead.",
- parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- }
- gypsy_get_assure2(parser, command) gypsy_parser *parser;
- gypsy_command *command; {
- switch(parser->token) {
- case GYPSY_COMPILES:
- command->callback = gypsy_cmd_compiles;
- gypsy_get_token(parser);
- gypsy_get_compiles(parser, command);
- break;
- case GYPSY_LINKS:
- command->callback = gypsy_cmd_links;
- gypsy_todo(parser);
- case GYPSY_SUCCEEDS:
- command->callback = gypsy_cmd_succeeds;
- gypsy_todo(parser);
- case GYPSY_FAILS:
- command->callback = gypsy_cmd_fails;
- gypsy_todo(parser);
- case GYPSY_RETURNS:
- command->callback = gypsy_cmd_returns;
- gypsy_todo(parser);
- case GYPSY_OUTPUTS:
- command->callback = gypsy_cmd_outputs;
- gypsy_todo(parser);
- default:
- sprintf(parser->err, "Expected GYPSY_COMPILES, GYPSY_LINKS, GYPSY_SUCCEED"
- "S, GYPSY_FAILS, GYPSY_RETURNS or GYPSY_OUTPUTS at line %d; got %"
- "s instead.", parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- }
- gypsy_get_assure(parser) gypsy_parser *parser; {
- /* Declarations */
- gypsy_command *command;
- /* Statements */
- if(parser->token == GYPSY_ASSURE) {
- gypsy_get_token(parser);
- if(parser->token == GYPSY_THAT) {
- gypsy_get_token(parser);
- if(parser->token == GYPSY_TEXT) {
- command = (gypsy_command *)zalloc(sizeof(gypsy_command));
- strcpy(command->argument1, strtrim(parser->buf));
- gypsy_get_token(parser);
- gypsy_get_assure2(parser, command);
- } else {
- sprintf(parser->err, "Expected GYPSY_TEXT at line %d; got %s instead.",
- parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- } else {
- sprintf(parser->err, "Expected GYPSY_THAT at line %d; got %s instead.",
- parser->line, gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- }
- }
- gypsy_get_unit(parser) gypsy_parser *parser; {
- while(parser->token != GYPSY_EOF) {
- switch(parser->token) {
- case GYPSY_ASSURE:
- gypsy_get_assure(parser);
- if(parser->token == '.')
- return;
- if(parser->token == ';')
- gypsy_get_token(parser);
- continue;
- case GYPSY_SET:
- case GYPSY_UNSET:
- gypsy_todo(parser);
- default:
- sprintf(parser->err, "Expected GYPSY_ASSURE, GYPSY_SET or GYPSY_UNSET; "
- "got %s instead.", gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- break;
- }
- }
- }
- gypsy_get_file(parser) gypsy_parser *parser; {
- }
- gypsy_get_unit_or_file(parser) gypsy_parser *parser; {
- if(parser->token == GYPSY_BLOCK) {
- gypsy_get_token(parser);
- if(strchr(parser->buf, '.'))
- gypsy_get_file(parser);
- else gypsy_get_unit(parser);
- } else {
- sprintf(parser->err, "Expected GYPSY_BLOCK; got %s instead.",
- gypsy_token_str(parser->token));
- gypsy_parse_error(parser);
- }
- }
- /** */
- gypsy_parse(parser) gypsy_parser *parser; {
- /*gypsy_get_token(parser);
- while(parser->token != GYPSY_EOF)
- gypsy_get_unit_or_file(parser);*/
- while(parser->token != GYPSY_EOF) {
- gypsy_get_token(parser);
- printf("Token: %s [%d]\n", gypsy_token_str(parser->token), parser->line);
- };
- exit(-1);
- return 1;
- }
- /** */
- gypsy_parser *gypsy_open(file) char *file; {
- /* Declarations */
- gypsy_parser *result;
- /* Statements */
- result = (gypsy_parser *)zalloc(sizeof(gypsy_parser));
- /* Check for the allocation */
- if(result) {
- result->file = fopen(file, "r");
- /* If the file could be open */
- if(result->file) {
- /* We setup and return the newly allocated object */
- result->ahead_line = 1;
- result->sol = 1;
- strcpy(result->filename, file);
- /* And then parse it */
- if(!gypsy_parse(result)) {
- strcpy(result->err, "Sorry, couldn't parse file.");
- gypsy_parse_error(result);
- }
- /* Now we can close the file and return safely */
- fclose(result->file);
- result->file = 0;
- return result;
- }
- }
- /* Return NULL if anything bad happened */
- return 0;
- }
- /** */
- gypsy_parser *gypsy_test(parser) gypsy_parser *parser; {
- }
- /** */
- gypsy_close(parser) gypsy_parser *parser; {
- if(parser)
- free(parser);
- }
- int main() {
- gypsy_parser *parser = gypsy_open("test.psy");
- gypsy_close(parser);
- return EXIT_SUCCESS;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement