ref: 455e30a2680bb0d1eb77d6a051efbafc9f00600d
dir: /peg.peg/
%{ #include "tree.h" #include "version.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <libgen.h> #include <assert.h> typedef struct Header Header; struct Header { int line; char *text; Header *next; }; FILE *input= 0; int verboseFlag= 0; int nolinesFlag= 0; static int lineNumber= 0; static int headerLine= 0; static int actionLine= 0; static char *fileName= 0; static int trailerLine= 0; static char *trailer= 0; static Header *headers= 0; void makeHeader(int line, char *text); void makeTrailer(int line, 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= '%{' { headerLine= lineNumber; } < ( !'%}' (end-of-line | .) )* > RPERCENT { makeHeader(headerLine, yytext); } #{YYACCEPT} trailer= '%%' { headerLine= lineNumber } < .* > { makeTrailer(headerLine, 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= AT action { push(makeInline(yytext)); } | 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(actionLine, 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= '{' { actionLine= lineNumber } < braces* > '}' - braces= '{' braces* '}' | !'}' ( end-of-line | . ) EQUAL= '=' - COLON= ':' - SEMICOLON= ';' - BAR= '|' - AND= '&' - NOT= '!' - AT= '@' - QUESTION= '?' - STAR= '*' - PLUS= '+' - OPEN= '(' - CLOSE= ')' - DOT= '.' - BEGIN= '<' - END= '>' - TILDE= '~' - RPERCENT= '%}' - -= (space | comment)* space= ' ' | '\t' | end-of-line comment= '#' (!end-of-line .)* end-of-line end-of-line= ( '\r\n' | '\n' | '\r' ) { ++lineNumber } 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"); exit(1); } void makeHeader(int line, char *text) { Header *header= (Header *)malloc(sizeof(Header)); header->line= line; header->text= strdup(text); header->next= headers; headers= header; } void makeTrailer(int line, char *text) { trailerLine= line; trailer= strdup(text); } static void version(char *name) { printf("%s version %s\n", name, MINIPEG_VERSION); } 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, " -P do not generate #line directives\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"); exit(1); } int main(int argc, char **argv) { Node *n; int c; output= stdout; input= stdin; lineNumber= 1; fileName= "<stdin>"; while (-1 != (c= getopt(argc, argv, "PVho:v"))) { switch (c) { case 'V': version(basename(argv[0])); exit(0); case 'h': usage(basename(argv[0])); break; case 'o': if (!(output= fopen(optarg, "w"))) { perror(optarg); exit(1); } break; case 'P': nolinesFlag= 1; break; case 'v': verboseFlag= 1; break; default: fprintf(stderr, "for usage try: %s -h\n", argv[0]); exit(1); } } argc -= optind; argv += optind; if (argc) { for (; argc; --argc, ++argv) { if (!strcmp(*argv, "-")) { input= stdin; fileName= "<stdin>"; } else { if (!(input= fopen(*argv, "r"))) { perror(*argv); exit(1); } 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, "#line %i \"%s\"\n%s\n", headers->line, fileName, headers->text); if (rules) Rule_compile_c(rules, nolinesFlag); if (trailer) { if (!nolinesFlag) fprintf(output, "#line %i \"%s\"\n", trailerLine, fileName); fprintf(output, "%s\n", trailer); } return 0; }