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 accept(Parser* p, TokType type)
{
if (matches(p, type)) {
return strdup(expect_val(p, type)->text);
}
-//static int consume(Parser* p) {
-// int type = peek(p)->type;
-// if (!accept(p, type))
-// error(p, "Unexpected token");
-// return type;
-//}
+static int consume(Parser* p)
+{
+ int type = peek(p)->type;
+ if (!accept(p, type))
+ {
+ error(p, "Unexpected token");
+ }
+ return 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)
+{
+ parse_enter();
+ expect(p, MODULE);
+ char* sname = expect_text(p, IDENT);
+ /* TODO: Check that it matches filename here */
+ expect(p, ';');
+ if (matches(p, IMPORT))
+ {
+ import_list(p);
+ }
+ declaration_seq(p);
+ if (accept(p, BEGIN))
+ {
+ statement_seq(p);
+ }
+ expect(p, END);
+ char* ename = expect_text(p, IDENT);
+ if (strcmp(sname, ename))
+ {
+ error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+ }
+ expect(p, ';');
+ parse_exit();
+}
static void import_list(Parser* p)
{
static void declaration_seq(Parser* p)
{
- (void)p;
+ if (accept(p, CONST))
+ {
+ const_decl(p);
+ expect(p, ';');
+ }
+ if (accept(p, TYPE))
+ {
+// type_decl(p);
+ expect(p, ';');
+ }
+ if (accept(p, VAR))
+ {
+// var_decl(p);
+ expect(p, ';');
+ }
}
static void statement_seq(Parser* p)
(void)p;
}
-void module(Parser* p)
+static void const_decl(Parser* p)
{
- parse_enter();
- expect(p, MODULE);
- char* sname = expect_text(p, IDENT);
- /* TODO: Check that it matches filename here */
- expect(p, ';');
- if (matches(p, IMPORT))
- {
- import_list(p);
- }
- declaration_seq(p);
- if (accept(p, BEGIN))
+ while (1)
{
- statement_seq(p);
+ /*char* name =*/ expect_text(p, IDENT);
+ expect(p, '=');
+ expression(p);
+ if (!accept(p, ','))
+ {
+ break;
+ }
}
- expect(p, END);
- char* ename = expect_text(p, IDENT);
- if (strcmp(sname, ename))
+ (void)p;
+}
+
+static void expression(Parser* p)
+{
+ 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}.
+}
+
+/*
+
+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] ")" .
+
+*/
+
+
+static void simple_expr(Parser* p)
+{
+// if (matches_oneof(p, (int[]){ '+', '-', 0 }))
+// {
+// consume(p);
+//// term(p);
+// }
+ term(p);
+}
+
+static void term(Parser* p)
+{
+ factor(p);
+}
+
+// designator [ActualParameters]
+// designator = qualident {selector}.
+// selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
+// ExpList = expression {"," expression}.
+// ActualParameters = "(" [ExpList] ")" .
+
+static void factor(Parser* p)
+{
+ switch ((int)peek(p)->type)
{
- error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+ case INT:
+ case REAL:
+ case STRING:
+ case NIL:
+ case BOOL:
+ consume(p);
+ break;
+
+ case '(':
+ expect(p, '(');
+ expression(p);
+ expect(p, ')');
+ break;
+
+ case NOT:
+ consume(p);
+ factor(p);
+ break;
+
+ default:
+ error(p, "not a valid literal/expression");
+ break;
}
- expect(p, ';');
- parse_exit();
}
/* Grammar Unit Tests
parse_rule(import_list,
"import A, B = ModB, C;");
}
+
+ TEST(Should parse constant declarations)
+ {
+ parse_rule(const_decl,
+ "FOO = 123");
+ parse_rule(const_decl,
+ "FOO = 123.123");
+ parse_rule(const_decl,
+ "FOO = \"\"");
+ parse_rule(const_decl,
+ "FOO = true");
+ parse_rule(const_decl,
+ "FOO = false");
+ parse_rule(const_decl,
+ "FOO = nil");
+ parse_rule(const_decl,
+ "FOO = not true");
+ parse_rule(const_decl,
+ "FOO = (not true)");
+ }
}
#endif