mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-12-28 09:29:57 +00:00
update phase2
This commit is contained in:
parent
3e5a128d8e
commit
bc2a530355
35
lemon_base.h
Normal file
35
lemon_base.h
Normal 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
1063
lempar.cxx
Normal file
File diff suppressed because it is too large
Load Diff
156
phase2-parser.lemon
Normal file
156
phase2-parser.lemon
Normal 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.
|
||||
|
55
phase2.h
55
phase2.h
@ -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
|
||||
|
33
phase2.rl
33
phase2.rl
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user