PageRenderTime 85ms CodeModel.GetById 40ms app.highlight 6ms RepoModel.GetById 34ms app.codeStats 0ms

/parser.y

http://github.com/fizx/parsley
Happy | 631 lines | 560 code | 71 blank | 0 comment | 0 complexity | ab793a8be436f7468091ecda3d0df141 MD5 | raw file
  1%{
  2#include <math.h>
  3#include <stdio.h>
  4#include <stdlib.h>
  5#include <string.h>
  6#include "parsed_xpath.h"
  7#include <libxml/hash.h>
  8
  9#ifndef PARSER_Y_H_INCLUDED
 10#define PARSER_Y_H_INCLUDED
 11
 12static pxpathPtr parsed_answer;
 13
 14int yylex (void);
 15void yyerror (char const *);
 16
 17void prepare_parse(char*);
 18void cleanup_parse(void);
 19void start_debugging(void);
 20
 21static xmlHashTablePtr alias_hash;
 22
 23char* xpath_alias(char*);
 24void init_xpath_alias();
 25
 26int yyparse(void);
 27pxpathPtr myparse(char*);
 28void answer(pxpathPtr);
 29
 30#define LIT_BIN_OP(A, B, C)           pxpath_cat_literals(3, A, LIT(B), C)
 31#define BIN_OP(A, B, C)               pxpath_cat_paths(3, A, OP(B), C)
 32#define PREP_OP(A, B)                 pxpath_cat_paths(2, OP(A), B)
 33#define PXP(A)                        pxpath_new_path(1, A)
 34#define LIT(A)                        pxpath_new_literal(1, A)
 35#define OP(A)   	                    pxpath_new_operator(1, A)
 36#define APPEND(A, S)                  pxpath_cat_paths(2, A, PXP(S)); 
 37#define PREPEND(A, S)                 pxpath_cat_paths(2, PXP(S), A); 
 38#define PXPWRAP(A, B, C)              pxpath_cat_paths(3, PXP(A), B, PXP(C))
 39#define P4E(A, B, C, D)               pxpath_cat_paths(4, A, PXP(B), C, PXP(D))
 40#define P4O(A, B, C, D)               pxpath_cat_paths(4, PXP(A), B, PXP(C), D)
 41#define P6E(A, B, C, D, E, F)         pxpath_cat_paths(6, A, PXP(B), C, PXP(D), E, PXP(F));
 42#define INPUT_TYPE(A, S)              APPEND(A, "[lower-case(name())='input' and lower-case(@type)='" #S "']")
 43#define TRACE(A, B)                   fprintf(stderr, "trace(%s): ", A); fprintf(stderr, "%s\n", pxpath_to_string(B));
 44
 45#endif
 46  
 47%}
 48
 49%glr-parser
 50%token_table
 51%debug
 52
 53%union {
 54  int empty;
 55	char* string;
 56  pxpathPtr node;
 57}
 58
 59%token <string> NUMBER
 60%token <string> S
 61%token <string> AT
 62%token <string> LPAREN
 63%token <string> RPAREN
 64%token <string> PIPE
 65%token <string> LT
 66%token <string> SLASH
 67%token <string> DBLSLASH
 68%token <string> BANG
 69%token <string> COLON
 70%token <string> DBLCOLON
 71%token <string> QUERY
 72%token <string> HASH
 73%token <string> COMMA
 74%token <string> DOT
 75%token <string> DBLDOT
 76%token <string> GT
 77%token <string> LBRA
 78%token <string> RBRA
 79%token <string> TILDE
 80%token <string> SPLAT
 81%token <string> PLUS
 82%token <string> DASH
 83%token <string> EQ
 84%token <string> LTE
 85%token <string> GTE
 86%token <string> DOLLAR
 87%token <string> BSLASHLIT
 88%token <string> OTHER
 89%token <string> XANCESTOR
 90%token <string> XANCESTORSELF
 91%token <string> XATTR
 92%token <string> XCHILD
 93%token <string> XDESC
 94%token <string> XDESCSELF
 95%token <string> XFOLLOW
 96%token <string> XFOLLOWSIB
 97%token <string> XNS
 98%token <string> XPARENT
 99%token <string> XPRE
