Mehrere Aufrufe mit Peg / Leg Parser

Müssen Sie Ihre Parser mehrmals während der Ausführung eines einzigen Programms aufrufen? Dieser kleine Artikel zeigt ihnen wie sie dies machen. Das ist ein C Codeschnipsel der von Leg generiert ist, sie werden bemerken das eine einfache bedingung für yybuflen erstellt wird, was sich als Fehler herausstellt. Solange man nicht einen reset auf 0 macht kann der parser auch nicht X mal laufen.


YY_PARSE(int) YYPARSEFROM(yyrule yystart)
{
int yyok;
if (!yybuflen)
{
yybuflen= 1024;
yybuf= malloc(yybuflen);
yytextlen= 1024;
yytext= malloc(yytextlen);
yythunkslen= 32;
yythunks= malloc(sizeof(yythunk) * yythunkslen);
yyvalslen= 32;
yyvals= malloc(sizeof(YYSTYPE) * yyvalslen);
yybegin= yyend= yypos= yylimit= yythunkpos= 0;
}


Unten ist ein Leg Parser für YAMP (ziemliches alpha Stadion da der Code noch viel wechselt), aber es ist eine gute Referenz:
%{
#include “yamp.h”
#define YYSTYPE char *
#define YYPARSE yy_selectorparse
#define YYPARSEFROM yy_selectorparsefrom
// #define YY_DEBUG 1

#define YY_INPUT(buf, result, max_size) { <br />int yyc = input++; <br />result = (EOF == yyc) ? 0 : ((buf) = yyc, 1); <br />yyprintf((stderr, “<%c>”, yyc)); <br />}

#define SELECTOR_PARSE_ERROR YA_ERROR(“Selector parse error near ‘%s’\n”, yytext)

#define SELECT(N) SELECT2(N, NULL)

#define SELECT2(N, …) <br />for (i = 0; i < parser->selected->nelements; ++i) <br />if (parser->selected->elements[i] && <br />!yaElementselector##N (parser->selected->elements[i], VA_ARGS)) <br />parser->selected->elements[i] = NULL;

#define SELECT_CHILDREN <br />parser->selected = yaElementArray_get_children(parser->selected);

#define SELECT_DESCENDANTS <br />parser->selected = yaElementArray_get_descendants(parser->selected);

#define SELECT_ADJACENT_SIBlING <br />parser->selected = yaElementArray_get_next_sibling(parser->selected);

#define SELECT_GENERAL_SIBlING <br />parser->selected = yaElementArray_get_next_siblings(parser->selected);

static yaSelectorParser *parser = NULL;
static char input;
static int i;
%}

main = Selectors
| s
| < (!EOS .)+ > { SELECTOR_PARSE_ERROR }

Selectors = Selector
( - ‘,’ -
Selector
)


Selector = Simple (Combinator Simple)

Combinator = - ‘+’ - { SELECT_ADJACENT_SIBlING }
| - ‘~’ - { SELECT_GENERAL_SIBlING }
| - ‘>’ - { SELECT_CHILDREN }
| s { SELECT_DESCENDANTS }

Simple = n:Id { SELECT2(name, n) }
Literal

| Literal+

Literal = ‘
| Hash
| Class
| Attribute
| Negate
| Pseudo
| State
| Input

Hash = ‘#’ n:Id { SELECT2(attr_val, “id”, n) }

Class = ‘.’ n:Id { SELECT2(attr_contains_word, “class”, n) }

Attribute = ‘[’ n:Id { SELECT2(attr, n) }
( ‘=’ v:Value { SELECT2(attr_val, n, v) }
| ‘~=’ v:Value { SELECT2(attr_contains_word, n, v) }
| ‘^=’ v:Value { SELECT2(attr_starts_with, n, v) }
| ‘$=’ v:Value { SELECT2(attr_ends_with, n, v) }
| ‘
=’ v:Value { SELECT2(attr_contains, n, v) }
)? ‘]’

Negate = ‘:not(’ - Simple - ‘)’

Pseudo = ‘:’
( ‘root’ { SELECT(root) }
| ‘nth-child(’ - n:Number - ‘)’ { SELECT2(nth_child, (int) n) }
| ‘nth-last-child(’ - n:Number - ‘)’
| ‘nth-of-type(’ - n:Number - ‘)’ { SELECT2(nth_of_type, (int) n) }
| ‘nth-last-of-type(’ - n:Number - ‘)’
| ‘first-child’ { SELECT(first_child) }
| ‘last-child’ { SELECT(last_child) }
| ‘first-of-type’ { SELECT(first_of_type) }
| ‘last-of-type’ { SELECT(last_of_type) }
| ‘only-of-type’ { SELECT(only_of_type) }
| ‘only-child’ { SELECT(only_child) }
| ‘even’ { SELECT(even) }
| ‘odd’ { SELECT(odd) }
| ‘empty-children’ { SELECT(empty_children) }
| ‘empty-text’ { SELECT(empty_text) }
| ‘empty’ { SELECT(empty) }
| ‘contains(’ - v:Value - ‘)’ { SELECT2(contains, v) }
)

State = ‘:’ n:Boolean { SELECT2(attr_val, n, n) }

Input = ‘:’ n:Type { SELECT2(attrval, “type”, n) }

Boolean = < ( ‘checked’ | ‘selected’ | ‘disabled’ ) > { $$ = strdup(yytext) }

Type = < ( ‘checkbox’ | ‘image’ | ‘reset’ | ‘button’ | ‘file’ | ‘text’ | ‘password’ | ‘radio’ | ‘submit’ ) > { $$ = strdup(yytext) }

Value = Id | String

String = ‘“’ < (!‘“’ .)* > ‘“’ { $$ = strdup(yytext) }
| ‘\” < (!’\” .)* > ‘\” { $$ = strdup(yytext) }

Number = < [0-9]+ > { $$ = (char *) atoi(yytext) }
Id = < ([a-zA-Z0-9
] | ‘-’)+ > { $$ = strdup(yytext) }
EOS = ‘\0’
s = [ \t]+
- = [ \t]*

%%

yaSelectorParser *
yaSelectorParser_parse(char *selector, yaElementArray *array) {
if (parser) free(parser), yybuflen = 0;
parser = yaSelectorParser_new(selector, array);
input = strdup(selector);
SELECT_DESCENDANTS;
yaElementArray_merge(parser->selected, array);
while (YYPARSE());
return parser;
}

comments powered by Disqus