phase parsing improvements

This commit is contained in:
Kelvin Sherlock 2016-01-31 00:41:02 -05:00
parent 1b4eb0f2bc
commit 1219a40d07
3 changed files with 92 additions and 9 deletions

View File

@ -24,11 +24,19 @@ public:
void reset(); void reset();
//template<class F>
//phase1 &operator >>= (F &&f) { pipe_to = pipe_function(f); return *this; }
phase1 &operator >>= (pipe_function f) { pipe_to = f; return *this; } phase1 &operator >>= (pipe_function f) { pipe_to = f; return *this; }
template<class F>
phase1 &operator >>= (F &f) {
using std::placeholders::_1;
pipe_to = std::bind(&F::operator(), &f, _1);
return *this;
}
private: private:
std::string scratch; std::string scratch;
pipe_function pipe_to; pipe_function pipe_to;

View File

@ -52,11 +52,19 @@ public:
phase2 & operator=(const phase2 &) = delete; phase2 & operator=(const phase2 &) = delete;
phase2 & operator=(phase2 &&) = default; phase2 & operator=(phase2 &&) = default;
void operator()(const std::string &line) { process(line); }
void process(const std::string &line); void process(const std::string &line);
void finish(); void finish();
phase2 &operator >>=(pipe_function f) { pipe_to = f; return *this; } phase2 &operator >>=(pipe_function f) { pipe_to = f; return *this; }
template<class F>
phase2 &operator >>= (F &f) {
using std::placeholders::_1;
pipe_to = std::bind(&F::operator(), &f, _1);
return *this;
}
private: private:
void parse(int, std::string &&); void parse(int, std::string &&);

View File

@ -14,9 +14,51 @@
action not_special { !special() } action not_special { !special() }
escape = 0xb6;
ws = [ \t]; ws = [ \t];
escape_seq =
escape any
;
sstring =
[']
( (any-[']) )*
[']
$err{
throw std::runtime_error("### MPW Shell - 's must occur in pairs.");
}
;
vstring =
[{]
( (any-[{]) )*
[}]
$err{
throw std::runtime_error("### MPW Shell - 's must occur in pairs.");
}
;
# double-quoted string.
dstring =
["]
(
escape_seq
|
(any-escape-["])
)*
["]
$err{
throw std::runtime_error("### MPW Shell - \"s must occur in pairs.");
}
;
main := |* main := |*
'||' when not_special => { '||' when not_special => {
flush(); flush();
parse(PIPE_PIPE, std::string(ts, te)); parse(PIPE_PIPE, std::string(ts, te));
@ -27,23 +69,42 @@
parse(AMP_AMP, std::string(ts, te)); parse(AMP_AMP, std::string(ts, te));
}; };
'(' when not_special => {
# ( evaluate (1+2) ) is lparen, eval, rparen.
# need to balance parens here and terminate a special token when it goes negative.
'(' => {
if (special()) {
pcount++;
scratch.push_back(fc);
} else {
flush(); flush();
parse(LPAREN, std::string(ts, te)); parse(LPAREN, std::string(ts, te));
}
}; };
# ) may include redirection so start a new token but don't parse it yet. ')' => {
')' when not_special => { if (special() && pcount-- > 0) scratch.push_back(fc);
else {
flush(); flush();
scratch.push_back(fc); scratch.push_back(fc);
type = RPAREN; type = RPAREN;
}
}; };
# todo -- also add in strings and escapes.
';' => { flush(); parse(SEMI, ";"); }; ';' => { flush(); parse(SEMI, ";"); };
ws => { if (!scratch.empty()) scratch.push_back(fc); }; ws => { if (!scratch.empty()) scratch.push_back(fc); };
any => { scratch.push_back(fc); };
sstring => { scratch.append(ts, te); };
dstring => { scratch.append(ts, te); };
vstring => { scratch.append(ts, te); };
escape_seq => { scratch.append(ts, te); };
(any-escape-['"{]) => { scratch.push_back(fc); };
*|; *|;
}%% }%%
@ -80,7 +141,7 @@
BEGIN %eof{ type = BEGIN; return; }; BEGIN %eof{ type = BEGIN; return; };
BEGIN ws => { type = BEGIN; return; }; BEGIN ws => { type = BEGIN; return; };
')' => { type = LPAREN; return; }; '(' => { type = LPAREN; return; };
*|; *|;
}%% }%%
@ -106,6 +167,7 @@ void phase2::flush() {
scratch.clear(); scratch.clear();
} }
/* slightly wrong since whitespace is needed for it to be special. */
bool phase2::special() { bool phase2::special() {
if (!type) classify(); if (!type) classify();
@ -140,6 +202,7 @@ void phase2::classify() {
void phase2::process(const std::string &line) { void phase2::process(const std::string &line) {
int pcount = 0; // special form parens cannot cross lines.
int cs; int cs;
int act; int act;
@ -156,6 +219,8 @@ void phase2::process(const std::string &line) {
%% write exec; %% write exec;
flush(); flush();
// 2 NLs to make the stack reduce. harmless if in a multi-line constuct.
parse(NL, "");
parse(NL, ""); parse(NL, "");
exec(); exec();
@ -185,6 +250,8 @@ void phase2::exec() {
phase2::phase2() { phase2::phase2() {
parser = std::move(phase2_parser::make()); parser = std::move(phase2_parser::make());
//parser->trace(stdout, " ] ");
} }
#pragma mark - phase2_parser #pragma mark - phase2_parser