ソースを参照

some work on Context.parseSingleExpr

Dan Korostelev 8 年 前
コミット
acab19c99f
3 ファイル変更39 行追加2 行削除
  1. 12 0
      src/macro/macroApi.ml
  2. 21 0
      src/macro/macroContext.ml
  3. 6 2
      std/haxe/macro/Context.hx

+ 12 - 0
src/macro/macroApi.ml

@@ -19,6 +19,7 @@ type 'value compiler_api = {
 	after_generate : (unit -> unit) -> unit;
 	on_type_not_found : (string -> 'value) -> unit;
 	parse_string : string -> Globals.pos -> bool -> Ast.expr;
+	parse_single_expr : string -> Globals.pos -> Ast.expr * string;
 	type_expr : Ast.expr -> Type.texpr;
 	resolve_type  : Ast.complex_type -> Globals.pos -> t;
 	type_macro_expr : Ast.expr -> Type.texpr;
@@ -121,6 +122,7 @@ type obj_type =
 	| OTypedExprDef_catches
 	| OJSGenApi
 	| OContext_getPosInfos
+	| OContext_parseSingleExpr
 	| OCompiler_getDisplayPos
 	| ORef
 (* ---- ^^^^^ please exactly match the name of the typedef or use TypeName_field if it's a anonymous *)
@@ -252,6 +254,7 @@ let proto_name = function
 	| OTypedExprDef_catches -> "TypedExprDef", Some "catches"
 	| OJSGenApi -> "JSGenApi", None
 	| OContext_getPosInfos -> "Context", Some "getPosInfos"
+	| OContext_parseSingleExpr -> "Context", Some "parseSingleExpr"
 	| OCompiler_getDisplayPos -> "Compiler", Some "getDisplayPos"
 	| ORef -> "Ref", None
 
@@ -1546,6 +1549,15 @@ let macro_api ccom get_api =
 			if s = "" then raise Invalid_expr;
 			encode_expr ((get_api()).parse_string s (decode_pos p) (decode_bool b))
 		);
+		"parse_single_expr", vfun2 (fun s p ->
+			let s = decode_string s in
+			let p = decode_pos p in
+			let expr, rest = (get_api()).parse_single_expr s p in
+			encode_obj OContext_parseSingleExpr [
+				"expr", encode_expr expr;
+				"rest", encode_string rest;
+			]
+		);
 		"make_expr", vfun2 (fun v p ->
 			encode_expr (value_to_expr v (decode_pos p))
 		);

+ 21 - 0
src/macro/macroContext.ml

@@ -183,6 +183,27 @@ let make_macro_api ctx p =
 			];
 		);
 		MacroApi.parse_string = parse_expr_string;
+		MacroApi.parse_single_expr = (fun s p ->
+			let err () = Interp.exc_string "Invalid expression" in
+			if s = "" then err();
+			let tokens = Sedlexing.Utf8.from_string s in
+			let str = Stream.from (fun _ ->
+				try
+					Some (Lexer.token tokens)
+				with Lexer.Error (Lexer.Invalid_character _,_) ->
+					None
+			) in
+			let expr = try Parser.expr str with Stream.Error _ -> err() in
+			let rec loop e =
+				let e = Ast.map_expr loop e in
+				let ep = pos e in
+				fst e, {p with pmin = p.pmin + ep.pmin; pmax = p.pmin + ep.pmax}
+			in
+			let expr = loop expr in
+			let pos = Sedlexing.lexeme_start tokens in
+			let rest = String.sub s pos (String.length s - pos) in
+			expr,rest
+		);
 		MacroApi.type_expr = (fun e ->
 			typing_timer ctx true (fun() -> type_expr ctx e Value)
 		);

+ 6 - 2
std/haxe/macro/Context.hx

@@ -280,6 +280,10 @@ class Context {
 		return load("do_parse", 3)(expr, pos, true);
 	}
 
+	public static function parseSingleExpr( expr : String, pos : Position ) : { expr: Expr, rest: String } {
+		return load("parse_single_expr", 2)(expr, pos);
+	}
+
 	/**
 		Builds an expression from `v`.
 
@@ -517,8 +521,8 @@ class Context {
 	}
 
 	/**
-		Types expression `e`, stores the resulting typed expression internally and 
-		returns a syntax-level expression that can be returned from a macro and 
+		Types expression `e`, stores the resulting typed expression internally and
+		returns a syntax-level expression that can be returned from a macro and
 		will be replaced by the stored typed expression.
 
 		If `e` is null or invalid, an exception is thrown.