changeset 36:5325b640424d

First pass expression parsing
author Lost Wizard (lost@starbug3)
date Tue, 08 Feb 2011 22:42:12 -0700
parents cdb0175e1063
children a5d4693483af
files lwbasic/lexer.c lwbasic/lwbasic.h lwbasic/parser.c
diffstat 3 files changed, 129 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/lwbasic/lexer.c	Sat Feb 05 14:22:54 2011 -0700
+++ b/lwbasic/lexer.c	Tue Feb 08 22:42:12 2011 -0700
@@ -72,6 +72,8 @@
 	{ "bor", 			token_op_bor },
 	{ "bxor",			token_op_bxor },
 	{ "xor",			token_op_xor },
+	{ "not",			token_op_not },
+	{ "bnot",			token_op_bnot },
 	{ NULL }
 };
 
@@ -106,6 +108,10 @@
 	"<times>",
 	"<divide>",
 	"<modulus>",
+	"<openparen>",
+	"<closeparen>",
+	"<not>",
+	"<bitwisenot>",
 	"<identifier>",
 	"<char>",
 	"<uint>",
@@ -384,6 +390,13 @@
 			state -> lexer_token = token_op_modulus;
 			return;
 		
+		case '(':
+			state -> lexer_token = token_op_oparen;
+			return;
+		
+		case ')':
+			state -> lexer_token = token_op_cparen;
+			return;
 		
 		}
 	}
--- a/lwbasic/lwbasic.h	Sat Feb 05 14:22:54 2011 -0700
+++ b/lwbasic/lwbasic.h	Tue Feb 08 22:42:12 2011 -0700
@@ -104,6 +104,10 @@
 	token_op_times,				/* times */
 	token_op_divide,			/* divide */
 	token_op_modulus,			/* modulus */
+	token_op_oparen,			/* open paren */
+	token_op_cparen,			/* close paren */
+	token_op_not,				/* boolean not */
+	token_op_bnot,				/* bitwise not */
 	token_identifier,			/* an identifier (variable, function, etc. */
 	token_char,					/* single character; fallback */
 	token_uint,					/* unsigned integer up to 32 bits */
--- a/lwbasic/parser.c	Sat Feb 05 14:22:54 2011 -0700
+++ b/lwbasic/parser.c	Tue Feb 08 22:42:12 2011 -0700
@@ -66,10 +66,14 @@
 	return pt;
 }
 
+static void parse_expr(cstate *state, int prec);
+static void parse_term(cstate *state);
 static int parse_expression(cstate *state)
 {
 	state -> expression = 1;
 	
+	parse_expr(state, 0);
+	
 	state -> expression = 0;
 	return 1;
 }
@@ -355,3 +359,111 @@
 		}
 	}	
 }
+
+static void parse_expr(cstate *state, int prec)
+{
+	static const struct operinfo {
+		int opernum;
+		int operprec;
+	} operators[] =
+	{
+		{ token_op_plus, 100 },
+		{ token_op_minus, 100 },
+		{ token_op_times, 150 },
+		{ token_op_divide, 150 },
+		{ token_op_modulus, 150 },
+		{ token_op_and,	25 },
+		{ token_op_or, 20 },
+		{ token_op_xor, 20 },
+		{ token_op_band, 50 },
+		{ token_op_bor, 45 },
+		{ token_op_bxor, 45 },
+		{ -1, -1 }
+	};
+	int opern;
+	
+	parse_term(state);
+	
+eval_next:
+	for (opern = 0; operators[opern].opernum != -1; opern++)
+	{
+		if (operators[opern].opernum == state -> lexer_token)
+			break;
+	}
+	if (operators[opern].opernum == -1)
+		return;
+	
+	if (operators[opern].operprec <= prec)
+		return;
+	
+	lexer(state);
+	
+	parse_expr(state, operators[opern].operprec);
+	
+	/* push operator */
+	
+	goto eval_next;
+}
+
+static void parse_term(cstate *state)
+{
+eval_next:
+	/* parens */
+	if (state -> lexer_token == token_op_oparen)
+	{
+		lexer(state);
+		parse_expr(state, 0);
+		expect(state, token_op_cparen);
+		return;
+	}
+	
+	/* unary plus; ignore it */
+	if (state -> lexer_token == token_op_plus)
+	{
+		lexer(state);
+		goto eval_next;
+	}
+	
+	/* unary minus, precision 200 */
+	if (state -> lexer_token == token_op_minus)
+	{
+		lexer(state);
+		parse_expr(state, 200);
+		
+		/* push unary negation */
+	}
+	
+	/* BNOT, NOT */
+	if (state -> lexer_token == token_op_not || state -> lexer_token == token_op_bnot)
+	{
+		lexer(state);
+		parse_expr(state, 200);
+		
+		/* push unary operator */
+	}
+	
+	/* integer */
+	if (state -> lexer_token == token_int)
+	{
+	}
+	
+	/* unsigned integer */
+	if (state -> lexer_token == token_uint)
+	{
+	}
+	
+	/* variable or function call */
+	if (state -> lexer_token == token_identifier)
+	{
+		lexer(state);
+		if (state -> lexer_token == token_op_oparen)
+		{
+			/* function call */
+			return;
+		}
+		/* variable */
+		return;
+	}
+	
+	lwb_error("Invalid input in expression; got %s\n", lexer_return_token(state));
+}