#pragma once #include #include #include namespace fsh { class Lexer { public: enum TokenType { WHITESPACE, WORD, STRING_LITERAL, OPT, FLAG, LREDIRECTION, RREDIRECTION, PIPE, END_OF_STREAM }; using Token = std::pair; int peek(); int consume(); Token next_token(); static std::list 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; Lexer& parser; std::string token; Lexer::TokenType type; std::vector 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; } }