浏览代码

added expression-level metadata support to the parser (fixed issue #1208 (again))

Simon Krajewski 12 年之前
父节点
当前提交
bf7163df19
共有 2 个文件被更改,包括 34 次插入5 次删除
  1. 13 4
      parser.ml
  2. 21 1
      tests/unit/TestMeta.hx

+ 13 - 4
parser.ml

@@ -358,11 +358,16 @@ and parse_common_flags = parser
 	| [< '(Kwd Extern,_); l = parse_common_flags >] -> (HExtern, EExtern) :: l
 	| [< '(Kwd Extern,_); l = parse_common_flags >] -> (HExtern, EExtern) :: l
 	| [< >] -> []
 	| [< >] -> []
 
 
+and parse_meta_params pname s = match s with parser
+	| [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma expr; '(PClose,_); >] -> params
+	| [< >] -> []
+
+and parse_meta_entry = parser
+	[< '(At,_); name,p = meta_name; params = parse_meta_params p; s >] -> (name,params,p)
+
 and parse_meta = parser
 and parse_meta = parser
-	| [< '(At,_); name,p = meta_name; s >] ->
-		(match s with parser
-		| [< '(POpen,_); params = psep Comma expr; '(PClose,_); s >] -> (name,params,p) :: parse_meta s
-		| [< >] -> (name,[],p) :: parse_meta s)
+	| [< entry = parse_meta_entry; s >] ->
+		entry :: parse_meta s
 	| [< >] -> []
 	| [< >] -> []
 
 
 and meta_name = parser
 and meta_name = parser
@@ -670,6 +675,8 @@ and inline_function = parser
 	| [< '(Kwd Function,p1) >] -> false, p1
 	| [< '(Kwd Function,p1) >] -> false, p1
 
 
 and expr = parser
 and expr = parser
+	| [< (name,params,p) = parse_meta_entry; s >] ->
+		(EMeta((name,params,p), expr s),p)
 	| [< '(BrOpen,p1); b = block1; '(BrClose,p2); s >] ->
 	| [< '(BrOpen,p1); b = block1; '(BrClose,p2); s >] ->
 		let e = (b,punion p1 p2) in
 		let e = (b,punion p1 p2) in
 		(match b with
 		(match b with
@@ -790,6 +797,8 @@ and expr = parser
 	| [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s
 	| [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s
 
 
 and expr_next e1 = parser
 and expr_next e1 = parser
+	| [< (name,params,p) = parse_meta_entry; s >] ->
+		(EMeta((name,params,p), expr_next e1 s),p)
 	| [< '(Dot,p); s >] ->
 	| [< '(Dot,p); s >] ->
 		if is_resuming p then display (EDisplay (e1,false),p);
 		if is_resuming p then display (EDisplay (e1,false),p);
 		(match s with parser
 		(match s with parser

+ 21 - 1
tests/unit/TestMeta.hx

@@ -54,6 +54,26 @@ package unit;
 		eq( c.k, null );
 		eq( c.k, null );
 	}
 	}
 
 
+	public function testExprMeta() {
+		eq(getMeta(@foo a).name, "foo");
+		eq(getMeta(@foo("a") b).name, "foo");
+		eq(getMeta(@foo ("a")).name, "foo");
+		
+		var m = getMeta(@bar("1", "foo") null);
+		eq(m.name, "bar");
+		eq(m.args[0], "1");
+		eq(m.args[1], "foo");
+		
+		eq(getMeta(@foo ("1")).args.length, 0);
+		eq(getMeta(@foo("1") "2").args.length, 1);
+	}
 
 
-
+	@:macro static function getMeta(e) {
+		switch(e.expr) {
+			case haxe.macro.Expr.ExprDef.EMeta(m, e):
+				return macro { name: $(m.name), args: $[m.params] };
+			default:
+				return macro report("Metadata expected");
+		}
+	}
 }
 }