Dynamic PEG for interpreted languages.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

479 lignes
11 KiB

%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "inputBuffer.c"
;
enum op { String, Query, Star, Plus, Or, And, Class, Dot, Exc, Id } ;
typedef union Node Node;
typedef struct Symbol Symbol;
typedef struct Array Array;
typedef struct SymbolTable SymbolTable;
struct Array {
Node **elements;
int length;
};
struct String { enum op type; char *string; int len; };
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]; };
struct Id { enum op type; Symbol *symbol; };
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;
struct Id Id;
};
struct Symbol{
char* name;
Node *rule;
};
struct SymbolTable {
Symbol **elements;
int length;
};
#define SymbolTable_initialiser {0,0}
SymbolTable symbolTable= SymbolTable_initialiser;
Symbol *createSymbol(char *name) {
Symbol *symbol= calloc(1, sizeof(Symbol));
symbol->name= strdup(name);
return symbol;
}
#define new(type) mkNode(sizeof(struct type),type)
Node *mkNode(size_t size,enum op type)
{
Node *node= calloc(1, size);
node->type= type;
return node;
}
Node *mkString(char *s)
{
Node *node= new(String);
node->String.string= strdup(s);
node->String.len=strlen(s);
return node;
}
Node *mkId(char *s){
Node *node= new(Id);
node->Id.symbol=createSymbol(s);
return node;
}
Node *mkQuery(Node *n)
{
Node *node= new(Query);
node->Query.children[0]= n;
return node;
}
Node *mkOr(Node *node1, Node *node2)
{
Node *node= new(Or);
node->Or.children[0]= node1;
node->Or.children[1]= node2;
return node;
}
Node *mkAnd(Node *node1, Node *node2)
{
Node *node= new(And);
node->And.children[0]= node1;
node->And.children[1]= node2;
return node;
}
Node *mkStar(Node *n)
{
Node *node= new(Star);
node->Star.children[0]= n;
return node;
}
Node *mkClass(char* str)
{
Node *node= new(Class);
node->Class.stringValue= str;
node->Class.len=strlen(str);
return node;
}
Node *mkPlus(Node *n)
{
Node *node= new(Plus);
node->Plus.children[0]= n;
return node;
}
Node *mkDot()
{
Node *node= new(Dot);
return node;
}
Node *mkExc(Node *n)
{
Node *node= new(Exc);
node->Exc.children[0]= n;
return node;
}
Node *_checktype(Node *object, enum op type)
{
if (object->type == type) return object;
fprintf(stderr, "\naccesing type %i as if it were a %i\n", object->type, type);
exit(1);
return 0;
}
#define get(object, type, member) (_checktype(object, type)->type.member)
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]);
return;
case Or:
print(node->Or.children[0]);
printf("Or");
print(node->Or.children[1]);
return;
case And:
print(node->And.children[0]);
printf("And");
print(node->And.children[1]);
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;
case Id:
printf("%s\n",get(node,Id,symbol)->name);
return;
}
abort();
}
void println(Node *node)
{
print(node);
printf("\n");
}
InputBuffer *inputBuffer=0;
#define YY_INPUT(buff,result,maxSize) \
{if (atEnd(inputBuffer)){ \
result=0; \
} \
else { \
*buff=currentChar(inputBuffer); \
advance(inputBuffer,1); \
result=1; \
}}
void move(SymbolTable *symbolTable, int a) {
symbolTable->length++;
symbolTable->elements= realloc(symbolTable->elements,sizeof(Node*) * symbolTable->length);
printf("begin\n");
for (int i= symbolTable->length-1; i >a; i--) {
symbolTable->elements[i] = symbolTable->elements[i-1];
printf("\n");
for(int i= 0; i<symbolTable->length; i++) {
printf("number : %i, name : %s, value : a\n",i, symbolTable->elements[i]->name);
}
}
printf("end\n");
}
void addSymbolSorted(SymbolTable *symbolTable, Symbol *symbol) {
int a=0;
int b= symbolTable->length-1;
int c;
//1 <b-a => no infinite loop with a and c = 0 et b =1
while (1 < b - a ) {
c= (a+b)/2;
if (strcmp(symbolTable->elements[c]->name, symbol->name) < 0) {
a= c;
} else {
b= c;
}
}
//b>-1 <=> symboleTable->length > 0
// this if is here to know if we put the symbol before or after a
if (b>-1 && strcmp(symbolTable->elements[a]->name, symbol->name) < 0) {
a++;
}
//we move all the symbols after a
move(symbolTable, a);
//we put the symbol at the right place
symbolTable->elements[a]->name = symbol->name;
}
int findSymbol(SymbolTable *symbolTable, char *name) {
for (int i= 0; i < symbolTable->length;i++) {
if (strcmp(symbolTable->elements[i]->name, name) == 0) {
return 1;
}
}
Symbol *symbol = createSymbol(name);
addSymbolSorted(symbolTable, symbol);
return 0;
}
Node *findSymbolSorted(SymbolTable *symbolTable, char *name) {
int a=0;
int b= symbolTable->length-1;
int c;
//1 <b-a => no infinite loop with a and c = 0 et b =1
while (1 < b - a ) {
c= (a+b)/2;
if (strcmp(symbolTable->elements[c]->name, name) < 0) {
a= c;
} else {
if (strcmp(symbolTable->elements[c]->name, name) > 0) {
b= c;
} else {
return symbolTable->elements[c]->rule;
}
}
}
//b>-1 <=> symboleTable->length > 0
// this if is here to know if we put the symbol before or after a
if (b>-1 && strcmp(symbolTable->elements[a]->name, name) < 0) {
a++;
}
//we move all the symbols after a
move(symbolTable, a);
//we put the symbol at the right place
symbolTable->elements[a]= createSymbol(name);
return 0;
}
void setRule(SymbolTable *symbolTable, char *name, Node *rule) {
for (int i= 0; i < symbolTable->length;i++) {
if (strcmp(symbolTable->elements[i]->name, name) == 0) {
symbolTable->elements[i]->rule= rule;
break;
}
}
}
void arrayAppend(Array *array, Node *statement) {
array->length++;
array->elements= realloc(array->elements,sizeof(Node*) * array->length);
array->elements[array->length-1] = statement;
}
#define YYSTYPE Node *
YYSTYPE yylval = 0;
%}
start = declaration+
declaration = i:id '=' - e:expression { setRule(&symbolTable,get(i, Id, symbol)->name, e) }
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 | rule
rule = i:id !'=' { $$ = mkId(yytext) }
id = < [a-zA-z_][a-zA-z_0-9]* > - { $$ = mkId(yytext) }
string = '"' < [^"]* > '"' { $$ = mkString(yytext) } -
class = '['-<(!']'string)*> ']' { $$=mkClass(yytext) } -
dot = -'.'- {$$=mkDot()} -
- = space*
space = [ \t] | '\n' '\r'* | '\r' '\n'*
%%
int execute(Node *node, InputBuffer *in)
{
switch (node->type) {
case String: {
if (strncmp(currentText(in), get(node,String,string), get(node,String,len))) {
return 0;
}
advance(in, get(node,String,len));
return 1;
}
case And: {
int pos= getPosition(in);
if (!execute(get(node,And,children[0]), in)) //si il y a eu une erreur
{
return 0;
} //si ça s'est bien passé
if (!execute(get(node,And,children[1]), in)) {
setPosition(in, pos);
return 0;
}
return 1;
}
case Or: {
if (execute(get(node,Or,children[0]), in)) {
return 1;
}
return execute(get(node,Or,children[1]), in);
}
case Star: {
while (execute(get(node,Star,children[0]), in));
return 1;
}
case Plus: {
if (!execute(get(node,Plus,children[0]), in)) {
return 0;
}
while (execute(get(node,Plus,children[0]), in));
return 1;
}
case Class: {
if (!currentChar(in)) {
return 0;
}
if (strchr(get(node,Class,stringValue), currentChar(in))) {
advance(in, 1);
return 1;
}
return 0;
}
case Query: {
execute(get(node,Query,children[0]), in);
return 1;
}
case Exc: {
int pos= getPosition(in);
if (!execute(get(node,Exc,children[0]), in)) {
return 1;
}
setPosition(in, pos);
return 0;
}
case Dot: {
if (atEnd(in)) {
return 0;
}
advance(in, 1);
return 1;
}
case Id: {
Symbol *symbol= get(node, Id, symbol);
return execute(symbol->rule, in);
}
}
printf("this cannot happen\n");
abort();
}
int main(int argc, char **argv)
{
if(argc<2) return 0;
inputBuffer = mkInputBuffer(argv[1]);
if (!yyparse()) {
printf("Error\n");
return 1;
}
println(yylval);
char *line=0;
size_t line_max=0;
ssize_t line_len=0;
while((line_len=getline(&line,&line_max,stdin))>=0){
if(line_len>0 && line[line_len-1]=='\n'){
line[line_len-1]=0;
}
initInputBuffer(inputBuffer,line);
if (!execute(yylval, inputBuffer) || !atEnd(inputBuffer)){
printf("no match, current position : %i\n", getPosition(inputBuffer));
}
else{
printf("match, current position : %i\n", getPosition(inputBuffer));
}// 0 => no match, 1 => match
}
return 0;
(void)yySet;
(void)yyPop;
(void)yyPush;
(void)yyAccept;
(void)yymatchDot;
(void)yymatchString;
(void)yymatchChar;
}