[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