text: if (typeof define!=="function") {
  	define=require("requirejs").define;
  }
  
  define(["Parser"], function (Parser) {
  Grammar=function () {
  	var p=Parser;
  
  	var $=null;
  	function trans(name) {
  		if (typeof name=="string") return $.get(name);
  		return name;
  	}
  	function tap(name) {
  		return p.Parser.create(function (st) {
  			console.log("Parsing "+name+" at "+st.pos+"  "+st.src.str.substring(st.pos, st.pos+20).replace(/[\r\n]/g,"\\n"));
  			return st;
  		});
  	}
  	$=function (name){
  		var $$={};
  		$$.ands=function() {
  			var p=trans(arguments[0]);  //  ;
  			for (var i=1 ; i<arguments.length ;i++) {
  				p=p.and( trans(arguments[i]) );
  			}
  			p=p.tap(name);
  			$.defs[name]=p;
  			var $$$={};
  			$$$.autoNode=function () {
  				var res=p.ret(function () {
  					var res={type:name};
  					for (var i=0 ; i<arguments.length ;i++) {
  						var e=arguments[i];
  						var rg=Parser.setRange(e);
  						Parser.addRange(res, rg);
  						res["-element"+i]=e;
  					}
  					res.toString=function () {
  						return "("+this.type+")";
  					};
  				}).setName(name);
  				return $.defs[name]=res;
  			};
  			$$$.ret=function (f) {
  				if (arguments.length==0) return p;
  				if (typeof f=="function") {
  					return $.defs[name]=p.ret(f);
  				}
  				var names=[];
  				var fn=function(e){return e;};
  				for (var i=0 ; i<arguments.length ;i++) {
  					if (typeof arguments[i]=="function") {
  						fn=arguments[i];
  						break;
  					}
  					names[i]=arguments[i];
  				}
  				var res=p.ret(function () {
  					var res={type:name};
  					res[Grammar.SUBELEMENTS]=[];
  					for (var i=0 ; i<arguments.length ;i++) {
  						var e=arguments[i];
  						var rg=Parser.setRange(e);
  						Parser.addRange(res, rg);
  						if (names[i]) {
  							res[names[i]]=e;
  						}
  						res[Grammar.SUBELEMENTS].push(e);
  					}
  					res.toString=function () {
  						return "("+this.type+")";
  					};
  					return fn(res);
  				}).setName(name);
  				return  $.defs[name]=res;
  			};
  			return $$$;
  		};
  		$$.ors= function () {
  			var p=trans(arguments[0]);
  			for (var i=1 ; i<arguments.length ;i++) {
  				p=p.or( trans(arguments[i]) );
  			}
  			return $.defs[name]=p.setName(name);
  		};
  		return $$;
  	};
  
  	$.defs={};
  	$.get=function (name) {
  		if ($.defs[name]) return $.defs[name];
  		return p.lazy(function () {
  			var r=$.defs[name];
  			if (!r) throw "grammar named '"+name +"' is undefined";
  			return r;
  		}).setName("(Lazy of "+name+")");
  	};
  	return $;
  };
  Grammar.SUBELEMENTS="[SUBELEMENTS]";
  return Grammar;
  });