static double token_num;
static void NONRET parse_error(const char *msg, ...);
-static void parse_commands(list<cmd *> *cmds);
+static void parse_commands(list<cmd *> &cmds);
static void parse_error(const char *msg, ...)
{
{
while (*in_pos >= 'A' && *in_pos <= 'Z' ||
*in_pos >= 'a' && *in_pos <= 'z' ||
- *in_pos >= '0' && *in_pos <= '9')
+ *in_pos >= '0' && *in_pos <= '9' ||
+ *in_pos == '_')
token += *in_pos++;
return TOK_IDENT;
}
/*** Argument types ***/
+class arg_int : public arg_val {
+ int val;
+public:
+ arg_int(int x) { val = x; }
+ bool given() { return true; }
+ int as_int(int def UNUSED) { return val; }
+ string dump() { return "<int> " + to_string(val); }
+};
+
class arg_double : public arg_val {
double val;
public:
- bool given() { return true; }
- explicit operator double () { return val; }
arg_double(double x) { val = x; }
- string dump() { return to_string(val); }
+ bool given() { return true; }
+ double as_double(double def UNUSED) { return val; }
+ string dump() { return "<double> " + to_string(val); }
};
class arg_string : public arg_val {
string val;
public:
- bool given() { return true; }
- explicit operator string () { return val; }
arg_string(string x) { val = x; }
- string dump() { return '"' + val + '"'; }
+ bool given() { return true; }
+ const string as_string(string def UNUSED) { return val; }
+ string dump() { return "<string> \"" + val + '"'; }
};
static arg_val null_arg;
pipeline_branch *pb = new pipeline_branch;
pp->branches.push_back(pb);
+ token_type t;
for (;;)
{
- token_type t = next_token();
- if (t == TOK_CLOSE_BRACE || t == TOK_END)
- parse_error("Premature end of pipeline");
- if (t == TOK_COLON)
+ t = next_token();
+ if (t == TOK_END)
+ parse_error("Missing close brace");
+ if (t == TOK_CLOSE_BRACE || t == TOK_COLON || t == TOK_COMMA)
break;
- if (pb->selectors.size())
- {
- if (t != TOK_COMMA)
- parse_error("Invalid pipeline selector");
- t = next_token();
- if (t == TOK_CLOSE_BRACE || t == TOK_END)
- parse_error("Premature end of pipeline");
- }
-
pipeline_selector ps;
if (t != TOK_NUMBER)
parse_error("Pipeline selectors must start with a number");
pb->selectors.push_back(ps);
}
- parse_commands(&pb->commands);
+ if (t == TOK_COLON)
+ parse_commands(pb->commands);
+ else
+ return_token();
}
c->pipe = pp;
parse_error("Parameter %s must be a string", adef->name);
val = new arg_string(token);
break;
+ case AT_INT:
+ t = next_token();
+ if (t != TOK_NUMBER || !token_is_int())
+ parse_error("Parameter %s must be an integer", adef->name);
+ val = new arg_int((int) token_num);
+ break;
case AT_DOUBLE:
t = next_token();
if (t != TOK_NUMBER)
}
}
-static void debug_cmds(list<cmd *> *cmds)
+static void debug_cmds(list<cmd *> &cmds)
{
- for (auto c: *cmds)
+ for (auto c: cmds)
debug_cmd(c);
}
return c;
}
-static void parse_commands(list<cmd *> *cmds)
+static void parse_commands(list<cmd *> &cmds)
{
for (;;)
{
}
cmd *c = parse_cmd();
- cmds->push_back(c);
+ cmds.push_back(c);
}
}
-void parse(const char *in, list<cmd *> *cmds)
+static void instantiate(list<cmd *> &cmds)
+{
+ for (auto c: cmds)
+ {
+ c->exec = c->def->constructor(c);
+ if (c->pipe)
+ {
+ for (auto pb: c->pipe->branches)
+ instantiate(pb->commands);
+ }
+ }
+}
+
+void parse(const char *in, list<cmd *> &cmds)
{
in_pos = in;
parse_commands(cmds);
parse_error("Extra tokens after commands");
debug_cmds(cmds);
+ instantiate(cmds);
+}
+
+void help()
+{
+ for (int i=0; cmd_table[i].name; i++)
+ {
+ const cmd_def *def = &cmd_table[i];
+ printf("%s\n", def->name);
+
+ const arg_def *arg = def->arg_defs;
+ static const char * const type_names[] = {
+ "string", "int", "double", "dimen"
+ };
+ while (arg->name)
+ {
+ printf("\t%s (%s)%s%s\n",
+ arg->name,
+ type_names[arg->type & AT_TYPE_MASK],
+ (arg->type & AT_MANDATORY) ? " [mandatory]" : "",
+ (arg->type & AT_POSITIONAL) ? " [positional]" : "");
+ arg++;
+ }
+
+ if (def->has_pipeline)
+ printf("\t{ pipeline }\n");
+ }
}