-
Notifications
You must be signed in to change notification settings - Fork 48
Home
Filipe Funenga edited this page Jun 5, 2013
·
27 revisions
Normalize vocabulary to correspond the upcoming docopt.py v0.7.0.
Element should be Pattern:
Pattern
ChildPattern # a better name??: TerminalPattern or LeafPattern
Option
Argument
Command
ParentPattern # a better name??: CollectionPattern
Required
Optional
AnyOptions
OneOrMore
Either
How Pattern C-struct could look like:
typedef {
// probably more conventional to have enum
// all UPPER CASE
enum {
OPTION,
ARGUMENT,
COMMAND,
REQUIRED,
OPTIONAL,
ONEORMORE,
EITHER,
NONE,
} type;
union {
Option option;
Argument argument;
Command command;
// maybe having a single container for
// required/optional/oneoremore/either,
// since they all hold the same kind of data.
Container container;
} payload;
} Pattern;
typedef struct {
// in Python these are `short` and `long`,
// but these are reserved in C
const char *oshort; // maybe *flag?
const char *olong; // maybe *full?
bool argcount; // number of arguments 0 or 1
bool value; // value if argcount is 0
char *argument; // value if argcount is 1
// maybe instead of having `value` and `argument`
// we could have just `char *value` and treat it
// as NULL/non-NULL for true/false (if argcount == 0)
// and as value/no-value when argcount == 1?
// I wonder, would that be portable:
// char *value = true;
//
// Oh, it is actually more complicated than that.
// In Python, Option's value could be either:
// * True/False, if it's a single option without argument
// * a number, if it's an option (w/o argument) that could be repeated
// * a string, if it's an option with argument non-repeated
// * array of strings, if it's an option with argument, repeated
// Well:
// repeatable | no yes
// -----------+----------------------
// argcount |
// 0 | bool int
// 1 | char* char**
//
// So we need to handle all these cases.
//
// a) Maybe go full type-unsafe and declare it as char**
// and use it as bool/char*/int by casting? :-)
//
// b) Another variant would be to have a union of these types.
//
// c) Yet another would be to store all these in the same struct.
} Option;
typedef struct {
char *name;
bool repeating; // Maybe int count; instead?
// (to explicitly state the length of **array).
char *value; // Maybe get rid of this in favor of
// just having 1 item in **array.
char **array; // I can think of 2 ways how to allocate this array.
// 1. It could be statically allocated
// to fit, say, max 32 elements, and then each
// pointer in it will point to an item in argv.
// 2. Make it point to (a part of) argv directly
// and then use `count` to see how long it is.
} Argument;
typedef struct {
char *name;
// Command's value could be either True/False in Python
// or the number of times the command was mentioned.
// We could use the fact that 0 is falsy in C, and
// declare it simply as int:
int value; // Maybe int count; instead?
} Command;
// In Python version required/optional/etc hold an array
// called `children` which is an array of all child nodes.
// Since we don't want to allocate these arrays dynamically
// or overallocate them statically (by allocating, say
// 32 items "just in case"), I was thinking of 2 variants:
//
// 1. Use linked list like the following:
typedef struct {
Pattern *pattern;
Container *next;
} Container;
// and transform patterns in Python into a linked list form:
//
// Required(a, b, c) into Required(a, Required(b, Required(c, NULL)))
//
// 2. Another way could be to *generate* code for each struct. I.e. if the
// pattern is `usage: prog [<this> <that>] (-a | -b | -c)` or in Python terms:
// Required(Optional(<this>, <that>), Either(-a, -b, -c))
//
// Then just generate precisely these containers:
//
typedef struct {
Pattern patterns[2];
} ContainerRequired1;
typedef struct {
Pattern patterns[2];
} ContainerOptional1;
typedef struct {
Pattern patterns[3];
} ContainerEither1;