100%token <string> XPRESIB
101%token <string> XSELF
102%token <string> XOR
103%token <string> XAND
104%token <string> XDIV
105%token <string> XMOD
106%token <string> XCOMMENT
107%token <string> XTEXT 
108%token <string> XPI		
109%token <string> XNODE	
110%token <string> CXEQUATION
111%token <string> CXOPHE
112%token <string> CXOPNE
113%token <string> CXOPSTARTEQ
114%token <string> CXOPENDEQ
115%token <string> CXOPCONTAINS
116%token <string> CXOPCONTAINS2
117%token <string> CXFIRST
118%token <string> CXLAST
119%token <string> CXNOT
120%token <string> CXEVEN
121%token <string> CXODD
122%token <string> CXEQ
123%token <string> CXGT
124%token <string> CXLT
125%token <string> CXCONTENT
126%token <string> CXHEADER
127%token <string> CXCONTAINS
128%token <string> CXEMPTY
129%token <string> CXHAS
130%token <string> CXPARENT
131%token <string> CXNTHCH
132%token <string> CXNTHLASTCH
133%token <string> CXNTHTYPE
134%token <string> CXNTHLASTTYPE
135%token <string> CXFIRSTCH
136%token <string> CXLASTCH
137%token <string> CXFIRSTTYPE
138%token <string> CXLASTTYPE
139%token <string> CXONLYCH
140%token <string> CXONLYTYPE
141%token <string> CXINPUT
142%token <string> CXTEXT
143%token <string> CXPASSWORD
144%token <string> CXRADIO
145%token <string> CXCHECKBOX
146%token <string> CXSUBMIT
147%token <string> CXIMAGE
148%token <string> CXRESET
149%token <string> CXBUTTON
150%token <string> CXFILE
151%token <string> CXENABLED
152%token <string> CXDISABLED
153%token <string> CXCHECKED
154%token <string> CXSELECTED
155%token <string> NAME
156%token <string> STRING
157%type <node> Root
158%type <empty> OptS
159%type <node> LocationPath
160%type <node> AbsoluteLocationPath
161%type <node> RelativeLocationPath
162%type <node> Step
163%type <node> AxisSpecifier
164%type <string> AxisName
165%type <node> NodeTest
166%type <node> Predicates
167%type <node> Predicate
168%type <node> PredicateExpr
169%type <node> AbbreviatedAbsoluteLocationPath
170%type <node> AbbreviatedRelativeLocationPath
171%type <string> AbbreviatedStep
172%type <string> AbbreviatedAxisSpecifier
173%type <node> Expr
174%type <node> NumberLike
175%type <node> PrimaryExpr
176%type <node> FunctionCall
177%type <node> Arguments
178%type <node> ArgumentSet
179%type <node> PrefixedName
180%type <node> Argument
181%type <node> UnionExpr
182%type <node> PathExpr
183%type <node> FunctionName
184%type <node> FilterExpr
185%type <node> OrExpr
186%type <node> AndExpr
187%type <node> EqualityExpr
188%type <node> RelationalExpr
189%type <node> AdditiveExpr
190%type <node> MultiplicativeExpr
191%type <node> UnaryExpr
192%type <string> Literal
193%type <node> Number
194%type <node> simple_selector_anchor
195%type <string> MultiplyOperator
196%type <node> VariableReference
197%type <node> NameTest
198%type <string> NodeType
199%type <string> UnprefixedName
200%type <string> combinator
201%type <node> possibly_empty_sequence
202%type <string> keyword
203%type <node> StringLike
204%type <node> selectors_group
205%type <node> QName
206%type <string> NCName
207%type <string> Prefix
208%type <string> LocalPart
209%type <node> attribute_extended_selector
210%type <node> Ident
211%type <node> universal
212%type <node> selector
213%type <node> namespace_prefix
214%type <node> type_selector
215%type <node> element_name
216%type <node> simple_selector_sequence
217%%
218
219Root
220  :	Expr OptS		{ answer($1); }
221	;
222
223LocationPath
224  : RelativeLocationPath  %dprec 1
225	| AbsoluteLocationPath  %dprec 2
226	| selectors_group				%dprec 3
227	;
228	
229AbsoluteLocationPath
230  : SLASH RelativeLocationPath				{ $$ = PREP_OP($1, $2); }
231	| SLASH                             { $$ = PXP($1); }
232	| AbbreviatedAbsoluteLocationPath
233	;
234	
235RelativeLocationPath
236  : Step 
237  | RelativeLocationPath SLASH Step		{ $$ = BIN_OP($1, $2, $3); }
238	| AbbreviatedRelativeLocationPath
239	;
240	
241Step
242  : AxisSpecifier NodeTest						{ $$ = pxpath_cat_paths(2, $1, $2); }
243	| AxisSpecifier NodeTest Predicates  { $$ = pxpath_cat_paths(3, $1, $2, $3); }
244	| AbbreviatedStep                   { $$ = PXP($1); }
245	;
246	
247AxisSpecifier
248  : AxisName DBLCOLON									{ $$ = pxpath_new_path(2, $1, $2); } 
249	| AbbreviatedAxisSpecifier          { $$ = PXP($1); }
250	;
251AxisName
252	: XANCESTOR 		
253	| XANCESTORSELF	
254	| XATTR					
255	| XCHILD				
256	| XDESC					
257	| XDESCSELF			
258	| XFOLLOW				
259	| XFOLLOWSIB		
260	| XNS						
261	| XPARENT				
262	| XPRE					
263	| XPRESIB				
264	| XSELF					
265	;
266	
267NodeTest
268  : NameTest 
269	| NodeType LPAREN RPAREN						 { $$ = pxpath_new_path(3, $1, $2, $3); }
270	| XPI LPAREN Literal RPAREN					 { $$ = pxpath_new_path(4, $1, $2, $3, $4); }
271	;
272	
273Predicates
274  : Predicates Predicate               { $$ = pxpath_cat_paths(2, $1, $2); }
275  | Predicate
276	;
277	
278Predicate
279  : LBRA PredicateExpr RBRA						 { $$ = PXPWRAP($1, $2, $3); }
280	;
281	
282PredicateExpr
283  : Expr
284	;
285	
286AbbreviatedAbsoluteLocationPath
287  : DBLSLASH RelativeLocationPath			{ $$ = PREP_OP($1, $2); }
288	;
289	
290AbbreviatedRelativeLocationPath
291  : RelativeLocationPath DBLSLASH Step	{ $$ = BIN_OP($1, $2, $3); }
292	;
293	
294AbbreviatedStep
295  : DOT
296 	| DBLDOT
297	;
298	
299AbbreviatedAxisSpecifier
300  : AT
301	|				{ $$ = ""; }
302	;
303Expr
304  : LPAREN Argument RPAREN %dprec 2  { $$ = PXPWRAP($1, $2, $3);    }  
305  | OrExpr						 %dprec 1
306	;
307PrimaryExpr
308  : VariableReference 
309	| LPAREN Expr RPAREN 				 	{ $$ = PXPWRAP($1, $2, $3);     }  
310  | Literal                     { $$ = LIT($1);  }
311  | Number 
312	| FunctionCall
313	;
314	
315FunctionCall
316  : FunctionName LPAREN Arguments RPAREN		{ $$ = pxpath_new_func(xpath_alias(pxpath_to_string($1)), $3); }
317	;
318Arguments
319	: ArgumentSet
320	|										{ $$ = NULL; }
321	;
322ArgumentSet
323  :	Argument COMMA ArgumentSet	 	  %dprec 2		{ $$ = $1; $1->next = $3; }
324	| Argument												%dprec 1
325	;
326Argument
327  : OptS Expr OptS		{ $$ = $2; }
328	;
329UnionExpr
330  : PathExpr 
331	| UnionExpr PIPE PathExpr							{ $$ = BIN_OP($1, $2, $3); }
332	;
333	
334PathExpr
335  : LocationPath 
336	| FilterExpr                                    
337	| FilterExpr SLASH RelativeLocationPath					{ $$ = BIN_OP($1, $2, $3); }
338	| FilterExpr DBLSLASH RelativeLocationPath			{ $$ = BIN_OP($1, $2, $3); }
339	;
340	
341FilterExpr
342  : PrimaryExpr 
343	| FilterExpr Predicates				{ $$ = pxpath_cat_paths(2, $1, $2); }
344	;
345	
346OrExpr
347  : AndExpr 
348	| OrExpr XOR AndExpr						{ $$ = LIT_BIN_OP($1, $2, $3); }
349	;
350	
351AndExpr
352  : EqualityExpr 
353	| AndExpr XAND EqualityExpr			{ $$ = LIT_BIN_OP($1, $2, $3); }
354	;
355	
356EqualityExpr
357  : RelationalExpr 
358	| EqualityExpr EQ RelationalExpr				{ $$ = LIT_BIN_OP($1, $2, $3); }
359	| EqualityExpr CXOPNE RelationalExpr		{ $$ = LIT_BIN_OP($1, $2, $3); }	
360	;
361	
362RelationalExpr
363  : AdditiveExpr                               %dprec 2
364  | RelationalExpr OptS LT OptS AdditiveExpr   %dprec 3     { $$ = LIT_BIN_OP($1, $3, $5); }
365  | RelationalExpr OptS GT OptS AdditiveExpr   %dprec 1     { $$ = LIT_BIN_OP($1, $3, $5); }
366  | RelationalExpr OptS LTE OptS AdditiveExpr  %dprec 3     { $$ = LIT_BIN_OP($1, $3, $5); }
367  | RelationalExpr OptS GTE OptS AdditiveExpr  %dprec 3     { $$ = LIT_BIN_OP($1, $3, $5); }
368	;
369
370AdditiveExpr
371  : MultiplicativeExpr                             %dprec 3
372	| AdditiveExpr OptS PLUS OptS MultiplicativeExpr %dprec 1 	{ $$ = LIT_BIN_OP($1, $3, $5); }
373	| AdditiveExpr OptS DASH OptS MultiplicativeExpr %dprec 2 	{ $$ = LIT_BIN_OP($1, $3, $5); }
374	;
375
376MultiplicativeExpr
377  : UnaryExpr                                                %dprec 2
378  | MultiplicativeExpr OptS MultiplyOperator OptS UnaryExpr	 %dprec 2 { $$ = LIT_BIN_OP($1, $3, $5); }
379  | MultiplicativeExpr OptS XDIV OptS UnaryExpr              %dprec 1 { $$ = LIT_BIN_OP($1, $3, $5); }
380  | MultiplicativeExpr OptS XMOD OptS UnaryExpr              %dprec 2 { $$ = LIT_BIN_OP($1, $3, $5); }
381	;
382
383UnaryExpr
384  : UnionExpr 
385	| DASH UnaryExpr		{ $$ = PREP_OP($1, $2); }
386	;
387	
388Literal
389  : STRING
390	;
391Number
392  : NUMBER                { $$ = LIT($1); }
393	| NUMBER DOT						{ $$ = pxpath_new_literal(2, $1, $2); }
394	| NUMBER DOT NUMBER			{ $$ = pxpath_new_literal(3, $1, $2, $3); }
395	| DOT NUMBER						{ $$ = pxpath_new_literal(2, $1, $2); }
396	;
397	
398MultiplyOperator
399  : SPLAT
400	;
401	
402VariableReference
403  : DOLLAR QName				{	$$ = PREP_OP($1, $2); }
404	;
405	
406NameTest
407  : SPLAT               { $$ = PXP($1); }
408	| NCName COLON SPLAT 	{ $$ = pxpath_new_path(3, $1, $2, $3); }
409	| QName
410	;
411	
412NodeType
413  : XCOMMENT 
414	| XTEXT 
415	| XPI 
416	| XNODE
417	;
418	
419FunctionName
420  : QName
421	;
422
423QName
424  : PrefixedName
425	| UnprefixedName      { $$ = PXP($1); }
426	;
427
428PrefixedName
429	: Prefix COLON LocalPart  { $$ = pxpath_new_path(3, $1, $2, $3); }
430	;
431	
432UnprefixedName
433	: LocalPart
434	;
435
436Prefix
437	: NCName
438	;
439
440LocalPart
441	: NCName
442	;
443
444NCName
445	: NAME
446	| keyword
447	;
448
449selectors_group
450	: attribute_extended_selector COMMA OptS selectors_group		{ $$ = pxpath_cat_paths(4, pxpath_new_literal(1, ".//"), $1, pxpath_new_literal(1, "|"), $4); }
451	| attribute_extended_selector 	{ $$ = pxpath_cat_paths(2, pxpath_new_literal(1, ".//"), $1); }
452  ;
453
454attribute_extended_selector
455	: selector
456	| selector S AT NAME	{ $$ = pxpath_cat_paths(3, $1, PXP("/@"), PXP($4)); }
457	;
458
459selector
460  : simple_selector_sequence combinator selector						{ $$ = pxpath_cat_paths(3, $1, PXP($2), $3); }
461	| simple_selector_sequence
462  ;
463	
464combinator
465  : OptS PLUS OptS			{ $$ = "/following-sibling::*[1]/self::"; } 
466	| OptS GT OptS				{ $$ = "/"; } 
467	| OptS TILDE OptS		{ $$ = "/following-sibling::*/self::"; } 
468	| S							{ $$ = "//"; }
469  ;
470
471simple_selector_sequence
472	: simple_selector_anchor                        
473	| possibly_empty_sequence LBRA	type_selector OptS CXOPHE OptS StringLike OptS RBRA                   { $$ = pxpath_cat_paths(10, $1, PXP("[@"), $3, PXP(" = "), $7, PXP(" or starts-with(@"), $3, PXP(", concat("), $7, PXP(", '-' ))]")); }
474	| possibly_empty_sequence CXNOT LPAREN selectors_group RPAREN		                                      { $$ = pxpath_cat_paths(5, PXP("set-difference("), $1, PXP(", "), $4, PXP(")")); }
475	| possibly_empty_sequence HASH Ident		                                                              { $$ = P4E($1, "[@id='", $3, "']"); }
476	| possibly_empty_sequence DOT Ident		                                                                { $$ = P4E($1, "[contains(concat( ' ', @class, ' ' ), concat( ' ', '", $3, "', ' ' ))]"); }
477	| possibly_empty_sequence LBRA	type_selector RBRA                                                    { $$ = P4E($1, "[@", $3, "]"); }
478	| possibly_empty_sequence CXEQ LPAREN NumberLike RPAREN			                                          { $$ = P4E($1, "[position() = ", $3, "]"); }
479	| possibly_empty_sequence CXGT LPAREN NumberLike RPAREN			                                          { $$ = P4E($1, "[position() > ", $3, "]"); }
480	| possibly_empty_sequence CXLT LPAREN NumberLike RPAREN			                                          { $$ = P4E($1, "[position() < ", $3, "]"); }
481	| possibly_empty_sequence CXCONTAINS	LPAREN StringLike RPAREN                                        { $$ = P4E($1, "[contains(., ", $4, ")]"); }
482	| possibly_empty_sequence CXHAS LPAREN selectors_group RPAREN		                                      { $$ = P4E($1, "[", $3, "]"); }
483	| possibly_empty_sequence CXNTHTYPE LPAREN NumberLike RPAREN		                                    	{ $$ = P4E($1, "[position() = ", $3, "]"); }
484	| possibly_empty_sequence CXNTHLASTTYPE LPAREN NumberLike RPAREN			                                { $$ = P4E($1, "[position() = last() - ", $3, "]"); }
485	| possibly_empty_sequence LBRA	type_selector OptS EQ OptS StringLike OptS RBRA                       { $$ = P6E($1, "[@", $3, " = ", $7, "]"); }
486	| possibly_empty_sequence LBRA	type_selector OptS CXOPNE OptS StringLike OptS RBRA                   { $$ = P6E($1, "[@", $3, " != ", $7, "]"); }
487	| possibly_empty_sequence LBRA	type_selector OptS CXOPSTARTEQ OptS StringLike OptS RBRA              { $$ = P6E($1, "[starts-with(@", $3, ", ", $7, ")]"); }
488	| possibly_empty_sequence LBRA	type_selector OptS CXOPENDEQ OptS StringLike OptS RBRA                { $$ = P6E($1, "[ends-with(@", $3, ", ", $7, ")]"); }
489	| possibly_empty_sequence LBRA	type_selector OptS CXOPCONTAINS OptS StringLike OptS RBRA             { $$ = P6E($1, "[contains(@", $3, ", ", $7, ")]"); }
490	| possibly_empty_sequence LBRA	type_selector OptS CXOPCONTAINS2 OptS StringLike OptS RBRA            { $$ = P6E($1, "[contains(@", $3, ", ", $7, ")]"); }
491	| possibly_empty_sequence CXNTHCH LPAREN NumberLike RPAREN 	                                          { $$ = P4O("*[", $4,  "]/self::", $1); }
492	| possibly_empty_sequence CXNTHLASTCH LPAREN NumberLike RPAREN 	                                      { $$ = P4O("*[last() - ", $4, "]/self::", $1); }
493	| possibly_empty_sequence CXFIRST	                                                                    { $$ = APPEND($1, "[1]"); }
494	| possibly_empty_sequence CXLAST	                                                                  	{ $$ = APPEND($1, "[last()]"); }
495	| possibly_empty_sequence CXEVEN		                                                                  { $$ = APPEND($1, "[position() % 2 = 0]"); }
496	| possibly_empty_sequence CXODD		                                                                    { $$ = APPEND($1, "[position() % 2 = 1]"); }
497	| possibly_empty_sequence CXCONTENT	LPAREN StringLike RPAREN	                                                                { $$ = P4E($1, "[translate(normalize-space(.), $nbsp, ' ')=", $4, "]"); }
498	| possibly_empty_sequence CXHEADER		                                                                { $$ = APPEND($1, "[contains('h1 h2 h3 h4 h5 h6', lower-case(local-name()))]"); }
499	| possibly_empty_sequence CXEMPTY		                                                                  { $$ = APPEND($1, "[not(node())]"); }
500	| possibly_empty_sequence CXPARENT		                                                                { $$ = APPEND($1, "[node()]"); }
501	| possibly_empty_sequence CXFIRSTTYPE                                                                 { $$ = APPEND($1, "[1]"); }
502	| possibly_empty_sequence CXLASTTYPE                                                                  { $$ = APPEND($1, "[last()]"); }
503	| possibly_empty_sequence CXONLYTYPE 	                                                                { $$ = APPEND($1, "[count()=1]"); }
504	| possibly_empty_sequence CXINPUT 		                                                                { $$ = APPEND($1, "[lower-case(name())='input']"); }
505	| possibly_empty_sequence CXENABLED 	                                                                { $$ = APPEND($1, "[lower-case(name())='input' and not(@disabled)]"); }
506	| possibly_empty_sequence CXDISABLED 	                                                                { $$ = APPEND($1, "[lower-case(name())='input' and @disabled]"); }
507	| possibly_empty_sequence CXCHECKED 	                                                                { $$ = APPEND($1, "[@checked]"); }
508	| possibly_empty_sequence CXSELECTED 	                                                                { $$ = APPEND($1, "[@selected]"); }
509	| possibly_empty_sequence CXFIRSTCH 	                                                                { $$ = PREPEND($1, "*[1]/self::"); }
510	| possibly_empty_sequence CXLASTCH 	                                                                  { $$ = PREPEND($1, "*[last()]/self::"); }
511	| possibly_empty_sequence CXONLYCH 		                                                                { $$ = PREPEND($1, "*[count()=1]/self::"); }
512  | possibly_empty_sequence CXTEXT 			                                                                { $$ = INPUT_TYPE($1, text); }
513	| possibly_empty_sequence CXPASSWORD 	                                                                { $$ = INPUT_TYPE($1, password); }
514	| possibly_empty_sequence CXRADIO 		                                                                { $$ = INPUT_TYPE($1, radio); }
515	| possibly_empty_sequence CXCHECKBOX 	                                                                { $$ = INPUT_TYPE($1, checkbox); }
516	| possibly_empty_sequence CXSUBMIT 		                                                                { $$ = INPUT_TYPE($1, submit); }
517	| possibly_empty_sequence CXIMAGE 		                                                                { $$ = INPUT_TYPE($1, image); }
518	| possibly_empty_sequence CXRESET 		                                                                { $$ = INPUT_TYPE($1, reset); }
519	| possibly_empty_sequence CXBUTTON 		                                                                { $$ = INPUT_TYPE($1, button); }
520	| possibly_empty_sequence CXFILE 			                                                                { $$ = INPUT_TYPE($1, file); }
521	;
522	
523possibly_empty_sequence
524	: simple_selector_sequence
525	|											{ $$ = PXP("*"); }
526	;
527
528simple_selector_anchor
529	:	type_selector
530	| universal
531	;
532
533type_selector
534  : namespace_prefix element_name	{	$$ = pxpath_cat_paths(3, $1, PXP(":"), $2); }
535  | element_name				
536  ;
537
538namespace_prefix
539  : SPLAT PIPE			{ $$ = PXP("*"); }
540  | Ident PIPE			{	$$ = $1;  }
541  | PIPE						{ $$ = PXP("*"); }
542  ;
543
544element_name
545  : Ident  { $$ = $1; }
546  ;
547
548universal
549  : namespace_prefix SPLAT { $$ = pxpath_cat_paths(3, $1, PXP(":"), PXP($2)); }
550  | SPLAT                   { $$ = PXP($1); }
551  ;
552
553NumberLike
554	: NUMBER                  { $$ = PXP($1); }
555  ;
556
557Ident
558	: NAME                { $$ = PXP($1); }
559	| BSLASHLIT						{ $$ = PXP($1 + 1); }
560	| NAME Ident					{ $$ = pxpath_cat_paths(2, PXP($1), $2); }
561	| BSLASHLIT Ident			{ $$ = pxpath_cat_paths(2, PXP($1 + 1), $2); }
562	| keyword             { $$ = PXP($1); }
563	;
564	
565keyword
566	: XANCESTOR
567	| XANCESTORSELF
568	| XATTR
569	| XCHILD
570	| XDESC
571	| XDESCSELF
572	| XFOLLOW
573	| XFOLLOWSIB
574	| XNS
575	| XPARENT
576	| XPRE
577	| XPRESIB
578	| XSELF
579	| XOR
580	| XAND
581	| XDIV
582	| XMOD
583	| XCOMMENT
584	| XTEXT
585	| XPI
586	| XNODE
587	;
588	
589StringLike
590	: Ident 			
591	| STRING      { $$ = pxpath_new_literal(1, $1); }
592	;
593
594OptS
595  : S			      { $$ = 0; }					
596	|							{ $$ = 0; }
597	;
598	
599%%
600
601char* xpath_alias(char* key) {
602	char* value = (char*) xmlHashLookup(alias_hash, key);
603	return value == NULL ? key : value;
604}
605
606void init_xpath_alias() {
607	alias_hash = xmlHashCreate(100);
608	xmlHashAddEntry(alias_hash, "html", "lib:html-document");
609	xmlHashAddEntry(alias_hash, "match", "regexp:match");
610	xmlHashAddEntry(alias_hash, "replace", "regexp:replace");
611	xmlHashAddEntry(alias_hash, "test", "regexp:test");
612	xmlHashAddEntry(alias_hash, "with-newlines", "lib:nl");	
613}
614
615pxpathPtr myparse(char* string){
616  // start_debugging();
617  parsed_answer = NULL;
618  prepare_parse(string);
619  yyparse();
620  cleanup_parse();
621	return parsed_answer;
622}
623
624void answer(pxpathPtr a){
625	parsed_answer = a;
626}
627
628void start_debugging(){
629  yydebug = 1;
630  return;
631}