Dynamic PEG for interpreted languages.
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

128 righe
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