275 lines · 6.6 KB · Text
RawDownload
# LE Grammar for LE Grammars# # Copyright (c) 2007 by Ian Piumarta# All rights reserved.# # Permission is hereby granted, free of charge, to any person obtaining a# copy of this software and associated documentation files (the 'Software'),# to deal in the Software without restriction, including without limitation# the rights to use, copy, modify, merge, publish, distribute, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, provided that the above copyright notice(s) and this# permission notice appear in all copies of the Software.  Acknowledgement# of the use of this Software in supporting documentation would be# appreciated but is not required.# # THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.# # Last edited: 2013-08-16 00:14:11 by piumarta on emilia %{#include <u.h>#include <libc.h>#include <stdio.h>#include "tree.h"#include "version.h"   typedef struct Header Header;   struct Header {    char   *text;    Header *next;  };   FILE *input= 0;   int   verboseFlag= 0;   static int	 lineNumber= 0;  static char	*fileName= 0;  static char	*trailer= 0;  static Header	*headers= 0;   void makeHeader(char *text);  void makeTrailer(char *text);   void yyerror(char *message); # define YY_INPUT(buf, result, max)		\  {						\    int c= getc(input);				\    if ('\n' == c || '\r' == c) ++lineNumber;	\    result= (EOF == c) ? 0 : (*(buf)= c, 1);	\  } # define YY_LOCAL(T)	static T# define YY_RULE(T)	static T%} # Hierarchical syntax grammar=	- ( declaration | definition )+ trailer? end-of-file declaration=	'%{' < ( !'%}' . )* > RPERCENT		{ makeHeader(yytext); }						#{YYACCEPT} trailer=	'%%' < .* >				{ makeTrailer(yytext); }					#{YYACCEPT} definition=	identifier 				{ if (push(beginRule(findRule(yytext)))->rule.expression)							    fprintf(stderr, "rule '%s' redefined\n", yytext); }			EQUAL expression		{ Node *e= pop();  Rule_setExpression(pop(), e); }			SEMICOLON?											#{YYACCEPT} expression=	sequence (BAR sequence			{ Node *f= pop();  push(Alternate_append(pop(), f)); }			    )* sequence=	error   (error				{ Node *f= pop();  push(Sequence_append(pop(), f)); }			)* error=		prefix  (TILDE action			{ push(makeError(pop(), yytext)); }			)? prefix=		AND action				{ push(makePredicate(yytext)); }|		AND suffix				{ push(makePeekFor(pop())); }|		NOT suffix				{ push(makePeekNot(pop())); }|		    suffix suffix=		primary (QUESTION			{ push(makeQuery(pop())); }			     | STAR			{ push(makeStar (pop())); }			     | PLUS			{ push(makePlus (pop())); }			   )? primary=	identifier				{ push(makeVariable(yytext)); }			COLON identifier !EQUAL		{ Node *name= makeName(findRule(yytext));  name->name.variable= pop();  push(name); }|		identifier !EQUAL			{ push(makeName(findRule(yytext))); }|		OPEN expression CLOSE|		literal					{ push(makeString(yytext)); }|		class					{ push(makeClass(yytext)); }|		DOT					{ push(makeDot()); }|		action					{ push(makeAction(yytext)); }|		BEGIN					{ push(makePredicate("YY_BEGIN")); }|		END					{ push(makePredicate("YY_END")); } # Lexical syntax identifier=	< [-a-zA-Z_][-a-zA-Z_0-9]* > - literal=	['] < ( !['] char )* > ['] -|		["] < ( !["] char )* > ["] - class=		'[' < ( !']' range )* > ']' - range=		char '-' char | char char=		'\\' [-abefnrtv'"\[\]\\]|		'\\' 'x'[0-9A-Fa-f][0-9A-Fa-f]|		'\\' 'x'[0-9A-Fa-f]|		'\\' [0-3][0-7][0-7]|		'\\' [0-7][0-7]?|		!'\\' . action=		'{' < braces* > '}' - braces=		'{' braces* '}'|		!'}' . EQUAL=		'=' -COLON=		':' -SEMICOLON=	';' -BAR=		'|' -AND=		'&' -NOT=		'!' -QUESTION=	'?' -STAR=		'*' -PLUS=		'+' -OPEN=		'(' -CLOSE=		')' -DOT=		'.' -BEGIN=		'<' -END=		'>' -TILDE=		'~' -RPERCENT=	'%}' - -=		(space | comment)*space=		' ' | '\t' | end-of-linecomment=	'#' (!end-of-line .)* end-of-lineend-of-line=	'\r\n' | '\n' | '\r'end-of-file=	!. %% void yyerror(char *message){  fprintf(stderr, "%s:%d: %s", fileName, lineNumber, message);  if (yyctx->__text[0]) fprintf(stderr, " near token '%s'", yyctx->__text);  if (yyctx->__pos < yyctx->__limit || !feof(input))    {      yyctx->__buf[yyctx->__limit]= '\0';      fprintf(stderr, " before text \"");      while (yyctx->__pos < yyctx->__limit)	{	  if ('\n' == yyctx->__buf[yyctx->__pos] || '\r' == yyctx->__buf[yyctx->__pos]) break;	  fputc(yyctx->__buf[yyctx->__pos++], stderr);	}      if (yyctx->__pos == yyctx->__limit)	{	  int c;	  while (EOF != (c= fgetc(input)) && '\n' != c && '\r' != c)	    fputc(c, stderr);	}      fputc('\"', stderr);    }  fprintf(stderr, "\n");  exits("yyerror");} void makeHeader(char *text){  Header *header= (Header *)malloc(sizeof(Header));  header->text= strdup(text);  header->next= headers;  headers= header;} void makeTrailer(char *text){  trailer= strdup(text);} static void version(char *name){  printf("%s version %d.%d.%d\n", name, PEG_MAJOR, PEG_MINOR, PEG_LEVEL);} static void usage(char *name){  version(name);  fprintf(stderr, "usage: %s [<option>...] [<file>...]\n", name);  fprintf(stderr, "where <option> can be\n");  fprintf(stderr, "  -h          print this help information\n");  fprintf(stderr, "  -o <ofile>  write output to <ofile>\n");  fprintf(stderr, "  -v          be verbose\n");  fprintf(stderr, "  -V          print version number and exit\n");  fprintf(stderr, "if no <file> is given, input is read from stdin\n");  fprintf(stderr, "if no <ofile> is given, output is written to stdout\n");  exits("usage");} voidmain(int argc, char **argv){  Node *n;  int   c;   output= stdout;  input= stdin;  lineNumber= 1;  fileName= "<stdin>";   ARGBEGIN{    case 'V':      version(argv[0]);      exits("version");    case 'h':      usage(argv[0]);    case 'o':      if(!(output = fopen(EARGF(usage(argv[0])), "w")))		sysfatal("fopen: %r");      break;   case 'v':      verboseFlag = 1;      break;  }ARGEND   if (argc)    {      for (;  argc;  --argc, ++argv)	{	  if (!strcmp(*argv, "-"))	    {	      input= stdin;	      fileName= "<stdin>";	    }	  else	    {	      if (!(input= fopen(*argv, "r")))                sysfatal("fopen: %r");	      fileName= *argv;	    }	  lineNumber= 1;	  if (!yyparse())	    yyerror("syntax error");	  if (input != stdin)	    fclose(input);	}    }  else    if (!yyparse())      yyerror("syntax error");   if (verboseFlag)    for (n= rules;  n;  n= n->any.next)      Rule_print(n);   Rule_compile_c_header();   for (; headers;  headers= headers->next)    fprintf(output, "%s\n", headers->text);   if (rules)    Rule_compile_c(rules);   if (trailer)    fprintf(output, "%s\n", trailer);   exits(nil);}