mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-12-29 00:30: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 <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
typedef std::unique_ptr<struct command> command_ptr;
|
#include "command.h"
|
||||||
typedef std::vector<command_ptr> command_ptr_vector;
|
#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 {
|
class phase2 {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(command_ptr &&)> pipe_function;
|
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 process(const std::string &line);
|
||||||
void finish();
|
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; }
|
phase2 &operator >>=(pipe_function f) { pipe_to = f; return *this; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void parse(int, std::string &&);
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<phase2_parser> parser;
|
||||||
|
|
||||||
std::string scratch;
|
std::string scratch;
|
||||||
int type = 0;
|
int type = 0;
|
||||||
bool error = false;
|
|
||||||
bool immediate = false;
|
|
||||||
|
|
||||||
pipe_function pipe_to;
|
pipe_function pipe_to;
|
||||||
|
|
||||||
@ -38,7 +74,8 @@ private:
|
|||||||
void classify();
|
void classify();
|
||||||
void exec();
|
void exec();
|
||||||
|
|
||||||
command_ptr_vector command_queue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
33
phase2.rl
33
phase2.rl
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mpw-shell-grammar.h"
|
#include "phase2-parser.h"
|
||||||
#include "phase2.h"
|
#include "phase2.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
@ -85,7 +85,6 @@
|
|||||||
|
|
||||||
}%%
|
}%%
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
%% machine classify;
|
%% machine classify;
|
||||||
%% write data;
|
%% write data;
|
||||||
@ -167,16 +166,40 @@ void phase2::finish() {
|
|||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void phase2::parse(int token, std::string &&s) {
|
||||||
|
if (parser) parser->parse(token, std::move(s));
|
||||||
|
}
|
||||||
|
|
||||||
void phase2::exec() {
|
void phase2::exec() {
|
||||||
|
|
||||||
if (pipe_to) {
|
if (pipe_to && parser) {
|
||||||
for (auto &p : command_queue) {
|
for (auto &p : parser->command_queue) {
|
||||||
if (p) {
|
if (p) {
|
||||||
pipe_to(std::move(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