Jump to content
  • entries
    16
  • comments
    27
  • views
    11,243

Progress in Programming


Rhindle the Dragon

1,006 views

blog-0156537001488852877.jpg

MEMOIRS OF A NOVELTY ACCOUNT

VOL. II, ISSUE IV

Good evening. I am... Dracula. Ah ah ah.

For me, this Monday was truly imperial. I was stuck at a certain part of my CS210 lexer assignment, and showed it to my instructor, saying "I feel like if I just get past this problem, I could finish this in two hours." He said he severely doubted my ability to do that.

Guess what? I got past the problem and finished the assignment in two hours. And I even did it in less than 300 lines! In fact, I'm so freaking proud of this that I'll share it with the community.

 

Here you go:

/*--------------------------------------------------------------	Lexer Assignment	CS 210	Rhindle the Dragon	2-27-2017 to 3-6-2017	Deep as a river, wide as the sea	Changin' the ways of a captain and me--------------------------------------------------------------*/#include <stdio.h>#include <string.h>#include "keys.h"#define MAXSIZE 1048576#define WORKSIZE 256int iskeyword(char []);int isoperator(char []);int main(int argc, char *argv[]){	if (argc == 1)	{		printf("\nYou MUST specify the name of a file to read.\n\n");		return 0;	}	FILE *fp = fopen(argv[1], "r");	if (!fp)	{		printf("\nError opening file!\n\n");		return 1;	}	char a, master[MAXSIZE], working[WORKSIZE];	int i, j;	/* This loop feeds the entire file into an array. */	for (i = 0; (a = fgetc(fp)) != EOF; i++)		master[i] = a;	fclose(fp);	printf("\n");	/* The parsing portion begins here. */	for (i = 0; master[i] != '\0'; i++)	{		/* This section skips white space. */		if (master[i] == ' ' || master[i] == '\n' || master[i] == '\t')			continue;		/* This section checks for comments. */		else if (master[i] == '/' && master[i + 1] == '*')		{			printf("%c", master[i]);			while (1)			{				if (master[i + 2] == '*' && master[i + 3] == '/')					break;				i++;				printf("%c", master[i]);			}			printf("%c%c%c (comment)\n", master[i + 1], master[i + 2], master[i + 3]);			i += 4;		}		/* This section checks for string literals. */		else if (master[i] == '\"')		{			j = 0;			working[j] = master[i];			i++;			j++;			while (master[i] != '\"')			{				working[j] = master[i];				i++;				j++;			}			working[j] = master[i];			working[j + 1] = '\0';			printf("%s (string)\n", working);		}		/* This section checks for character literals. */		else if (master[i] == '\'')		{			for (j = 0; j < 3; j++)			{				working[j] = master[i];				i++;			}			working[j] = '\0';			i--;			printf("%s (character literal)\n", working);		}		/* This section checks for numeric literals. */		else if (master[i] > 0x2F && master[i] < 0x3A)		{			j = 0;			while ((master[i] > 0x2F && master[i] < 0x3A) ||				(master[i] > 0x40 && master[i] < 0x47) ||				(master[i] > 0x60 && master[i] < 0x67) ||				master[i] == 0x23 || master[i] == 0x2E || master[i] == 0x5F)			{				working[j] = master[i];				i++;				j++;			}			i--;			working[j] = '\0';			printf("%s (numeric literal)\n", working);		}		/* This section checks for identifiers and possible keywords. */		else if ((master[i] > 0x60 && master[i] < 0x7B) ||			(master[i] > 0x40 && master[i] < 0x5B))		{			j = 0;			while ((master[i] > 0x60 && master[i] < 0x7B) ||				(master[i] > 0x40 && master[i] < 0x5B) ||				(master[i] > 0x2F && master[i] < 0x3A) || (master[i] == 0x5F))			{				working[j] = master[i];		/* Feed lexeme into array */				i++;				j++;			}			i--;			working[j] = '\0';			if (iskeyword(working) == 0)			/* Check if keyword */				printf("%s (keyword)\n", working);			else				printf("%s (identifier)\n", working);		}		/* This section checks for operators. */		else if ((master[i] > 0x27 && master[i] < 0x30) ||			(master[i] > 0x39 && master[i] < 0x3F) ||			master[i] == 0x21 || master[i] == 0x26 ||			master[i] == 0x5B || master[i] == 0x5D || master[i] == 0x7C)		{			j = 0;			working[j] = master[i];			i++;			j++;			if (master[i] == '=' || master[i] == '.' || master[i] == '<' ||				master[i] == '>' || master[i] == '*')			{				working[j] = master[i];				j++;			}			else				i--;			working[j] = '\0';			if (isoperator(working) == 0)				printf("%s (operator)\n", working);			else			{				printf("ILLEGAL OPERATOR\n");				return 0;			}		}		/* This is the default condition. */		else		{			printf("UNK\n");			return 0;		}	}	printf("\n");	return 0;}int iskeyword(char working[]){	int k;	int flag1 = 0;	for (k = 0; k < MONKEY; k++)	{		if (strcmp(keys[k], working) == 0)		{			flag1 = 1;			break;		}	}	if (flag1 == 1)		return 0;	else		return 1;}int isoperator(char working[]){	int k;	int flag1 = 0;	for (k = 0; k < BROADWAY; k++)	{		if (strcmp(opers[k], working) == 0)		{			flag1 = 1;			break;		}	}	if (flag1 == 1)		return 0;	else		return 1;}

