Merge pull request #4 from jeremyroman/master
[mspang/inapt.git] / parser.rl
index 8882472..e0dde39 100644 (file)
--- a/parser.rl
+++ b/parser.rl
@@ -65,7 +65,7 @@ using namespace std;
             block_stack.push_back(tmp_block);
             fcall main;
         } else {
-            fatal("%s: %d: Syntax Error: Nesting Too Deep at '}'", curfile, curline);
+            fatal("%s: %d: Syntax Error: Nesting Too Deep at '{'", curfile, curline);
         }
     }
 
@@ -79,7 +79,7 @@ using namespace std;
 
     action start_conditional {
         inapt_conditional *cond = new inapt_conditional;
-        cond->condition = xstrndup(ts, p - ts); ts = 0;
+        cond->predicates.swap(predicates);
         conditional_stack.push_back(cond);
     }
 
@@ -110,19 +110,18 @@ using namespace std;
     newline = '\n' @newline;
     comment = '#' (any - '\n')* newline;
     whitespace = [\t\v\f\r ] | comment | newline;
-    profile = alpha (alpha | digit | '-' | '+' | '.')*;
+    profile = alpha (alpha | digit | '-' | '_' | '+' | '.')*;
     package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >strstart;
-    predicate = '@' ('!'? profile) >strstart %predicate whitespace+;
+    predicate = '@' ('!'? profile ('/' '!'? profile)*) >strstart %predicate whitespace+;
     package_alternates = package_name >strstart %add_alternate ('/' package_name >strstart %add_alternate)*;
     package_list = ((whitespace+ predicate* package_alternates)+ %add_package whitespace*);
     profile_list = (whitespace+ profile >strstart %profile)* whitespace*;
     cmd_install = ('install' @start_install package_list ';');
     cmd_remove = ('remove' @start_remove package_list ';');
     cmd_profiles = ('profiles' profile_list ';' @add_profiles);
-    start_block = '{' @start_block;
     end_block = '}' @end_block;
-    cmd_if = 'if' whitespace+ profile >strstart %start_conditional whitespace* start_block whitespace*
-             ('else' whitespace* start_block whitespace* ';' @full_conditional | ';' @half_conditional);
+    cmd_if = 'if' whitespace+ predicate+ '{' @start_conditional @start_block whitespace*
+             ('else' whitespace* '{' @start_block whitespace* ';' @full_conditional | ';' @half_conditional);
     cmd = whitespace* (predicate* (cmd_install | cmd_remove | cmd_profiles) | cmd_if);
     cmd_list = cmd* whitespace* end_block?;
     main := cmd_list;
@@ -130,7 +129,7 @@ using namespace std;
 
 %% write data;
 
-void badsyntax(const char *filename, int lineno, char badchar, const char *message) {
+static void badsyntax(const char *filename, int lineno, char badchar, const char *message) {
     if (!message) {
         if (badchar == '\n')
             message = "Unexpected newline";
@@ -180,7 +179,7 @@ void parser(const char *filename, inapt_block *top_block)
     %% write init;
 
     while (!done) {
-        char *p = buf + have, *pe, *eof = 0;
+        char *p = buf + have, *pe;
         int len, space = BUFSIZE - have;
 
         if (!space)
@@ -192,7 +191,6 @@ void parser(const char *filename, inapt_block *top_block)
         pe = p + len;
 
         if (!len) {
-            eof = pe;
             done = 1;
         }
 
@@ -211,7 +209,7 @@ void parser(const char *filename, inapt_block *top_block)
     }
 
     if (cs < inapt_first_final)
-        badsyntax(curfile, curline, 0, "Unexpected EOF");
+        badsyntax(curfile, curline, 0, "Unexpected EOF (forgot semicolon?)");
 
     if (top)
         badsyntax(curfile, curline, 0, "Unclosed block at EOF");