%{ (***********************************************************************) (* *) (* TAToo *) (* *) (* Kim Nguyen, LRI UMR8623 *) (* Université Paris-Sud & CNRS *) (* *) (* Copyright 2010-2012 Université Paris-Sud and Centre National de la *) (* Recherche Scientifique. All rights reserved. This file is *) (* distributed under the terms of the GNU Lesser General Public *) (* License, with the special exception on linking described in file *) (* ../LICENSE. *) (* *) (***********************************************************************) (* Time-stamp: *) open Ast open Tree.Common %} %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 EQ NEQ LT GT LTE GTE OR AND ADD SUB DIV MOD %token NODE TEXT COMMENT %token COMMA %token EOF %left OR %left AND %left EQ NEQ %left LT GT LTE GTE %left ADD SUB %left MOD DIV STAR %nonassoc uminus %start xpath_query %type xpath_query %% xpath_query: path EOF { $1 } ; path: path_rev { List.rev $1 } ; path_rev: simple_path { [ $1 ] } | path_rev PIPE simple_path { $3 :: $1 } ; simple_path: absolute_path { Absolute (List.rev $1) } | relative_path { Relative (List.rev $1) } ; absolute_path: SLASH relative_path { $2 } | SLASHSLASH relative_path { $2 @ [(Descendant true, (node, NodeKind.Node), [])] } ; relative_path: 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 } ; axis_test: AXIS COLONCOLON test { let a, (t,k) = $1, $3 in let new_t = if a == Attribute && Utils.QNameSet.is_finite t then Utils.QNameSet.fold (fun t a -> Utils.QNameSet.add (Utils.QName.attribute t) a) t Utils.QNameSet.empty else t in (a, (new_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),NodeKind.Element) } | ATTNAME { (Attribute, (Utils.QNameSet.singleton (Utils.QName.of_string $1), NodeKind.Attribute)) } ; test: NODE { node, NodeKind.Node } | TEXT { text, NodeKind.Text } | STAR { star, NodeKind.Element } | COMMENT { Utils.QNameSet.singleton(Utils.QName.comment), NodeKind.Comment } | PI { Utils.QNameSet.singleton( Utils.QName.processing_instruction ( Utils.QName.of_string $1) ), NodeKind.ProcessingInstruction } | TAG { Utils.QNameSet.singleton(Utils.QName.of_string $1), NodeKind.Element } ; pred_list: pred_list_rev { List.rev $1 } ; pred_list_rev: { [] } | pred_list LB expr RB { $3 :: $1 } ; expr: INT { Number(`Int($1)) } | 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) } | LP expr RP { $2 } | path { Path $1 } ; arg_list: { [] } | arg_list1 { List.rev $1 } ; arg_list1: expr { [ $1 ] } | arg_list1 COMMA expr { $3 :: $1 } ;