And here's the header:

/*++++++++++++++++++++++++++++++++++++++++	Lexeme List Header	Rhindle the Dragon	2-27-2017 to 3-6-2017++++++++++++++++++++++++++++++++++++++++*/#define MONKEY 34#define BROADWAY 27const char *keys[MONKEY] ={	"accessor", "and", "array", "begin",	"bool", "case", "else", "elsif", "end", "exit",	"function", "if", "in", "integer", "interface", "is",	"loop", "module", "mutator", "natural", "null",	"of", "or", "others", "out", "positive", "procedure",	"return", "struct", "subtype", "then",	"type", "when", "while"};const char *opers[BROADWAY] ={	".", "<", ">", "(", ")", "+", "-", "*", "/",	"|", "&", ";", ",", ":", "[", "]", "=", ":=",	"..", "<<", ">>", "<>", "<=", ">=", "**",	"!=", "=>"};

Featured Photograph: 1882 Elgin pocket watch I bought with the refund money.

  • Like 1

2 Comments


Recommended Comments

Some suggestions

 

master[MAXSIZE], working[WORKSIZE]; // declare as global or use malloc so they use the heap rather than the stack

 

Replace for (i = 0; (a = fgetc(fp)) != EOF; i++) master = a; with fread

Or, make the code line based & use fgets rather than trying to load the entire file into memory at once.

 

All of those hexcode comparisons are ugly. Better to use the actual characters so you don't make errors remembering ASCII codes. You should probably also look at the ctype.h functions.

 

Looks like you're doing a tokenizer. Wouldn't hurt to see if you could use strtok rather than brute forcing it yourself. (Although strtok isn't the easiest function to understand & use.)

 

I'd also use pointers rather than array indexes - more efficient code.

 

That all being said - sometimes being told you can't do something is enough to motivate you to prove them wrong. And there's nothing wrong with brute force code to get you over the initial challenges. But learn the libraries and leverage those functions - you don't have to re-invent the wheel (why write your own quick sort routine when qsort exists), there's less risk of introducing your own bugs and they are typically faster because the library can be in native code.

Link to comment

Thanks for the pointers! *(no pun intended.)

 

Yeah I thought about making the master array dynamic. Something about setting a max size just bothers me.

I refrained from using strtok because I didn't initially design the program to use <string.h> even though I ended up using it anyway. Plus, I was required to do it on a character-by-character basis. I'm not familiar with fread yet.

 

I'll keep this in mind when I rebuild this for my own programming language.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...