#include "cerise.h"
#include <stdarg.h>
-//#define TRACE
+#define TRACE
#ifdef TRACE
-static int Indent = 0;
-#define parse_enter() \
- (printf("%*c-> %s\n", ++Indent * 2, ' ', __func__))
-#define parse_exit() \
- Indent--
-// (printf("%*c<- %s\n", --Indent * 2, ' ', __func__))
+ static int Indent = 0;
+ #define RULE(name) \
+ void name##_actual(Parser* p); \
+ void name(Parser* p) { \
+ printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \
+ name##_actual(p); \
+ Indent--; } \
+ void name##_actual(Parser* p)
#else
-#define parse_enter()
-#define parse_exit()
+ #define RULE(name) \
+ void name(Parser* p)
#endif
/* Precedence Table
return (peek(p)->type == type);
}
-//static bool matches_oneof(Parser* p, TokType types[])
-//{
-// for (int i = 0; types[i] != NONE; i++)
-// {
-// if (matches(p, types[i]))
-// {
-// return true;
-// }
-// }
-// return false;
-//}
+static bool matches_oneof(Parser* p, TokType types[])
+{
+ for (int i = 0; types[i] != NONE; i++)
+ {
+ if (matches(p, types[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
static bool accept(Parser* p, TokType type)
{
/* Grammar Definition
*****************************************************************************/
void module(Parser* p);
-static void import_list(Parser* p);
-static void declaration_seq(Parser* p);
-static void statement_seq(Parser* p);
-static void const_decl(Parser* p);
-
-static void expression(Parser* p);
-static void simple_expr(Parser* p);
-static void term(Parser* p);
-static void factor(Parser* p);
-
-//static int RelationOps[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
-//static int AddOps[] = { '+', '-', OR, 0 };
-//static int MulOps[] = { '*', '/', AND, 0 };
-
-void module(Parser* p)
+void import_list(Parser* p);
+void declaration_seq(Parser* p);
+void statement_seq(Parser* p);
+void const_decl(Parser* p);
+void expression(Parser* p);
+void simple_expr(Parser* p);
+void term(Parser* p);
+void factor(Parser* p);
+void designator(Parser* p);
+void qualident(Parser* p);
+void expr_list(Parser* p);
+
+RULE(module)
{
- parse_enter();
expect(p, MODULE);
char* sname = expect_text(p, IDENT);
/* TODO: Check that it matches filename here */
error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
}
expect(p, ';');
- parse_exit();
}
-static void import_list(Parser* p)
+RULE(import_list)
{
- parse_enter();
expect(p, IMPORT);
while (1)
{
expect(p, ',');
}
expect(p, ';');
- parse_exit();
}
-static void declaration_seq(Parser* p)
+RULE(declaration_seq)
{
if (accept(p, CONST))
{
}
}
-static void statement_seq(Parser* p)
+RULE(statement_seq)
{
(void)p;
}
-static void const_decl(Parser* p)
+RULE(const_decl)
{
while (1)
{
(void)p;
}
-static void expression(Parser* p)
+RULE(expression)
{
+ // expression = SimpleExpression [relation SimpleExpression].
+ // relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
+
+ int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
simple_expr(p);
-// int operators[] = {EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0};
-// simple_expr(p);
-// if (matches_oneof(p, operators))
-// {
-// consume(p);
-// simple_expr(p);
-// }
-
-// expression = SimpleExpression [relation SimpleExpression].
-// relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
-// SimpleExpression = ["+" | "-"] term {AddOperator term}.
+ if (matches_oneof(p, ops))
+ {
+ consume(p);
+ simple_expr(p);
+ }
}
-/*
-
-expression = SimpleExpression [relation SimpleExpression].
- relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
-
-SimpleExpression = ["+" | "-"] term {AddOperator term}.
- AddOperator = "+" | "-" | "or".
-
-term = factor {MulOperator factor}.
- MulOperator = "*" | "/" | "div" | "mod" | "and".
-
-factor = number | string | "nil" | "true" | "false" | designator [ActualParameters] | "(" expression ")" | "not" factor.
-designator [ActualParameters]
-designator = qualident {selector}.
- selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
-ExpList = expression {"," expression}.
-ActualParameters = "(" [ExpList] ")" .
-
-*/
+RULE(simple_expr)
+{
+ // SimpleExpression = ["+" | "-"] term {AddOperator term}.
+ // AddOperator = "+" | "-" | "or".
+ /* first term and +/- */
+ if (matches_oneof(p, (int[]){'+', '-', 0}))
+ {
+ consume(p); // OP
+ term(p);
+ }
+ else
+ {
+ term(p);
+ }
-static void simple_expr(Parser* p)
-{
-// if (matches_oneof(p, (int[]){ '+', '-', 0 }))
-// {
-// consume(p);
-//// term(p);
-// }
- term(p);
+ /* optional second term and op */
+ while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
+ {
+ consume(p);
+ term(p);
+ }
}
-static void term(Parser* p)
+RULE(term)
{
+ // term = factor {MulOperator factor}.
+ // MulOperator = "*" | "/" | "and".
factor(p);
+ while (matches_oneof(p, (int[]){'*', '/', AND, 0}))
+ {
+ consume(p);
+ factor(p);
+ }
}
-// designator [ActualParameters]
-// designator = qualident {selector}.
-// selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
-// ExpList = expression {"," expression}.
-// ActualParameters = "(" [ExpList] ")" .
+/*
+factor = number
+ | string
+ | "nil"
+ | "true"
+ | "false"
+ | designator [ActualParameters]
+ | "(" expression ")"
+ | "not" factor.
+*/
-static void factor(Parser* p)
+RULE(factor)
{
switch ((int)peek(p)->type)
{
factor(p);
break;
- default:
- error(p, "not a valid literal/expression");
+ case IDENT:
+ designator(p);
+// actual_params(p);
+ break;
+ }
+}
+
+/*
+ designator = qualident {selector}.
+ selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
+ ExpList = expression {"," expression}.
+ qualident = [ident "."] ident.
+
+ ActualParameters = "(" [ExpList] ")" .
+*/
+RULE(designator)
+{
+ qualident(p);
+ /* selector */
+ switch ((int)peek(p)->type)
+ {
+ case '.':
+ expect(p, IDENT);
+ break;
+
+ case '[':
+ expr_list(p);
+ expect(p, ']');
+ break;
+
+ case '^':
+ expect(p, '^');
+ break;
+
+ case '(':
+ qualident(p);
+ expect(p, ')');
break;
}
}
+RULE(qualident)
+{
+ expect(p, IDENT);
+ if (accept(p, '.'))
+ {
+ expect(p, IDENT);
+ }
+}
+
+RULE(expr_list)
+{
+ while (1)
+ {
+ expression(p);
+ if (!accept(p, ','))
+ {
+ break;
+ }
+ }
+}
+
/* Grammar Unit Tests
*****************************************************************************/
#ifdef CERISE_TESTS
"FOO = not true");
parse_rule(const_decl,
"FOO = (not true)");
+ parse_rule(const_decl,
+ "FOO = +1");
+ parse_rule(const_decl,
+ "FOO = -1");
+ parse_rule(const_decl,
+ "FOO = 1 + 1");
+ parse_rule(const_decl,
+ "FOO = 1 + 2 * 4");
}
}
#endif