X-Git-Url: http://git.nguyen.vg/gitweb/?p=tatoo.git;a=blobdiff_plain;f=src%2Fxpath%2Fxpath_internal_parser.mly;h=f0207ea25b1122e456607a02572f040989bd5ed1;hp=04ecf369521831159d72a8125c3e12a609edd959;hb=456aa2cae4ba3afc4fe364880e52f66490700650;hpb=30bc0bb1291426e5e26eb2dee1ffc41e4c246349 diff --git a/src/xpath/xpath_internal_parser.mly b/src/xpath/xpath_internal_parser.mly index 04ecf36..f0207ea 100644 --- a/src/xpath/xpath_internal_parser.mly +++ b/src/xpath/xpath_internal_parser.mly @@ -14,23 +14,21 @@ (* *) (***********************************************************************) -(* - Time-stamp: -*) - open Ast - let f () = () + open Tree %} %token TAG +%token PI +%token ATTNAME %token STRING %token INT %token FLOAT %token AXIS %token RB LB LP RP -%token SLASH SLASHSLASH COLONCOLON STAR PIPE +%token SLASH SLASHSLASH COLONCOLON STAR PIPE DOT DOTDOT %token EQ NEQ LT GT LTE GTE OR AND ADD SUB DIV MOD -%token NODE TEXT +%token NODE TEXT COMMENT %token COMMA %token EOF @@ -52,15 +50,9 @@ path EOF { $1 } ; path: - path_rev { List.rev $1 } -; - -path_rev: - simple_path { [ $1 ] } -| path_rev PIPE simple_path { $3 :: $1 } + separated_nonempty_list(PIPE, simple_path) { $1 } ; - simple_path: absolute_path { Absolute (List.rev $1) } | relative_path { Relative (List.rev $1) } @@ -68,37 +60,84 @@ simple_path: absolute_path: SLASH relative_path { $2 } -| SLASHSLASH relative_path { (DescendantOrSelf, node, []) :: $2 } +| SLASHSLASH relative_path { $2 @ + [(Descendant true, + (node, NodeKind.Node), + [])] } ; +/* + step is always a small list, of size 1-3 so @ is + cheap +*/ + relative_path: - step { [ $1 ] } -| relative_path SLASH step { $3 :: $1 } -| relative_path SLASHSLASH step { $3 - :: (DescendantOrSelf, node, []) - :: $1 } + step { $1 } +| relative_path SLASH step { $3 @ $1 } +| relative_path SLASHSLASH step { $3 @ + ((Descendant true, + (node, NodeKind.Node), + []) + :: $1) } ; step: - axis_test pred_list { let a, b = $1 in a, b, $2 } + DOT { [ (Self, (node, NodeKind.Node), []) ] } +| DOTDOT { [ (Parent, (node, NodeKind.Node), []) ] } +| axis_test pred_list { + match $1 with + (a,b) :: r -> (a,b,$2) :: (List.map (fun (a,b) -> (a,b,[])) r) + | [] -> assert false + } ; axis_test: - AXIS COLONCOLON test { $1, $3 } -| test { Child, $1 } + AXIS COLONCOLON test { let a, (t,k) = $1, $3 in + match a with + Attribute when QNameSet.is_finite t -> + [ a, ((QNameSet.fold + (fun t a -> + QNameSet.add + (QName.attribute t) a) + t QNameSet.empty), k) ] + | Preceding|Following -> + [ (Descendant true, (t,k)); + if a == Preceding then + (PrecedingSibling, (node, NodeKind.Node)) + else + (FollowingSibling, (node, NodeKind.Node)); + (Ancestor true, (node, NodeKind.Node)) ] + + | _ -> [ a, (t,k) ] + } +| test { [ Child, $1 ] } | AXIS { let _ = Format.flush_str_formatter () in let () = Format.fprintf Format.str_formatter "%a" Ast.print_axis $1 in let a = Format.flush_str_formatter () in - Child, Utils.QNameSet.singleton (Utils.QName.of_string a) + [Child, (QNameSet.singleton (QName.of_string a),NodeKind.Element)] } +| ATTNAME { [(Attribute, + (QNameSet.singleton (QName.of_string $1), + NodeKind.Attribute))] } ; test: - NODE { node } -| TEXT { text } -| STAR { star } -| TAG { Utils.QNameSet.singleton(Utils.QName.of_string $1) } + NODE { node, NodeKind.Node } +| TEXT { text, NodeKind.Text } +| STAR { node, NodeKind.Element } +| COMMENT { QNameSet.singleton(QName.comment), + NodeKind.Comment + } +| PI { (if $1 = "" then star + else QNameSet.singleton( + QName.processing_instruction ( + QName.of_string $1) + )), NodeKind.ProcessingInstruction + } +| TAG { QNameSet.singleton(QName.of_string $1), + NodeKind.Element + } ; pred_list: @@ -115,24 +154,27 @@ expr: | FLOAT { Number(`Float($1)) } | STRING { String $1 } | SUB expr %prec uminus { Unop(Neg, $2) } -| expr AND expr { Binop($1, And, $3) } -| expr OR expr { Binop($1, Or, $3) } -| expr ADD expr { Binop($1, Add, $3) } -| expr SUB expr { Binop($1, Sub, $3) } -| expr STAR expr { Binop($1, Mult, $3) } -| expr DIV expr { Binop($1, Div, $3) } -| expr MOD expr { Binop($1, Mod, $3) } -| expr EQ expr { Binop($1, Eq, $3) } -| expr NEQ expr { Binop($1, Neq, $3) } -| expr LT expr { Binop($1, Lt, $3) } -| expr LTE expr { Binop($1, Lte, $3) } -| expr GT expr { Binop($1, Gt, $3) } -| expr GTE expr { Binop($1, Gte, $3) } -| TAG LP arg_list RP { Fun_call(Utils.QName.of_string $1, $3) } +| e1 = expr; op = binop; e2 = expr { Binop(e1, op, e2) } +| TAG LP arg_list RP { Fun_call(QName.of_string $1, $3) } | LP expr RP { $2 } | path { Path $1 } ; +%inline binop: +| AND { And } +| OR { Or } +| ADD { Add } +| SUB { Sub } +| STAR { Mult } +| DIV { Div } +| MOD { Mod } +| EQ { Eq } +| NEQ { Neq } +| LT { Lt } +| LTE { Lte } +| GT { Gt } +| GTE { Gte } +; arg_list: { [] } | arg_list1 { List.rev $1 } @@ -142,4 +184,3 @@ arg_list1: expr { [ $1 ] } | arg_list1 COMMA expr { $3 :: $1 } ; -