Dynamic PEG for interpreted languages.
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

208 linhas
4.0 KiB

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
;
enum op { String, Query, Star, Plus, Or, And, Class, Dot, Exc } ;
typedef union Node Node;
struct String { enum op type; char *string; };
struct Query { enum op type; Node *children[1]; };
struct Star { enum op type; Node *children[1]; };
struct Plus { enum op type; Node *children[1]; };
struct Or { enum op type; Node *children[2]; };
struct And { enum op type; Node *children[2]; };
struct Class { enum op type; char *stringValue; int len; };
struct Dot { enum op type;};
struct Exc { enum op type; Node *children[1]; };
union Node {
enum op type;
struct String String;
struct Query Query;
struct Star Star;
struct Plus Plus;
struct Or Or;
struct And And;
struct Class Class;
struct Dot Dot;
struct Exc Exc;
};
Node *mkString(char *s)
{
Node *node= calloc(1, sizeof(struct String));
node->type= String;
node->String.string= strdup(s);
return node;
}
Node *mkQuery(Node *n)
{
Node *node= calloc(1, sizeof(struct Query));
node->type= Query;
node->Query.children[0]= n;
return node;
}
Node *mkOr(Node *node1, Node *node2)
{
Node *node= calloc(1, sizeof(struct Or));
node->Or.children[0]= node1;
node->Or.children[1]= node2;
return node;
}
Node *mkAnd(Node *node1, Node *node2)
{
Node *node= calloc(1, sizeof(struct And));
node->And.children[0]= node1;
node->And.children[1]= node2;
return node;
}
Node *mkStar(Node *n)
{
Node *node= calloc(1, sizeof(struct Star));
node->type= Star;
node->Star.children[0]= n;
return node;
}
Node *mkClass(char* str)
{
Node *node= calloc(1, sizeof(struct Class));
node->Class.stringValue= str;
node->Class.len=strlen(str);
return node;
}
Node *mkPlus(Node *n)
{
Node *node= calloc(1, sizeof(struct Plus));
node->type= Plus;
node->Plus.children[0]= n;
return node;
}
Node *mkDot()
{
Node *node= calloc(1, sizeof(struct Dot));
node->type= Dot;
return node;
}
Node *mkExc(Node *n)
{
Node *node= calloc(1, sizeof(struct Exc));
node->type= Exc;
node->Exc.children[0]= n;
return node;
}
void print(Node *node)
{
switch (node->type) {
case String:
printf("\"%s\"", node->String.string);
return;
case Query:
print(node->Query.children[0]);
printf("?");
return;
case Star:
print(node->Query.children[0]);
printf("*");
return;
case Plus:
print(node->Query.children[0]);
printf("+");
return;
case Or:
print(node->Or.children[0]);
print(node->Or.children[1]);
printf("Or");
return;
case And:
print(node->And.children[0]);
print(node->And.children[1]);
printf("And");
return;
case Class:
printf("Class");
printf("\"%s\"", node->Class.stringValue);
return;
case Dot:
printf("Dot");
return;
case Exc:
printf("!");
print(node->Exc.children[0]);
return;
}
abort();
}
void println(Node *node)
{
print(node);
printf("\n");
}
#define YYSTYPE Node *
YYSTYPE yylval = 0;
%}
start = - o:or { yylval = o }
or = a:and "|" - o:or { $$ = mkOr(o, a) }
| a:and { $$ = a }
and = p:prefix a:and { $$ = mkAnd(p, a) }
| p:prefix { $$ = p }
prefix = "!"- p : postfix {$$ = mkExc(p)}
| p: postfix {$$ = p}
postfix = s:atom ( "?" - { s = mkQuery(s) }
| "*" - { s = mkStar(s) }
| "+" - { s = mkPlus(s) }
)? { $$ = s}
atom = string | class | dot
string = '"' < [^"]* > '"' { $$ = mkString(yytext) } -
class = '[' <[]*> ']' { $$=mkClass(yytext) } -
dot = '.' {$$=mkDot()} -
- = space*
space = [ \t] | '\n' '\r'* | '\r' '\n'*
%%
int main(int argc, char **argv)
{
while (yyparse()) {
println(yylval);
}
return 0;
(void)yySet;
(void)yyPop;
(void)yyPush;
(void)yyAccept;
(void)yymatchDot;
(void)yymatchString;
(void)yymatchChar;
}