[augeas-devel] [PATCH 2/3] Add match keyword

David Lutterkort lutter at redhat.com
Sat Feb 21 07:52:23 UTC 2009


---
 src/lexer.l  |    4 +++-
 src/parser.y |   37 +++++++++++++++++++++++++++++++++----
 src/syntax.h |   26 +++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/src/lexer.l b/src/lexer.l
index 1fbe62a..77a556f 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -95,7 +95,7 @@ ARROW  ->
                return REGEXP;
   }
 
-  [|*?+()=:;\.\[\]{}-]    return yytext[0];
+  [|*?+()=:;\.\[\]{}_-]    return yytext[0];
 
   module        return KW_MODULE;
   let           return KW_LET;
@@ -104,6 +104,8 @@ ARROW  ->
   lens          return KW_LENS;
   in            return KW_IN;
   autoload      return KW_AUTOLOAD;
+  match         return KW_MATCH;
+  with          return KW_WITH;
 
   /* tests */
   test          return KW_TEST;
diff --git a/src/parser.y b/src/parser.y
index 9230a29..5705a3a 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -51,6 +51,8 @@ typedef struct info YYLTYPE;
 %parse-param    {yyscan_t scanner}
 %lex-param      {yyscan_t scanner}
 
+%expect 0
+
 %token <string> DQUOTED   /* "foo" */
 %token <string> REGEXP    /* /[ \t]+/ */
 %token <string> LIDENT UIDENT QIDENT
@@ -63,6 +65,7 @@ typedef struct info YYLTYPE;
 %token          KW_STRING
 %token          KW_REGEXP
 %token          KW_LENS
+%token          KW_MATCH KW_WITH
 %token          KW_TEST KW_GET KW_PUT KW_AFTER
 
 %union {
@@ -77,10 +80,12 @@ typedef struct info YYLTYPE;
 
 %type<term>   start decls
 %type<term>   exp composeexp unionexp minusexp catexp appexp rexp aexp
+%type<term>   branch branchlist matchexp
 %type<term>   param param_list
 %type<string> qid id autoload
 %type<type>  type atype
 %type<quant> rep
+%type<term>  str
 %type<term>  test_exp
 %type<intval> test_special_res
 %type<tree>  tree_const tree_const2 tree_branch
@@ -189,7 +194,28 @@ exp: KW_LET LIDENT param_list '=' exp KW_IN  exp
        LOC_MERGE(@1, @1, @6);
        $$ = make_let($2, $3, $5, $7, &@1);
      }
-   | composeexp
+   | matchexp
+
+/* Case expression */
+matchexp: KW_MATCH composeexp KW_WITH branchlist
+          { $$ = make_binop(A_MATCH, $2, $4, &@$); }
+        | composeexp
+
+branchlist: branchlist '|' branch
+            { $$ = $1; list_append($$, $3); }
+          | '|' branch
+            { $$ = $2; }
+
+branch: str ARROW minusexp
+        {
+          LOC_MERGE(@1, @1, @3);
+          $$ = make_binop(A_BRANCH, $1, $3, &@1);
+        }
+      | '_' ARROW minusexp
+        {
+          LOC_MERGE(@1, @1, @3);
+          $$ = make_binop(A_BRANCH, NULL, $3, &@1);
+        }
 
 composeexp: composeexp ';' unionexp
      { $$ = make_binop(A_COMPOSE, $1, $3, &@$); }
@@ -220,8 +246,7 @@ appexp: appexp rexp
 
 aexp: qid
       { $$ = make_ident($1, &@1); }
-    | DQUOTED
-      { $$ = make_value_term(V_STRING, $1, &@1); }
+    | str
     | REGEXP
       { $$ = make_value_term(V_REGEXP, $1, &@1); }
     | '(' exp ')'
@@ -229,6 +254,9 @@ aexp: qid
     | '[' exp ']'
       { $$ = make_unop(A_BRACKET, $2, &@$); }
 
+str: DQUOTED
+     { $$ = make_value_term(V_STRING, $1, &@1); }
+
 rexp: aexp rep
       { $$ = make_rep($1, $2, &@$); }
     | aexp
@@ -403,7 +431,8 @@ static struct term *make_binop(enum term_tag tag,
                               struct term *left, struct term *right,
                               struct info *locp) {
   assert(tag == A_COMPOSE || tag == A_CONCAT
-         || tag == A_UNION || tag == A_APP || tag == A_MINUS);
+         || tag == A_UNION || tag == A_APP || tag == A_MINUS
+         || tag == A_MATCH || tag == A_BRANCH);
   struct term *term = make_term_locp(tag, locp);
   term->left = left;
   term->right = right;
diff --git a/src/syntax.h b/src/syntax.h
index 208c4db..9c4bf7d 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -57,6 +57,8 @@ enum term_tag {
     A_MODULE,
     A_BIND,              /* Module scope binding of a name */
     A_LET,               /* local LET .. IN binding */
+    A_MATCH,
+    A_BRANCH,
     A_COMPOSE,
     A_UNION,
     A_MINUS,
@@ -98,7 +100,29 @@ struct term {
             char          *bname;
             struct term   *exp;
         };
-        struct {              /* A_COMPOSE, A_UNION, A_CONCAT, A_APP, A_LET */
+        /*
+         * Many things get stored as binary operators.
+         * A_COMPOSE, A_UNION, and A_CONCAT:
+         *   left and right are the operands, arbitrary expressions
+         * A_APP
+         *   'func arg' application of func to arg
+         *   left -> func, right -> arg
+         * A_LET
+         *   'let ident params = body in exp'
+         *   is desugared by the parser into
+         *   '(lambda ident: body) (lambda params: exp)'
+         *   i.e. function application of two anonymous forms
+         *   left -> (lambda ident: body), right -> (lambda params: exp)
+         * A_MATCH: left -> exp, right -> branches
+         *   'match exp with branches'
+         *   left -> exp, right -> branches
+         *   branches is a list of terms which are all A_BRANCH
+         * A_BRANCH: left -> pat, right -> expr
+         *   '| pat -> expr'
+         *   left -> pat, right -> expr
+         *   pat will be NULL for the wildcard '_'
+         */
+        struct {
             struct term *left;
             struct term *right;
         };
-- 
1.6.0.6




More information about the augeas-devel mailing list