Browse Source

ncd: Implement caret syntax sugar.

Ambroz Bizjak 11 years ago
parent
commit
3a1e5a4fb8

+ 3 - 0
examples/ncd_tokenizer_test.c

@@ -123,6 +123,9 @@ static int tokenizer_output (void *user, int token, char *value, size_t value_le
         case NCD_TOKEN_BLOCK:
             printf("block\n");
             break;
+        case NCD_TOKEN_CARET:
+            printf("caret\n");
+            break;
         default:
             printf("UNKNOWN_TOKEN\n");
             break;

File diff suppressed because it is too large
+ 577 - 492
generated/NCDConfigParser_parse.c


+ 3 - 2
generated/NCDConfigParser_parse.h

@@ -20,5 +20,6 @@
 #define BRACKET_OPEN                   20
 #define BRACKET_CLOSE                  21
 #define AT_SIGN                        22
-#define PROCESS                        23
-#define TEMPLATE                       24
+#define CARET                          23
+#define PROCESS                        24
+#define TEMPLATE                       25

File diff suppressed because it is too large
+ 407 - 350
generated/NCDConfigParser_parse.out


+ 66 - 1
generated/NCDConfigParser_parse.y

@@ -104,8 +104,9 @@ static void free_value (struct value o) { if (o.have) NCDValue_Free(&o.v); }
 %type value  { struct value }
 %type name_maybe { char * }
 %type process_or_template { int }
+%type name_list { struct value }
 
-// mention parser_out in some destructor to a void unused variable warning
+// mention parser_out in some destructor to avoid an unused-variable warning
 %destructor processes { (void)parser_out; free_program($$); }
 %destructor statement { free_statement($$); }
 %destructor elif_maybe { free_ifblock($$); }
@@ -121,6 +122,7 @@ static void free_value (struct value o) { if (o.have) NCDValue_Free(&o.v); }
 %destructor invoc { free_value($$); }
 %destructor value { free_value($$); }
 %destructor name_maybe { free($$); }
+%destructor name_list { free_value($$); }
 
 %stack_size 0
 
@@ -553,6 +555,65 @@ doneJ:
     free(N);
 }
 
+name_list(R) ::= NAME(A). {
+    if (!A.str) {
+        goto failK0;
+    }
+
+    NCDValue_InitList(&R.v);
+    
+    NCDValue this_string;
+    if (!NCDValue_InitString(&this_string, A.str)) {
+        goto failK1;
+    }
+    
+    if (!NCDValue_ListPrepend(&R.v, this_string)) {
+        goto failK2;
+    }
+
+    R.have = 1;
+    goto doneK;
+
+failK2:
+    NCDValue_Free(&this_string);
+failK1:
+    NCDValue_Free(&R.v);
+failK0:
+    R.have = 0;
+    parser_out->out_of_memory = 1;
+doneK:
+    free_token(A);
+}
+
+name_list(R) ::= NAME(A) DOT name_list(N). {
+    if (!A.str || !N.have) {
+        goto failKA0;
+    }
+    
+    NCDValue this_string;
+    if (!NCDValue_InitString(&this_string, A.str)) {
+        goto failKA0;
+    }
+
+    if (!NCDValue_ListPrepend(&N.v, this_string)) {
+        goto failKA1;
+    }
+
+    R.have = 1;
+    R.v = N.v;
+    N.have = 0;
+    goto doneKA;
+
+failKA1:
+    NCDValue_Free(&this_string);
+failKA0:
+    R.have = 0;
+    parser_out->out_of_memory = 1;
+doneKA:
+    free_token(A);
+    free_value(N);
+}
+
 statement_args_maybe(R) ::= . {
     R.have = 1;
     NCDValue_InitList(&R.v);
@@ -742,6 +803,10 @@ doneUA0:
     free(A);
 }
 
