Files
fsh-oop/include/lexer.hpp

90 lines
2.5 KiB
C++

#pragma once
#include <functional>
#include <list>
#include <string>
namespace fsh {
class Lexer {
public:
enum TokenType {
WHITESPACE,
WORD,
STRING_LITERAL,
OPT,
FLAG,
LREDIRECTION,
RREDIRECTION,
PIPE,
END_OF_STREAM
};
using Token = std::pair<Lexer::TokenType, std::string>;
int peek();
int consume();
Token next_token();
static std::list<Token> process(std::string line);
private:
std::string workspace;
unsigned int idx;
Lexer(std::string str) : workspace(str), idx(0) {}
};
using Token = Lexer::Token;
class LexerStateMachine {
friend class Lexer;
private:
enum State {
START,
REDIRECT,
FLAG_OPT,
POTENTIAL_WORD,
STRING_LITERAL,
STATE_COUNT,
END
};
using StateHandler = std::function<State(void)>;
Lexer& parser;
std::string token;
Lexer::TokenType type;
std::vector<StateHandler> state_handlers;
LexerStateMachine(Lexer& parser) :
parser(parser), token(""), type(Lexer::TokenType::WHITESPACE), state_handlers(STATE_COUNT) {
state_handlers[State::START] = std::bind(&LexerStateMachine::handle_start, this);
state_handlers[State::REDIRECT] = std::bind(&LexerStateMachine::handle_redirect, this);
state_handlers[State::FLAG_OPT] = std::bind(&LexerStateMachine::handle_flag_opt, this);
state_handlers[State::POTENTIAL_WORD] = std::bind(&LexerStateMachine::handle_potential_word, this);
state_handlers[State::STRING_LITERAL] = std::bind(&LexerStateMachine::handle_string_literal, this);
}
State set_type(Lexer::TokenType type, State state);
Token run();
State handle_start();
State handle_redirect();
State handle_flag_opt();
State handle_potential_word();
State handle_string_literal();
State word_like_handler(Lexer::TokenType type, State state);
};
inline LexerStateMachine::State LexerStateMachine::set_type(Lexer::TokenType type = Lexer::TokenType::WHITESPACE,
State state = State::END) {
this->type = type;
return state;
}
} // namespace fsh