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.

320 lignes
6.6 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node Node;
typedef struct Exploration Exploration;
enum opcode {
STRING,
AND,
OR,
STAR,
PLUS,
CLASS,
QUESTION_MARK,
EXCLAMATION_MARK,
DOT
};
struct Exploration
{
int position;
char *text;
};
Exploration *mkExploration(char *text)
{
Exploration *exploration = calloc(1,sizeof(Exploration*)); //sizeof du type pointeur
exploration->position= 0;
exploration->text= text;
return exploration;
}
void advance(Exploration *exploration, int add)
{
exploration->position+= add;
}
int atEnd(Exploration *exploration) {
return exploration->text[exploration->position] == 0;
}
void setPosition(Exploration *exploration, int position)
{
exploration->position= position;
}
int getPosition(Exploration *exploration) {
return exploration->position;
}
int currentChar(Exploration *exploration)
{
return exploration->text[exploration->position];
}
char *currentText(Exploration *exploration)
{
return exploration->text + exploration->position;
}
struct String { enum opcode type; char *stringValue; int len;};
struct Class { enum opcode type; char *stringValue; int len;};
struct Node
{
enum opcode type;
union {
struct String STRING;
struct Class CLASS;
Node *children[2];
};
};
Node *mkNode(enum opcode type)
{
Node *node= calloc(1, sizeof(Node));
node->type= type;
return node;
}
Node *mkString(char *value)
{
Node *node= mkNode(STRING);
node->STRING.stringValue= value;
node->STRING.len=strlen(value);
return node;
}
Node *mkAnd(Node *node1, Node *node2)
{
Node *node= mkNode(AND);
node->children[0]= node1;
node->children[1]= node2;
return node;
}
Node *mkStar(Node *child)
{
Node *node= mkNode(STAR);
node->children[0]= child;
return node;
}
Node *mkPlus(Node *child)
{
Node *node= mkNode(PLUS);
node->children[0]= child;
return node;
}
Node *mkOr(Node *node1, Node *node2)
{
Node *node= mkNode(OR);
node->children[0]= node1;
node->children[1]= node2;
return node;
}
Node *mkClass(char* str)
{
Node *node= mkNode(CLASS);
node->STRING.stringValue= str;
node->STRING.len=strlen(str);
return node;
}
Node *mkQuestionMark(Node *child)
{
Node *node= mkNode(QUESTION_MARK);
node->children[0]= child;
return node;
}
Node *mkExclamationMark(Node *child)
{
Node *node= mkNode(EXCLAMATION_MARK);
node->children[0]= child;
return node;
}
Node *mkDot()
{
Node *node= mkNode(DOT);
return node;
}
Node *_checktype(Node *object, enum opcode 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)
const char* getTypeName(enum opcode type)
{
switch (type)
{
case STAR: return "STAR";
case EXCLAMATION_MARK: return "NOT";
case DOT: return "DOT";
case QUESTION_MARK: return "QMARK";
case PLUS : return "PLUS";
case CLASS : return "CLASS";
default : printf("unexpected use");return 0;
abort();
}
}
void println(Node *node, int indent)
{
for(int i=0;i<indent;i++){
printf("----");
}
indent++;
switch (node->type) {
case STRING: printf("%.*s", get(node, STRING, len), get(node, STRING, stringValue)); return;
case AND: {
printf("AND\n");
println(node->children[0],indent);printf("\n");
println(node->children[1],indent);printf("\n");return;
}
case OR: {
printf("OR\n");
println(node->children[0],indent);printf("\n");
println(node->children[1],indent);printf("\n");return;
}
case DOT:{
printf("DOT\n");return;
}
case CLASS:{
printf("CLASS : Char in [%.*s]\n",get(node, CLASS, len),get(node, CLASS, stringValue));return;
}
default : {
printf("%s\n",getTypeName(node->type));
println(node->children[0],indent);printf("\n");return;
}
}
abort();
}
int execute(Node *node, Exploration *in)
{
switch (node->type) {
case STRING: {
if (strncmp(currentText(in), node->STRING.stringValue, node->STRING.len)) {
return 0;
}
advance(in, node->STRING.len);
return 1;
}
case AND: {
int pos= getPosition(in);
if (!execute(node->children[0], in)) //si il y a eu une erreur
{
return 0;
} //si ça s'est bien passé
if (!execute(node->children[1], in)) {
setPosition(in, pos);
return 0;
}
return 1;
}
case OR: {
if (execute(node->children[0], in)) {
return 1;
}
return execute(node->children[1], in);
}
case STAR: {
while (execute(node->children[0], in));
return 1;
}
case PLUS: {
if (!execute(node->children[0], in)) {
return 0;
}
while (execute(node->children[0], in));
return 1;
}
case CLASS: {
if (!currentChar(in)) {
return 0;
}
if (strchr(node->STRING.stringValue, currentChar(in))) {
advance(in, 1);
return 1;
}
return 0;
}
case QUESTION_MARK: {
execute(node->children[0], in);
return 1;
}
case EXCLAMATION_MARK: {
int pos= getPosition(in);
if (!execute(node->children[0], in)) {
return 1;
}
setPosition(in, pos);
return 0;
}
case DOT: {
if (atEnd(in)) {
return 0;
}
advance(in, 1);
return 1;
}
}
printf("this cannot happen\n");
abort();
}
int main(int argc, char **argv)
{
Exploration *in= mkExploration("aabbcc");
/*Node *program=
mkString("aabbcc");
Node *program=
mkAnd(mkString("aab"),
mkString("bcc"));*/
/*Node *program=
mkAnd(mkString("aa"),
mkAnd(mkString("bb"),
mkString("cc")));*/
/*Node *program=
mkOr(mkPlus(mkString("a")), // "a"*"b"*"c"*
mkAnd(mkStar(mkString("b")),
mkStar(mkString("c"))));*/
Node *program= mkStar(mkClass("abc"));
Node *program3=mkAnd(mkAnd(mkPlus(mkString("hello world")),mkExclamationMark(mkString("how are u world !?"))),mkStar(mkClass("abcde")));
if (!execute(program, in) || !atEnd(in))
{
printf("no match, current position : %i\n", getPosition(in));
} else
{
printf("match, current position : %i\n", getPosition(in));
}// 0 => no match, 1 => match
println(program3,0);
return 0;
}