shithub: xml-9atom

ref: 4e09200f7e4bf8791c9c720922734e0759206b72
dir: /libxpath/xmlpath.y/

View raw version
%{
#include <u.h>
#include <libc.h>
#include <xml.h>
#include <xpath.h>
#include "dat.h"

extern int yylex(void);
extern int yyparse(void);

int yyxstep;

void
yyerror(char *s)
{
	werrstr("%s", s);
}

%}

%union {
	int i;
	int n;
	Name *nm;
	Node *nd;
}

%token	<i> 	CHILD PARENT SELF ANCESTOR ANCESTOR_OR_SELF DESCENDANT
%token	<i> 	DESCENDANT_OR_SELF DSLASH
%token	<i> 	FOLLOWING FOLLOWING_SIBLING PRECEDING PRECEDING_SIBLING
%token	<i> 	ATTRIBUTE NAMESPACE

%token	<i> 	AND OR EQ NEQ LT GT LE GE

%token	<nm>	NAME
%token	<nm>	QUOTE
%token	<n> 	NUMBER

%type	<nm>	name
%type	<n>		number
%type	<nm>	attr

%type	<nd>	node
%type	<nd>	func
%type	<nd>	path
%type	<nd> 	specl

%left EQ NEQ
%left LT GT
%left LE GE
%left AND
%left OR
%left '/' DSLASH CHILD
%left DESCENDANT_OR_SELF

%%

path:
	  node
	| /* empty */ { $$ = addnode(nil, Nroot, nil); }
	| path DSLASH path { $3->type = Ndescself; $$ = chainnode($1, $3); }
	| path '/' DESCENDANT_OR_SELF path { $4->type = Ndescself; $$ = chainnode($1, $4); }
	| path '/' path { $$ = chainnode($1, $3); }
	| path '/' CHILD path { $$ = chainnode($1, $4); }
	| path AND path { $$ = addcondcnode(Nand, $1, $3); }
	| path OR path { $$ = addcondcnode(Nor, $1, $3); }
	| path EQ path { $$ = addcondcnode(Neq, $1, $3); }
	| path NEQ path { $$ = addcondcnode(Nneq, $1, $3); }
	| path LT path { $$ = addcondcnode(Nlt, $1, $3); }
	| path GT path { $$ = addcondcnode(Ngt, $1, $3); }
	| path LE path { $$ = addcondcnode(Nle, $1, $3); }
	| path GE path { $$ = addcondcnode(Nge, $1, $3); }
	;

node:
	  name { $$ = addnode($1, Nchild, nil); }
	| name specl { $$ = addnode($1, Nchild, $2); }
	| number { $$ = addnoden($1, nil); }
	| number specl { $$ = addnoden($1, $2); }
	| attr { $$ = addnode($1, Nattribute, nil); }
	| func
	;

specl:
	  '[' path ']' { $$ = $2; }
	| specl '[' path ']' { $$ = addcondcnode(Nand, $1, $3); }
	;

attr:
	  '@' name { $$ = $2; }
	| ATTRIBUTE name { $$ = $2; }
	;

func:
	  name '(' ')' { $$ = addnode($1, Nfunction, nil); }
	;

number:
	  NUMBER
	;

name:
	  NAME
	;