changeset 35:cdb0175e1063

More work on expressions
author Lost Wizard (lost@starbug3)
date Sat, 05 Feb 2011 14:22:54 -0700
parents bfea77812e64
children 5325b640424d
files lwbasic/lexer.c lwbasic/lwbasic.h lwbasic/parser.c
diffstat 3 files changed, 190 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/lwbasic/lexer.c	Fri Feb 04 21:27:03 2011 -0700
+++ b/lwbasic/lexer.c	Sat Feb 05 14:22:54 2011 -0700
@@ -46,6 +46,7 @@
 	int token;
 };
 
+/* keywords that appear as part of normal expressions */
 static struct token_list lexer_global_tokens[] = 
 {
 	{ "function",		token_kw_function },
@@ -59,7 +60,18 @@
 	{ "endsub",			token_kw_endsub },
 	{ "endfunction",	token_kw_endfunction },
 	{ "dim",			token_kw_dim },
-	{ "=",				token_op_assignment },
+	{ NULL }
+};
+
+/* contains "built in" function names */
+static struct token_list lexer_expr_tokens[] =
+{
+	{ "and",			token_op_and },
+	{ "or",				token_op_or },
+	{ "band",			token_op_band },
+	{ "bor", 			token_op_bor },
+	{ "bxor",			token_op_bxor },
+	{ "xor",			token_op_xor },
 	{ NULL }
 };
 
@@ -77,6 +89,23 @@
 	"ENDFUNCTION",
 	"DIM",
 	"<assignment>",
+	"<equality>",
+	"<greater>",
+	"<less>",
+	"<greaterequal>",
+	"<lessequal>",
+	"<notequal>",
+	"<and>",
+	"<or>",
+	"<xor>",
+	"<bitwiseand>",
+	"<bitwiseor>",
+	"<bitwisexor>",
+	"<plus>",
+	"<minus>",
+	"<times>",
+	"<divide>",
+	"<modulus>",
 	"<identifier>",
 	"<char>",
 	"<uint>",
@@ -171,6 +200,11 @@
 		tok = lexer_global_tokens;
 	}
 	
+	if (state -> expression)
+	{
+		tok = lexer_expr_tokens;
+	}
+	
 	/* check for tokens if appropriate */
 	/* force uppercase */
 	if (tok)
@@ -194,6 +228,39 @@
 		state -> lexer_token = token_identifier;
 }
 
+static void lexer_parse_number(cstate *state, int neg)
+{
+	unsigned long tint = 0;
+	int c;
+	
+	for (;;)
+	{
+		c = lexer_curchar(state);
+		if (c >= '0' && c <= '9')
+		{
+			tint *= 10 + (c - '0');
+		}
+		else
+		{
+			/* end of the number here */
+			if (neg)
+			{
+				if (tint > 0x80000000)
+					lwb_error("Integer overflow\n");
+				state -> lexer_token_number.integer = -tint;
+				state -> lexer_token = token_int;
+			}
+			else
+			{
+				state -> lexer_token = token_uint;
+				state -> lexer_token_number.uinteger = tint;
+			}
+			return;
+		}
+		lexer_nextchar(state);
+	}
+}
+
 static void lexer_empty_token(cstate *state)
 {
 	lw_free(state -> lexer_token_string);
@@ -239,13 +306,101 @@
 		lexer_word(state);
 		return;
 	}
