%token_type {const char *} %default_type {struct XpathExprAst*} %extra_argument {struct XpathBuilder*build} %name Xpath2Parse %token_prefix XP2_ // Use precedence to enforce the rule that // "/*-5" should be parsed as "(/*) - 5", // or that "or or or" is equal to "(children::or) or (children::or)" %left OR AND INSTANCE CASTABLE CAST AS STAR DIVS COMPARISONNM UNIONNM. %left SLASH. start(S) ::= expr(L). { S = L; } expr(R) ::= exprSingle(S). { R = S; } expr(R) ::= expr(L) COMMA exprSingle(S). { R = L->add_item(S); } exprSingle(R) ::= forExpr(F). { R = F; } exprSingle(R) ::= quantifiedExpr(Q). { R = Q; } exprSingle(R) ::= ifExpr(I). { R = I; } exprSingle(R) ::= orExpr(O). { R = O; } forExpr(R) ::= TODO1. { R = null; } quantifiedExpr(R) ::= TODO2. { R = null; } ifExpr(R) ::= TODO3. { R = null; } orExpr(R) ::= andExpr(A). { R = A; } orExpr(R) ::= orExpr(O) OR andExpr(A). { R = build->or_node(O,A); } andExpr(R) ::= comparisonExpr(C). { R = C; } andExpr(R) ::= andExpr(A) AND comparisonExpr(C). { R = build->and_node(A,C); } comparisonExpr(R) ::= rangeExpr(E). { R = E; } comparisonExpr(R) ::= rangeExpr(EL) COMPARISONOP(OP) rangeExpr(ER). { R = build->oper(OP,EL,ER); } comparisonExpr(R) ::= rangeExpr(EL) COMPARISONNM(OP) rangeExpr(ER). { R = build->oper(OP,EL,ER); } rangeExpr(R) ::= additiveExpr(A). { R = A; } rangeExpr(R) ::= additiveExpr(A) TO(OP) additiveExpr(B). { R = build->oper(OP,A,B); } additiveExpr(R) ::= multiplicativeExpr(M). { R = M; } additiveExpr(R) ::= additiveExpr(LEFT) ADDOP(OP) multiplicativeExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } multiplicativeExpr(R) ::= unionExpr(U). { R = U; } multiplicativeExpr(R) ::= multiplicativeExpr(LEFT) STAR(OP) unionExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } multiplicativeExpr(R) ::= multiplicativeExpr(LEFT) DIVS(OP) unionExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } unionExpr(R) ::= intersectExceptExpr(U). { R = U; } unionExpr(R) ::= unionExpr(LEFT) UNIONOP(OP) intersectExceptExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } unionExpr(R) ::= unionExpr(LEFT) UNIONNM(OP) intersectExceptExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } intersectExceptExpr(R) ::= instanceOfExpr(U). { R = U; } intersectExceptExpr(R) ::= intersectExceptExpr(LEFT) INTER(OP) instanceOfExpr(RIGHT). { R = build->oper(OP,LEFT,RIGHT); } instanceOfExpr(R) ::= treatExpr(U). { R = U; } instanceOfExpr(R) ::= treatExpr(U) INSTANCE OF sequenceType(TYPE). { R = build->instance_of(U,TYPE); } treatExpr(R) ::= castableExpr(C). { R = C; } treatExpr(R) ::= castableExpr(C) AS(OP) sequenceType(TYPE). { R = build->oper(OP,C,TYPE); } castableExpr(R) ::= castExpr(C). { R = C; } castableExpr(R) ::= castExpr(C) CASTABLE AS singleType(TYPE). { R = build->castable_as(C,TYPE); } castExpr(R) ::= unaryExpr(C). { R = C; } castExpr(R) ::= unaryExpr(C) CAST AS singleType(TYPE). { R = build->cast_as(C,TYPE); } unaryExpr(R) ::= valueExpr(V). { R = V; } unaryExpr(R) ::= ADDOP(OP) unaryExpr(V). { R = build->unary_oper(OP,V); } valueExpr(R) ::= pathExpr(P). { R = P; } pathExpr(R) ::= SLASH. { R = build->root_node(); } pathExpr(R) ::= SLASH relativePathExpr(REL). { R = build->apply_to(build->root_node(), REL); } pathExpr(R) ::= DOUBLESLASH relativePathExpr(REL). { R = build->double_slash(build->root_node(), REL); } pathExpr(R) ::= relativePathExpr(REL). { R = REL; } relativePathExpr(R) ::= stepExpr(S). { R = S; } relativePathExpr(R) ::= relativePathExpr(LEFT) SLASH stepExpr(RIGHT). { R = build->apply_to(LEFT, RIGHT); } relativePathExpr(R) ::= relativePathExpr(LEFT) DOUBLESLASH stepExpr(RIGHT). { R = build->double_slash(LEFT, RIGHT); } stepExpr(R) ::= filterExpr(E). { R = E; } stepExpr(R) ::= axisStep(E). { R = E; } axisStep(R) ::= reverseStep(STEP) predicateList(PRED). { R = build->predicate(STEP,PRED); } axisStep(R) ::= forwardStep(STEP) predicateList(PRED). { R = build->predicate(STEP,PRED); } forwardStep(R) ::= FORWARDAXIS(A) COLONCOLON nodeTest(T). { R = build->apply_to_axis(A,T); } forwardStep(R) ::= abbrevForwardStep(A). { R = A; } abbrevForwardStep(R) ::= AT nodeTest(T). { R = build->make_attr_test(T); } abbrevForwardStep(R) ::= nodeTest(T). { R = build->apply_to_axis("child", T); } reverseStep(R) ::= REVERSEAXIS(A) COLONCOLON nodeTest(T). { R = build->apply_to_axis(A,T); } reverseStep(R) ::= abbrevReverseStep(A). { R = A; } abbrevReverseStep(R) ::= DOTDOT. { R = build->apply_to_axis("parent", build->true()); } nodeTest(R) ::= kindTest(K). { R = K; } nodeTest(R) ::= nameTest(K). { R = K; } nameTest ::= qname(Q). { R = build->name_test(QN_ALLBITS, Q); } nameTest ::= wildCard(W). { R = W; } wildCard(R) ::= STAR. { R = build->wildcard(NULL); } wildCard(R) ::= PARTIALWILDCARD(N). { R = build->wildcard(N); } filterExpr(R) ::= primaryExpr(P). { R = P; } filterExpr(R) ::= primaryExpr(P) predicateList(PRED). { R = build->predicate(P,PRED); } predicateList(R) ::= predicate(P). { R = P; } predicateList(R) ::= predicateList(L) predicate(P). { R = L->add_item(P); } predicate(R) ::= OPENBRACE expr(E) CLOSEBRACE. { R = E; } primaryExpr(R) ::= literal(L). { R = L; } primaryExpr(R) ::= varRef(V). { R = V; } primaryExpr(R) ::= parenthesizedExpr(V). { R = V; } primaryExpr(R) ::= contextItemExpr(V). { R = V; } primaryExpr(R) ::= functionCall(V). { R = V; } literal(R) ::= numericLiteral(L). { R = L; } literal(R) ::= STRINGLITERAL(L). { R = build->string_literal(L); } numericLiteral(R) ::= INTEGERLITERAL(L). { R = build->integer_literal(L); } numericLiteral(R) ::= DECIMALLITERAL(L). { R = build->decimal_literal(L); } numericLiteral(R) ::= DOUBLELITERAL(L). { R = build->double_literal(L); } varRef(R) ::= DOLLAR qname(N). { R = build->variable_reference(N); } parenthesizedExpr(R) ::= OPENPAREN CLOSEPAREN. { R = build->empty_tuple(); } parenthesizedExpr(R) ::= OPENPAREN expr(E) CLOSEPAREN. { R = E; } contextItemExpr(R) ::= DOT. { R = build->context_item(); } functionCall(R) ::= funcQname(N) argsList(L). { R = build->function_call(N,L); } /* Our own invention. Not in the spec. */ argsList(R) ::= OPENPAREN CLOSEPAREN. { R = NULL; } argsList(R) ::= OPENPAREN expr(E) CLOSEPAREN. { R = E; } singleType(R) ::= atomicType(T). { R = T; } singleType(R) ::= atomicType(T) QUESTIONMARK. { R = T; /* TODO: typing */} sequenceType(R) ::= EMPTYSEQUENCE OPENPAREN CLOSEPAREN. { R = NULL; /* TODO: typing */ } sequenceType(R) ::= itemType(T). { R = T; } sequenceType(R) ::= itemType OCCURRENCEINDICATOR. { R = NULL; /* TODO: typing */ } itemType(R) ::= kindTest(K). { R = K; } itemType(R) ::= ITEM OPENPAREN CLOSEPAREN. { R = NULL; /* TODO: tests and shit */ } itemType(R) ::= atomicType(T). { R = T; } atomicType(R) ::= qname. { R = NULL; /* TODO: tests and shit */ } kindTest(R) ::= documentTest(T). kindTest(R) ::= elementTest(T). kindTest(R) ::= attributeTest(T). kindTest(R) ::= schemaElementTest(T). kindTest(R) ::= schemaAttributeTest(T). kindTest(R) ::= piTest(T). kindTest(R) ::= commentTest(T). kindTest(R) ::= textTest(T). kindTest(R) ::= anyKindTest(T). anyKindTest(R) ::= NODE OPENPAREN CLOSEPAREN. { R = build->true(); } documentTest(R) ::= DOCUMENT_NODE OPENPAREN elementTest CLOSEPAREN. { R = NULL; /* TODO: documentTest */ } documentTest(R) ::= DOCUMENT_NODE OPENPAREN schemaElementTest CLOSEPAREN. { R = NULL; /* TODO: documentTest */ } textTest(R) ::= TEXT OPENPAREN CLOSEPAREN. { R = build->name_test(QN_ALLBITS, QN_TEXTNODE); } commentTest(R) ::= COMMENT OPENPAREN CLOSEPAREN. { R = build->name_test(QN_ALLBITS, QN_COMMENTNODE); } piTest(R) ::= PROCESSING_INSTRUCTION OPENPAREN CLOSEPAREN. { R = build->name_test(QN_URIBITS, NS_PINODE); } piTest(R) ::= PROCESSING_INSTRUCTION OPENPAREN NCNAME(N) CLOSEPAREN. { Qcode lcode = build->local_code(N); R = build->name_test(QN_URIBITS, QN_MAKE(NS_PINODE,lcode)); } piTest(R) ::= PROCESSING_INSTRUCTION OPENPAREN STRINGLITERAL(N) CLOSEPAREN. { Qcode lcode = build->local_code(N); R = build->name_test(QN_URIBITS, QN_MAKE(NS_PINODE,lcode)); } attributeTest(R) ::= ATTRIBUTE OPENPAREN CLOSEPAREN. { R = NULL; /* attribute tests */ } attributeTest(R) ::= ATTRIBUTE OPENPAREN attribNameOrWildcard CLOSEPAREN. { R = NULL; /* attribute tests */ } attributeTest(R) ::= ATTRIBUTE OPENPAREN attribNameOrWildcard COMMA typeName CLOSEPAREN. { R = NULL; /* attribute tests */ } attribNameOrWildcard(R) ::= qname(Q). { R = build->name_test(QN_ALLBITS, Q); } attribNameOrWildcard(R) ::= STAR. { R = build->name_test(0, 0); /* TODO: match all attributes? */ } schemaAttributeTest(R) ::= SCHEMA_ATTRIBUTE OPENPAREN qname CLOSEPAREN. { R = NULL; /* schema attribute tests */ } elementTest(R) ::= ELEMENT OPENPAREN CLOSEPAREN. { R = NULL; /* schema attribute tests */ } elementTest(R) ::= ELEMENT OPENPAREN elementNameOrWildcard CLOSEPAREN. { R = NULL; /* schema attribute tests */ } elementTest(R) ::= ELEMENT OPENPAREN elementNameOrWildcard COMMA typeName CLOSEPAREN. { R = NULL; /* schema attribute tests */ } elementTest(R) ::= ELEMENT OPENPAREN elementNameOrWildcard COMMA typeName QUESTIONMARK CLOSEPAREN. { R = NULL; /* schema attribute tests */ } elementNameOrWildcard ::= qname(Q). { R = build->name_test(QN_ALLBITS, Q); } elementNameOrWildcard ::= STAR. { R = NULL; /* TODO: match all elements? */ } schemaElementTest ::= SCHEMA_ELEMENT OPENPAREN qname CLOSEPAREN. { R = NULL; /* schema element tests */ } typeName(R) ::= qname. { R = NULL; /* TODO: typeName tests? */ } // "qname" production represents any valid qname; this may also be // the name of an operator. See also funcQname, which are the set of // qnames valid to be used as a function. %type qname {const char*} qname(R) ::= funcQname(Q). { R = Q; } qname(R) ::= ATTRIBUTE(Q). { R = Q; } qname(R) ::= COMMENT(Q). { R = Q; } qname(R) ::= DOCUMENT_NODE(Q). { R = Q; } qname(R) ::= ELEMENT(Q). { R = Q; } qname(R) ::= EMPTY_SEQUENCE(Q). { R = Q; } qname(R) ::= IF(Q). { R = Q; } qname(R) ::= ITEM(Q). { R = Q; } qname(R) ::= NODE(Q). { R = Q; } qname(R) ::= PROCESSING_INSTRUCTION(Q). { R = Q; } qname(R) ::= SCHEMA_ATTRIBUTE(Q). { R = Q; } qname(R) ::= SCHEMA_ELEMENT(Q). { R = Q; } qname(R) ::= TEXT(Q). { R = Q; } qname(R) ::= TYPESWITCH(Q). { R = Q; } // funcQname is the set of qnames which can be the name of an invoked // function. See section A3., Reserved Function Names, for more information. %type funcQname {const char*} funcQname(R) ::= UNKNOWNIDENTIFIER(Q). { R = Q; } funcQname(R) ::= AND(Q). { R = Q; } funcQname(R) ::= OR(Q). { R = Q; } funcQname(R) ::= INSTANCE(Q). { R = Q; } funcQname(R) ::= CASTABLE(Q). { R = Q; } funcQname(R) ::= CAST(Q). { R = Q; } funcQname(R) ::= AS(Q). { R = Q; } funcQname(R) ::= OF(Q). { R = Q; } funcQname(R) ::= FOR(Q). { R = Q; } funcQname(R) ::= REVERSEAXIS(Q). { R = Q; } funcQname(R) ::= FORWARDAXIS(Q). { R = Q; } funcQname(R) ::= DIVS(Q). { R = Q; } funcQname(R) ::= COMPARISONNM(Q). { R = Q; } funcQname(R) ::= UNIONNM(Q). { R = Q; } %include { #include "qname.hpp" }