#include <stdlib.h>
#include <ctype.h>
/*
commands:
EOF
|
command commands
command:
command_begin string command_end
string:
anything but command_end
command_begin:
QUOTE
command_end:
QUOTE SEMICOLON
|
QUOTE EOF
*/
struct iss_t
{
char* s;
char* g;
};
typedef struct iss_t iss_t;
char iss_get_char( iss_t* self )
{
if ( !*self->g )
return 0;
return *self->g++;
}
struct wschar_t
{
char c;
char s[ 1024 ];
};
typedef struct wschar_t wschar_t;
char iss_get_wschar( iss_t* self, wschar_t* r )
{
char* p = r->s;
while ( isspace( *p
++ = r
->c
= iss_get_char
( self
) ) ) ;
*p = 0;
return r->c;
}
char iss_peek_wschar( iss_t* self )
{
char* savedg = self->g;
wschar_t t;
iss_get_wschar( self, &t );
self->g = savedg;
return t.c;
}
enum token_t
{
tk_done,
tk_beg,
tk_end,
tk_rest
};
typedef enum token_t token_t;
struct parser_t
{
iss_t* iss;
wschar_t wschar;
token_t token;
};
typedef struct parser_t parser_t;
token_t parser_get_token( parser_t* self )
{
iss_get_wschar( self->iss, &self->wschar );
// if done
if ( self->wschar.c == 0 )
return self->token = tk_done;
// not a quote
if ( self->wschar.c != '\"' )
return self->token = tk_rest;
// it is quote: check the next token
switch ( iss_peek_wschar( self->iss ) )
{
case 0:
case ';':
iss_get_wschar( self->iss, &self->wschar ); // eat
return self->token = tk_end;
default:
return self->token = tk_beg;
}
}
int parser_command( parser_t* self )
{
if ( self->token != tk_beg )
{
printf( "command begin expected" ); return -1;
}
while ( parser_get_token( self ) == tk_rest || self->token == tk_beg )
if ( self->token != tk_end )
{
printf( "command end expected" ); return -1;
}
return 0;
}
void parser_commands( parser_t* self )
{
while ( 1 )
{
switch ( parser_get_token( self ) )
{
case tk_done:
return;
default:
if ( parser_command( self ) < 0 )
return;
};
};
}
int main()
{
char* s = "\"command1\"; \"sleep 30; command2 -a ; command3\"; \"command4=\"MyTest\"\"";
iss_t iss = { s, s };
parser_t parser = { &iss };
parser_commands( &parser );
return 0;
}