+value(R) ::= CARET name_list(A). {
+    R = A;
+}
+
 value(R) ::= dotted_name(A). {
     if (!A) {
         goto failV0;

+ 4 - 0
ncd/NCDConfigParser.c

@@ -166,6 +166,10 @@ static int tokenizer_output (void *user, int token, char *value, size_t value_le
             Parse(state->parser, BLOCK, minor, &state->out);
         } break;
         
+        case NCD_TOKEN_CARET: {
+            Parse(state->parser, CARET, minor, &state->out);
+        } break;
+        
         default:
             BLog(BLOG_ERROR, "line %zu, character %zu: invalid token", line, line_char);
             free(minor.str);

+ 66 - 1
ncd/NCDConfigParser_parse.y

@@ -104,8 +104,9 @@ static void free_value (struct value o) { if (o.have) NCDValue_Free(&o.v); }
 %type value  { struct value }
 %type name_maybe { char * }
 %type process_or_template { int }
+%type name_list { struct value }
 
-// mention parser_out in some destructor to a void unused variable warning
+// mention parser_out in some destructor to avoid an unused-variable warning
 %destructor processes { (void)parser_out; free_program($$); }
 %destructor statement { free_statement($$); }
 %destructor elif_maybe { free_ifblock($$); }
@@ -121,6 +122,7 @@ static void free_value (struct value o) { if (o.have) NCDValue_Free(&o.v); }
 %destructor invoc { free_value($$); }
 %destructor value { free_value($$); }
 %destructor name_maybe { free($$); }
+%destructor name_list { free_value($$); }
 
 %stack_size 0
 
@@ -553,6 +555,65 @@ doneJ:
     free(N);
 }
 
+name_list(R) ::= NAME(A). {
+    if (!A.str) {
+        goto failK0;
+    }
+
+    NCDValue_InitList(&R.v);
+    
+    NCDValue this_string;
+    if (!NCDValue_InitString(&this_string, A.str)) {
+        goto failK1;
+    }
+    
+    if (!NCDValue_ListPrepend(&R.v, this_string)) {
+        goto failK2;
+    }
+
+    R.have = 1;
+    goto doneK;
+
+failK2:
+    NCDValue_Free(&this_string);
+failK1:
+    NCDValue_Free(&R.v);
+failK0:
+    R.have = 0;
+    parser_out->out_of_memory = 1;
+doneK:
+    free_token(A);
+}
+
+name_list(R) ::= NAME(A) DOT name_list(N). {
+    if (!A.str || !N.have) {
+        goto failKA0;
+    }
+    
+    NCDValue this_string;
+    if (!NCDValue_InitString(&this_string, A.str)) {
+        goto failKA0;
+    }
+
+    if (!NCDValue_ListPrepend(&N.v, this_string)) {
+        goto failKA1;
+    }
+
+    R.have = 1;
+    R.v = N.v;
+    N.have = 0;
+    goto doneKA;
+
+failKA1:
+    NCDValue_Free(&this_string);
+failKA0:
+    R.have = 0;
+    parser_out->out_of_memory = 1;
+doneKA:
+    free_token(A);
+    free_value(N);
+}
+
 statement_args_maybe(R) ::= . {
     R.have = 1;
     NCDValue_InitList(&R.v);
@@ -742,6 +803,10 @@ doneUA0:
     free(A);
 }
 
+value(R) ::= CARET name_list(A). {
+    R = A;
+}
+
 value(R) ::= dotted_name(A). {
     if (!A) {
         goto failV0;

+ 3 - 0
ncd/NCDConfigTokenizer.c

@@ -117,6 +117,9 @@ void NCDConfigTokenizer_Tokenize (MemRef the_str, NCDConfigTokenizer_output outp
         else if (l = data_begins_with(str, left, "@")) {
             token = NCD_TOKEN_AT;
         }
+        else if (l = data_begins_with(str, left, "^")) {
+            token = NCD_TOKEN_CARET;
+        }
         else if (l = data_begins_with(str, left, "->")) {
             token = NCD_TOKEN_ARROW;
         }

+ 1 - 0
ncd/NCDConfigTokenizer.h

@@ -60,6 +60,7 @@
 #define NCD_TOKEN_INCLUDE_GUARD 22
 #define NCD_TOKEN_AT 23
 #define NCD_TOKEN_BLOCK 24
+#define NCD_TOKEN_CARET 25
 
 typedef int (*NCDConfigTokenizer_output) (void *user, int token, char *value, size_t value_len, size_t line, size_t line_char);
 

+ 9 - 0
ncd/tests/caret.ncd

@@ -0,0 +1,9 @@
+process main {
+    var(^foo) x;
+    assert(@val_equal(x, {"foo"}));
+
+    var(^foo.bar.ba09.z) x;
+    assert(@val_equal(x, {"foo", "bar", "ba09", "z"}));
+
+    exit("0");
+}

Some files were not shown because too many files changed in this diff