+
+	if (state -> expression && c >= '0' && c <= '9')
+	{
+		/* we have a number */
+		lexer_parse_number(state, 0);
+		return;
+	}
+ 
+	lexer_nextchar(state);	
+	if (state -> expression)
+	{
+		if (c == '-' && lexer_curchar(state) >= '0' && lexer_curchar(state) <= '9')
+		{
+			/* we have a negative number here */
+			lexer_parse_number(state, 1);
+			return;
+		}
+		if (c == '=')
+		{
+			state -> lexer_token = token_op_equality;
+			return;
+		}
+		if (c == '<')
+		{
+			if (lexer_curchar(state) == '=')
+			{
+				lexer_nextchar(state);
+				state -> lexer_token = token_op_lessequal;
+				return;
+			}
+			if (lexer_curchar(state) == '>')
+			{
+				lexer_nextchar(state);
+				state -> lexer_token = token_op_notequal;
+				return;
+			}
+			state -> lexer_token = token_op_less;
+			return;
+		}
+		if (c == '>')
+		{
+			if (lexer_curchar(state) == '>')
+			{
+				lexer_nextchar(state);
+				state -> lexer_token = token_op_greaterequal;
+				return;
+			}
+			if (lexer_curchar(state) == '<')
+			{
+				state -> lexer_token = token_op_notequal;
+				lexer_nextchar(state);
+				return;
+			}
+			state -> lexer_token = token_op_greater;
+			return;
+		}
+		switch(c)
+		{
+		case '+':
+			state -> lexer_token = token_op_plus;
+			return;
+		
+		case '-':
+			state -> lexer_token = token_op_minus;
+			return;
+		
+		case '/':
+			state -> lexer_token = token_op_divide;
+			return;
+		
+		case '*':
+			state -> lexer_token = token_op_times;
+			return;
+		
+		case '%':
+			state -> lexer_token = token_op_modulus;
+			return;
+		
+		
+		}
+	}
+	else
+	{
+		if (c == '=')
+		{
+			state -> lexer_token = token_op_assignment;
+			return;
+		}
+	}
 	
 	/* return the character if all else fails */
+	state -> lexer_token = token_char;
 	state -> lexer_token_string = lw_realloc(state -> lexer_token_string, 2);
 	state -> lexer_token_string[0] = c;
 	state -> lexer_token_string[1] = 0;
-	lexer_nextchar(state);
-	state -> lexer_token = token_char;
 	return;
 }
 
--- a/lwbasic/lwbasic.h	Fri Feb 04 21:27:03 2011 -0700
+++ b/lwbasic/lwbasic.h	Sat Feb 05 14:22:54 2011 -0700
@@ -53,7 +53,7 @@
 	int lexer_token;
 	int lexer_curchar;
 	int lexer_ignorechar;
-	
+	int expression;	
 	int parser_state;
 	
 	void *input_state;
@@ -87,6 +87,23 @@
 	token_kw_endfunction,		/* ENDFUNCTION keyword */
 	token_kw_dim,				/* DIM keyword */
 	token_op_assignment,		/* assignment operator */
+	token_op_equality,			/* equality test */
+	token_op_greater,			/* greater than */
+	token_op_less,				/* less than */
+	token_op_greaterequal,		/* greater or equal */
+	token_op_lessequal,			/* less or equal */
+	token_op_notequal,			/* not equal */
+	token_op_and,				/* boolean and */
+	token_op_or,				/* boolean or */
+	token_op_xor,				/* boolean exlusive or */
+	token_op_band,				/* bitwise and */
+	token_op_bor,				/* bitwise or */
+	token_op_bxor,				/* bitwise xor */
+	token_op_plus,				/* plus */
+	token_op_minus,				/* minus */
+	token_op_times,				/* times */
+	token_op_divide,			/* divide */
+	token_op_modulus,			/* modulus */
 	token_identifier,			/* an identifier (variable, function, etc. */
 	token_char,					/* single character; fallback */
 	token_uint,					/* unsigned integer up to 32 bits */
--- a/lwbasic/parser.c	Fri Feb 04 21:27:03 2011 -0700
+++ b/lwbasic/parser.c	Sat Feb 05 14:22:54 2011 -0700
@@ -66,6 +66,14 @@
 	return pt;
 }
 
+static int parse_expression(cstate *state)
+{
+	state -> expression = 1;
+	
+	state -> expression = 0;
+	return 1;
+}
+
 static void parse_decls(cstate *state)
 {
 	/* declarations */
@@ -122,6 +130,7 @@
 static void parse_statements(cstate *state)
 {
 	symtab_entry_t *se;
+	int et;
 	
 	for (;;)
 	{
@@ -141,10 +150,14 @@
 			if (!se)
 				lwb_error("Unknown variable %s\n", state -> lexer_token_string);
 			lexer(state);
+			/* ensure the first token of the expression will be parsed correctly */
+			state -> expression = 1;
 			expect(state, token_op_assignment);
 
 			/* parse the expression */
-			/* parse_expression(state); */
+			et = parse_expression(state);
+			
+			/* check type compatibility */
 			
 			/* actually do the assignment */