瀏覽代碼

add fatal(); remove yylval; add option -f to read grammar from a file

main
Ian Piumarta 3 年之前
父節點
當前提交
cac04a2cd3
共有 1 個文件被更改,包括 176 次插入128 次删除
  1. +176
    -128
      parse.leg

+ 176
- 128
parse.leg 查看文件

@ -3,8 +3,23 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "inputBuffer.c" #include "inputBuffer.c"
; ;
void fatal(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "\nError: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
enum op { String, Query, Star, Plus, Or, And, Class, Dot, Exc, Id } ; enum op { String, Query, Star, Plus, Or, And, Class, Dot, Exc, Id } ;
@ -82,7 +97,7 @@ Node *mkString(char *s)
} }
Node *mkId(Symbol *s){ Node *mkId(Symbol *s){
Node *node= new(Id); Node *node= new(Id);
node->Id.symbol=s; node->Id.symbol=s;
return node; return node;
@ -107,7 +122,7 @@ Node *mkOr(Node *node1, Node *node2)
Node *mkAnd(Node *node1, Node *node2) Node *mkAnd(Node *node1, Node *node2)
{ {
Node *node= new(And);
Node *node= new(And);
node->And.children[0]= node1; node->And.children[0]= node1;
node->And.children[1]= node2; node->And.children[1]= node2;
return node; return node;
@ -162,43 +177,43 @@ void print(Node *node)
{ {
switch (node->type) { switch (node->type) {
case String: case String:
printf("\"%s\"", node->String.string);
return;
printf("\"%s\"", node->String.string);
return;
case Query: case Query:
print(node->Query.children[0]);
printf("?");
return;
print(node->Query.children[0]);
printf("?");
return;
case Star: case Star:
print(node->Query.children[0]);
printf("*");
return;
print(node->Query.children[0]);
printf("*");
return;
case Plus: case Plus:
print(node->Query.children[0]);
return;
print(node->Query.children[0]);
return;
case Or: case Or:
print(node->Or.children[0]);
printf("Or");
print(node->Or.children[1]);
return;
print(node->Or.children[0]);
printf("Or");
print(node->Or.children[1]);
return;
case And: case And:
print(node->And.children[0]);
printf("And");
print(node->And.children[1]);
return;
print(node->And.children[0]);
printf("And");
print(node->And.children[1]);
return;
case Class: case Class:
printf("Class");
printf("\"%s\"", node->Class.stringValue);
return;
printf("Class");
printf("\"%s\"", node->Class.stringValue);
return;
case Dot: case Dot:
printf("Dot");
return;
printf("Dot");
return;
case Exc: case Exc:
printf("!");
print(node->Exc.children[0]);
return;
printf("!");
print(node->Exc.children[0]);
return;
case Id: case Id:
printf("%s\n",get(node,Id,symbol)->name);
return;
printf("%s\n",get(node,Id,symbol)->name);
return;
} }
abort(); abort();
} }
@ -218,7 +233,7 @@ else { \
*buff=currentChar(inputBuffer); \ *buff=currentChar(inputBuffer); \
advance(inputBuffer,1); \ advance(inputBuffer,1); \
result=1; \ result=1; \
}}
}}
@ -226,11 +241,11 @@ else { \
Symbol *intern(char *name){ Symbol *intern(char *name){
int left=0,right=symbolTable.length-1; int left=0,right=symbolTable.length-1;
while(left<=right){
while (left<=right) {
int middle=(left+right)/2; int middle=(left+right)/2;
int comp=strcmp(name,symbolTable.elements[middle]->name); int comp=strcmp(name,symbolTable.elements[middle]->name);
if(comp<0){ if(comp<0){
right=middle-1; right=middle-1;
} }
@ -241,7 +256,7 @@ Symbol *intern(char *name){
return symbolTable.elements[middle]; return symbolTable.elements[middle];
} }
} }
symbolTable.elements= realloc(symbolTable.elements,sizeof(symbolTable.elements[0]) * (symbolTable.length+1)); symbolTable.elements= realloc(symbolTable.elements,sizeof(symbolTable.elements[0]) * (symbolTable.length+1));
memmove(symbolTable.elements+left+1,symbolTable.elements+left,(symbolTable.length-left)*sizeof(symbolTable.elements[0])); memmove(symbolTable.elements+left+1,symbolTable.elements+left,(symbolTable.length-left)*sizeof(symbolTable.elements[0]));
symbolTable.length++; symbolTable.length++;
@ -249,130 +264,127 @@ Symbol *intern(char *name){
} }
void setRule(char *name, Node *rule){
void setRule(char *name, Node *rule)
{
printf("Setting rule %s to ", name);
println(rule);
intern(name)->rule=rule; intern(name)->rule=rule;
} }
#define YYSTYPE Node * #define YYSTYPE Node *
YYSTYPE yylval = 0;
%} %}
start = declaration+
declaration = i:id '=' - e:expression { setRule(get(i, Id, symbol)->name, e) }
start = - declaration+
expression = or
declaration = i:id '=' - e:expression { setRule(get(i, Id, symbol)->name, e) }
or = a:and - "|" - o:or {$$ = mkOr(o, a) }
| a:and { $$ = a }
expression = or
and = p:prefix a:and { $$ = mkAnd(p, a); }
| p:prefix { $$ = p }
or = a:and "|" - o:or { $$ = mkOr(o, a) }
| a:and { $$ = a }
prefix = "!"- p : postfix {$$ = mkExc(p)}
| p: postfix {$$ = p}
and = p:prefix a:and { $$ = mkAnd(p, a) }
| p:prefix { $$ = p }
postfix = s:atom ( "?" - { s = mkQuery(s) }
| "*" - { s = mkStar(s) }
| "+" - { s = mkPlus(s) }
)? { $$ = s}
prefix = "!" - p : postfix { $$ = mkExc(p) }
| p: postfix { $$ = p}
atom = string | class | dot | rule
postfix = s:atom ( "?" - { s = mkQuery(s) }
| "*" - { s = mkStar(s) }
| "+" - { s = mkPlus(s) }
)? { $$ = s }
rule = i:id !'=' { $$ = mkId(intern(yytext)) }
atom = string | class | dot | rule
id = < [a-zA-z_][a-zA-z_0-9]* > - { $$ = mkId(intern(yytext)) }
rule = i:id !'=' { $$ = mkId(intern(yytext)) }
string = '"' < [^"]* > '"' { $$ = mkString(yytext) } -
id = < [a-zA-z_][a-zA-z_0-9]* > - { $$ = mkId(intern(yytext)) }
class = '['-<(!']'string)*> ']' { $$=mkClass(yytext) } -
string = '"' < [^\"]* > '"' - { $$ = mkString(yytext) }
dot = -'.'- {$$=mkDot()} -
class = '['-<(!']'string)*> ']' - { $$=mkClass(yytext) }
dot = '.' - { $$=mkDot() }
- = space*
- = space*
space = [ \t] | '\n' '\r'* | '\r' '\n'*
space = [ \t] | '\n' '\r'* | '\r' '\n'*
%% %%
int execute(Node *node, InputBuffer *in) int execute(Node *node, InputBuffer *in)
{ {
switch (node->type) { switch (node->type) {
case String: { case String: {
if (strncmp(currentText(in), get(node,String,string), get(node,String,len))) {
return 0;
}
advance(in, get(node,String,len));
return 1;
if (strncmp(currentText(in), get(node,String,string), get(node,String,len))) {
return 0;
}
advance(in, get(node,String,len));
return 1;
} }
case And: { 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;
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: { case Or: {
if (execute(get(node,Or,children[0]), in)) {
return 1;
}
return execute(get(node,Or,children[1]), in);
if (execute(get(node,Or,children[0]), in)) {
return 1;
}
return execute(get(node,Or,children[1]), in);
} }
case Star: { case Star: {
while (execute(get(node,Star,children[0]), in));
return 1;
while (execute(get(node,Star,children[0]), in));
return 1;
} }
case Plus: { case Plus: {
if (!execute(get(node,Plus,children[0]), in)) {
return 0;
}
while (execute(get(node,Plus,children[0]), in));
return 1;
if (!execute(get(node,Plus,children[0]), in)) {
return 0;
}
while (execute(get(node,Plus,children[0]), in));
return 1;
} }
case Class: { case Class: {
if (!currentChar(in)) {
return 0;
}
if (strchr(get(node,Class,stringValue), currentChar(in))) {
advance(in, 1);
return 1;
}
return 0;
if (!currentChar(in)) {
return 0;
}
if (strchr(get(node,Class,stringValue), currentChar(in))) {
advance(in, 1);
return 1;
}
return 0;
} }
case Query: { case Query: {
execute(get(node,Query,children[0]), in);
return 1;
execute(get(node,Query,children[0]), in);
return 1;
} }
case Exc: { case Exc: {
int pos= getPosition(in);
if (!execute(get(node,Exc,children[0]), in)) {
return 1;
}
setPosition(in, pos);
return 0;
int pos= getPosition(in);
if (!execute(get(node,Exc,children[0]), in)) {
return 1;
}
setPosition(in, pos);
return 0;
} }
case Dot: { case Dot: {
if (atEnd(in)) {
return 0;
}
advance(in, 1);
return 1;
if (atEnd(in)) {
return 0;
}
advance(in, 1);
return 1;
} }
case Id: { case Id: {
Symbol *symbol= get(node, Id, symbol);
if (0 == symbol->rule) { printf("undefined rule: %s\n", symbol->name); }
return execute(symbol->rule, in);
Symbol *symbol= get(node, Id, symbol);
if (0 == symbol->rule) { printf("undefined rule: %s\n", symbol->name); }
return execute(symbol->rule, in);
} }
} }
printf("this cannot happen\n"); printf("this cannot happen\n");
@ -381,33 +393,69 @@ int execute(Node *node, InputBuffer *in)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
if(argc<2) return 0;
inputBuffer = mkInputBuffer(argv[1]);
switch (argc) {
case 2: {
inputBuffer = mkInputBuffer(argv[1]);
break;
}
case 3: {
if (!strcmp("-f", argv[1])) {
FILE *fp= fopen(argv[2], "r");
if (!fp) {
perror(argv[2]);
exit(1);
}
struct stat sb;
if (fstat(fileno(fp), &sb)) {
perror(argv[2]);
exit(1);
}
char *text= malloc(sb.st_size);
if (!text) {
fatal("out of memory");
exit(1);
}
if (fread(text, sb.st_size, 1, fp) < 1) {
perror(argv[2]);
exit(1);
}
fclose(fp);
inputBuffer = mkInputBuffer(text);
break;
}
fatal("unrecognised option: %s", argv[1]);
}
default: {
fatal("usage: %s parsing-expression | -f filename", argv[0]);
exit(1);
}
}
if (!yyparse()) { if (!yyparse()) {
printf("Error\n"); printf("Error\n");
return 1; return 1;
} }
println(yylval);
char *line=0;
size_t line_max=0;
char *line=0;
size_t line_max=0;
ssize_t line_len=0; ssize_t line_len=0;
Symbol *start= intern("start");
if (!start->rule) perror("no start rule");
while((line_len=getline(&line,&line_max,stdin))>=0){
if(line_len>0 && line[line_len-1]=='\n'){
Node *startRule= intern("start")->rule;
if (!startRule) {
fatal("no start rule");
return 1;
}
while ((line_len=getline(&line,&line_max,stdin))>=0) {
if (line_len>0 && line[line_len-1]=='\n') {
line[line_len-1]=0; line[line_len-1]=0;
} }
initInputBuffer(inputBuffer,line); initInputBuffer(inputBuffer,line);
if (!execute(yylval, inputBuffer) || !atEnd(inputBuffer)){
if (!execute(startRule, inputBuffer) || !atEnd(inputBuffer)) {
printf("no match, current position : %i\n", getPosition(inputBuffer)); printf("no match, current position : %i\n", getPosition(inputBuffer));
}
else{
}
else {
printf("match, current position : %i\n", getPosition(inputBuffer)); printf("match, current position : %i\n", getPosition(inputBuffer));
}// 0 => no match, 1 => match
} // 0 => no match, 1 => match
} }
return 0; return 0;

Loading…
取消
儲存