Remove the new machine
authorMichael Spang <mspang@csclub.uwaterloo.ca>
Wed, 9 Dec 2009 04:34:43 +0000 (23:34 -0500)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Tue, 22 Dec 2009 03:11:47 +0000 (22:11 -0500)
Instead of using a separate machine we can keep track of the depth of
nesting and raise an error if we try to close the outermost block.

Signed-off-by: Michael Spang <mspang@csclub.uwaterloo.ca>
parser.rl
util.h

index 2b26a7f..1f8081b 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -10,7 +10,7 @@
 
 using namespace std;
 
-#define xstrndup strndup
+#define MAXDEPTH 3
 
 %%{
     machine inapt;
@@ -39,15 +39,23 @@ using namespace std;
     }
 
     action misc_error {
-        fprintf(stderr, "%s: %d: Syntax Error\n", curfile, curline);
+        fatal("%s: %d: Syntax Error\n", curfile, curline);
     }
 
     action start_block {
-        fcall block_machine;
+        if (depth++ < MAXDEPTH) {
+            fcall main;
+        } else {
+            fatal("%s: %d: Syntax Error: Nesting Too Deep at '}'", curfile, curline);
+        }
     }
 
     action end_block {
-        fret;
+        if (depth--) {
+            fret;
+        } else {
+            fatal("%s: %d: Syntax Error: Unexpected '}'", curfile, curline);
+        }
     }
 
     newline = '\n' %newline;
@@ -58,10 +66,10 @@ using namespace std;
     cmd_install = ('install' @install package_list ';');
     cmd_remove = ('remove' @remove package_list ';');
     simple_cmd = cmd_install | cmd_remove;
-    block = '{' @start_block;
-    cmd_if = 'if' whitespace+ alpha+ whitespace* block whitespace* ('else' whitespace* block)?;
-    cmd_list = (simple_cmd | cmd_if)*;
-    block_machine := (cmd_list '}' @end_block) $err(misc_error);
+    start_block = '{' @start_block;
+    end_block = '}' @end_block;
+    cmd_if = 'if' whitespace+ alpha+ whitespace* start_block whitespace* ('else' whitespace* start_block)?;
+    cmd_list = (simple_cmd | cmd_if | whitespace)* end_block?;
     main := cmd_list $err(misc_error);
 }%%
 
@@ -78,8 +86,9 @@ void parser(const char *filename, inapt_context *top_context)
     int curline = 1;
     char *ts = 0, *te = 0;
     inapt_context *cur_context = top_context;
-    int stack[100];
+    int stack[MAXDEPTH];
     int top = 0; /* TODO: resize */
+    int depth = 0;
 
     const char *curfile = filename;
     enum inapt_action::action_t curaction = inapt_action::UNSET;
diff --git a/util.h b/util.h
index 78bb3d3..ba0d15c 100644 (file)
--- a/util.h
+++ b/util.h
@@ -64,4 +64,13 @@ static inline char *xstrdup(const char *s) {
     return dup;
 }
 
+static inline char *xstrndup(const char *s, size_t n) {
+    char *dup = strndup(s, n);
+
+    if (dup == NULL)
+        fatal("out of memory");
+
+    return dup;
+}
+
 #endif