update phase2

This commit is contained in:
Kelvin Sherlock 2016-01-30 12:44:42 -05:00
parent 3e5a128d8e
commit bc2a530355
5 changed files with 1328 additions and 14 deletions

35
lemon_base.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef __lemon_base_h__
#define __lemon_base_h__
#include <cstdio>
template<class TokenType>
class lemon_base {
public:
typedef TokenType token_type;
virtual ~lemon_base() = default;
#if 0
virtual typename std::enable_if<std::is_copy_constructible<TokenType>::value, void>::type
parse(int yymajor, const TokenType &yyminor) = 0;
#endif
//virtual typename std::enable_if<std::is_move_constructible<TokenType>::value, void>::type
virtual void parse(int yymajor, TokenType &&yyminor) = 0;
virtual void trace(FILE *, const char *) = 0;
protected:
virtual void parse_accept() {}
virtual void parse_failure() {}
virtual void stack_overflow() {}
virtual void syntax_error(int yymajor, TokenType &yyminor) {}
lemon_base() {}
private:
lemon_base(const lemon_base &) = delete;
lemon_base(lemon_base &&) = delete;
lemon_base &operator=(const lemon_base &) = delete;
lemon_base &operator=(lemon_base &&) = delete;
};
#endif

1063
lempar.cxx Normal file

File diff suppressed because it is too large Load Diff

156
phase2-parser.lemon Normal file
View File

@ -0,0 +1,156 @@
/*
>, < redirection is handled later, after environment expansion.
(also, redirection can be in the middle of a command.)
*/
%include {
#include "phase2.h"
#include "command.h"
#define LEMON_SUPER phase2_parser
}
%code {
std::unique_ptr<phase2_parser> phase2_parser::make() {
return std::make_unique<yypParser>();
}
}
%left PIPE_PIPE AMP_AMP.
%left PIPE.
%token_type {std::string}
%default_type {command_ptr}
%type start {void}
%type opt_command_list {void}
%type command_list {void}
/* these are put into a queue for immmediate execution */
start ::= opt_command_list.
opt_command_list ::= .
opt_command_list ::= command_list.
command_list ::= command_list opt_command(C) sep . {
if (C) command_queue.emplace_back(std::move(C));
}
command_list ::= opt_command(C) sep. {
if (C) command_queue.emplace_back(std::move(C));
}
/*
compound_list is identical to command_list, but it is not executed immediately.
*/
%type opt_compound_list { command_ptr_vector }
opt_compound_list(RV) ::= . { /* RV */ }
opt_compound_list(RV) ::= compound_list(L). { RV = std::move(L); }
%type compound_list { command_ptr_vector }
compound_list(RV) ::= compound_list(L) opt_command(C) sep . {
RV = std::move(L);
if (C) RV.emplace_back(std::move(C));
}
compound_list(RV) ::= opt_command(C) sep. {
if (C) RV.emplace_back(std::move(C));
}
sep ::= SEMI.
sep ::= NL.
%type opt_command { command_ptr }
opt_command(RV) ::= command(C). { RV = std::move(C); }
opt_command(RV) ::= . { /* RV */ }
%type command { command_ptr }
command(RV) ::= command(L) PIPE_PIPE opt_nl command(R). {
RV = std::make_unique<or_command>(std::move(L), std::move(R));
}
command(RV) ::= command(L) AMP_AMP opt_nl command(R). {
RV = std::make_unique<and_command>(std::move(L), std::move(R));
}
/*
command(RV) ::= command PIPE opt_nl command. {
RV = std::make_unique<pipe_command>(std::move(L), std::move(R));
}
*/
command(RV) ::= term(T). { RV = std::move(T); }
term(RV) ::= COMMAND(C). { RV = std::make_unique<simple_command>(std::move(C)); }
term(RV) ::= EVALUATE(C). { RV = std::make_unique<simple_command>(std::move(C)); }
term(RV) ::= if_command(C). { RV = std::move(C); }
term(RV) ::= begin_command(C). { RV = std::move(C); }
term(RV) ::= paren_command(C). { RV = std::move(C); }
paren_command(RV) ::= LPAREN(T) opt_compound_list(L) RPAREN(E). {
RV = std::make_unique<begin_command>(@T, std::move(L), std::move(E));
}
begin_command(RV) ::= BEGIN(T) sep opt_compound_list(L) END(E). {
RV = std::make_unique<begin_command>(@T, std::move(L), std::move(E));
}
if_command(RV) ::= IF(I) sep opt_compound_list(L) END(E). {
if_command::clause_vector_type v;
v.emplace_back(std::make_unique<if_else_clause>(IF, std::move(L), std::move(I)));
RV = std::make_unique<if_command>(
std::move(v),
std::move(E)
);
}
if_command(RV) ::= IF(I) sep opt_compound_list(L) else_command(EC) END(E). {
if_command::clause_vector_type v;
v.emplace_back(std::make_unique<if_else_clause>(IF, std::move(L), std::move(I)));
for(auto &c : EC) { v.emplace_back(std::move(c)); }
RV = std::make_unique<if_command>(
std::move(v), std::move(E));
}
%token_class else ELSE_IF ELSE.
%type else_command { if_command::clause_vector_type }
else_command(RV) ::= else(E) sep opt_compound_list(L). {
RV.emplace_back(std::make_unique<if_else_clause>(@E, std::move(L), std::move(E)));
}
/*
else_command(RV) ::= ELSE_IF(E) sep opt_compound_list(L). {
RV.emplace_back(std::make_unique<if_else_clause>(@E, std::move(L), std::move(E)));
}
*/
else_command(RV) ::= else_command(EC) else(E) sep opt_compound_list(L). {
RV = std::move(EC);
RV.emplace_back(std::make_unique<if_else_clause>(@E, std::move(L), std::move(E)));
}
/*
else_command(RV) ::= else_command(EC) ELSE_IF(E) sep opt_compound_list(L). {
RV = std::move(EC);
RV.emplace_back(std::make_unique<else_command>(std::move(E), std::move(L)));
}
*/
opt_nl ::= .
opt_nl ::= nl.
nl ::= NL.
nl ::= nl NL.

