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.

128 lignes
2.6 KiB

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int digitValue(int c)
{
switch (c) {
case '0'...'9': return c - '0';
case 'A'...'Z': return c - 'A' + 10;
case 'a'...'z': return c - 'a' + 10;
}
return 666;
}
int isRadix(int r, int c)
{
return digitValue(c) < r;
}
int unescapedCharacter(char *cp, char **ep)
{
int c= 0;
c= *cp++;
if ('\\' == c) {
c= *cp++;
switch (c) {
case 'n': c= 10; break;
case 'a': c= 7; break;
case 'b': c= 8; break;
case 'e': c= 27; break;
case 'f': c= 12; break;
case 'r': c= 13; break;
case 't': c= 9; break;
case 'v': c= 1; break;
case '\\': c= '\\'; break;
case ']': c= ']'; break;
case '-': c= '-'; break;
case '0'...'7': {
c -= '0'; // c is now the value of the digit that represented it
if (isRadix(8, *cp)) c= c * 8 + *cp++ - '0';
if (isRadix(8, *cp)) c= c * 8 + *cp++ - '0';
break;
}
case 'x': {
char *op= cp;
c= 0;
if (isRadix(16, *cp)) {
c= c * 16 + digitValue(*cp++);
if (isRadix(16, *cp)) {
c= c * 16 + digitValue(*cp++);
break;
}
}
fprintf(stderr, "illegal hexadecimal escape: \\x%.2s\n", op);
break;
}
default:
fprintf(stderr, "unusual escape: \\%c\n", c);
break;
}
}
if (ep) *ep= cp;
return c;
}
char *classify(char *spec)
{
char *class= calloc(1, 32);
int negated= 0;
if ('^' == *spec) ++negated, ++spec;
int prevChar= 0;
while (*spec) {
if ('-' == *spec && prevChar && spec[1]) {
++spec;
int thisChar= unescapedCharacter(spec, &spec);
if (thisChar < prevChar) {
fprintf(stderr, "range is backwards: \\x%x-\\x%x\n", prevChar, thisChar);
int tmp= prevChar;
prevChar= thisChar;
thisChar= tmp;
}
for (int i= prevChar; i <= thisChar; ++i)
setBit(class, i);
prevChar= 0;
continue;
}
prevChar= *spec;
setBit(class, unescapedCharacter(spec, &spec));
}
if (negated)
for (int i= 0; i < 32; ++i)
class[i] ^= 255; // invert all bits in the class
return class;
}
#ifdef TESTING_CLASS_C
int main()
{
char *line=0;
size_t line_max=0;
ssize_t line_len=0;
char a='a';
printf("%i\n",(int)a);
printf("%s",classify("a"));
while ((line_len= getline(&line,&line_max,stdin)) >= 0) {
if (line_len>0 && line[line_len-1]=='\n') {
line[line_len-1]=0;
}
char *class= classify(line);
for (int i= 0; i < 256; ++i)
if (testBit(class, i))
printf("%02x is set\n", i);
}
return 0;
}
#endif