79 lines
1.5 KiB
C
79 lines
1.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
/* BNFesque
|
|
rangelist := (range | number) [',' rangelist]
|
|
range := number '-' number */
|
|
|
|
int get_list(const char *, char **);
|
|
int get_rnge(const char *, char **);
|
|
|
|
/* parser only parses; what to do with parsed items is up to
|
|
* the add_number and and_range functions */
|
|
void add_number(int x);
|
|
int add_range(int x, int y);
|
|
|
|
#define skip_space while(isspace(*s)) s++
|
|
#define get_number(x, s, e) (x = strtol(s, e, 10), *e != s)
|
|
int get_list(const char *s, char **e)
|
|
{
|
|
int x;
|
|
while (1) {
|
|
skip_space;
|
|
if (!get_rnge(s, e) && !get_number(x, s, e)) break;
|
|
s = *e;
|
|
|
|
skip_space;
|
|
if ((*s) == '\0') { putchar('\n'); return 1; }
|
|
if ((*s) == ',') { s++; continue; }
|
|
break;
|
|
}
|
|
*(const char **)e = s;
|
|
printf("\nSyntax error at %s\n", s);
|
|
return 0;
|
|
}
|
|
|
|
int get_rnge(const char *s, char **e)
|
|
{
|
|
int x, y;
|
|
char *ee;
|
|
if (!get_number(x, s, &ee)) return 0;
|
|
s = ee;
|
|
|
|
skip_space;
|
|
if (*s != '-') {
|
|
*(const char **)e = s;
|
|
return 0;
|
|
}
|
|
s++;
|
|
if(!get_number(y, s, e)) return 0;
|
|
return add_range(x, y);
|
|
}
|
|
|
|
void add_number(int x)
|
|
{
|
|
printf("%d ", x);
|
|
}
|
|
|
|
int add_range(int x, int y)
|
|
{
|
|
if (y <= x) return 0;
|
|
while (x <= y) printf("%d ", x++);
|
|
return 1;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
char *end;
|
|
|
|
/* this is correct */
|
|
if (get_list("-6,-3--1,3-5,7-11,14,15,17-20", &end)) puts("Ok");
|
|
|
|
/* this is not. note the subtle error: "-6 -3" is parsed
|
|
* as range(-6, 3), so synax error comes after that */
|
|
get_list("-6 -3--1,3-5,7-11,14,15,17-20", &end);
|
|
|
|
return 0;
|
|
}
|