View File

@ -7,29 +7,65 @@
#include <functional>
#include <memory>
typedef std::unique_ptr<struct command> command_ptr;
typedef std::vector<command_ptr> command_ptr_vector;
#include "command.h"
#include "lemon_base.h"
//typedef std::unique_ptr<struct command> command_ptr;
//typedef std::vector<command_ptr> command_ptr_vector;
class phase2_parser : public lemon_base<std::string> {
public:
static std::unique_ptr<phase2_parser> make();
virtual void syntax_error(int yymajor, std::string &yyminor) override final;
virtual void parse_accept() override final;
virtual void parse_failure() override final;
private:
friend class phase2;
phase2_parser(const phase2_parser &) = delete;
phase2_parser(phase2_parser &&) = delete;
phase2_parser& operator=(const phase2_parser &) = delete;
phase2_parser& operator=(phase2_parser &&) = delete;
protected:
// these need to be accessible to the lemon-generated parser.
phase2_parser() = default;
command_ptr_vector command_queue;
bool error = false;
};
class phase2 {
public:
typedef std::function<void(command_ptr &&)> pipe_function;
phase2();
phase2(const phase2 &) = delete;
phase2(phase2 &&) = default;
phase2 & operator=(const phase2 &) = delete;
phase2 & operator=(phase2 &&) = default;
void process(const std::string &line);
void finish();
virtual void syntax_error();
virtual void parse_accept();
virtual void parse(int, std::string &&);
phase2 &operator >>=(pipe_function f) { pipe_to = f; return *this; }
private:
void parse(int, std::string &&);
std::unique_ptr<phase2_parser> parser;
std::string scratch;
int type = 0;
bool error = false;
bool immediate = false;
pipe_function pipe_to;
@ -38,7 +74,8 @@ private:
void classify();
void exec();
command_ptr_vector command_queue;
};
#endif

View File

@ -4,7 +4,7 @@
*
*/
#include "mpw-shell-grammar.h"
#include "phase2-parser.h"
#include "phase2.h"
#include "command.h"
@ -85,7 +85,6 @@
}%%
namespace {
%% machine classify;
%% write data;
@ -167,16 +166,40 @@ void phase2::finish() {
exec();
}
void phase2::parse(int token, std::string &&s) {
if (parser) parser->parse(token, std::move(s));
}
void phase2::exec() {
if (pipe_to) {
for (auto &p : command_queue) {
if (pipe_to && parser) {
for (auto &p : parser->command_queue) {
if (p) {
pipe_to(std::move(p));
}
}
command_queue.clear();
parser->command_queue.clear();
}
}
phase2::phase2() {
parser = std::move(phase2_parser::make());
}
#pragma mark - phase2_parser
void phase2_parser::parse_accept() {
error = false;
}
void phase2_parser::parse_failure() {
error = false;
}
void phase2_parser::syntax_error(int yymajor, std::string &yyminor) {
if (!error)
fprintf(stderr, "### Parse error near %s\n", yyminor.c_str());
error = true;
}