#pragma once #include #include #include namespace fsh { // Ova klasa vrsi leksicku analizu ulaznog string-a class Lexer { public: enum TokenType { WHITESPACE, WORD, STRING_LITERAL, FLAG, LREDIRECTION, RREDIRECTION, PIPE, END_OF_STREAM }; using Token = std::pair; // Daje nam sledeci karakter bez povecavanjem brojaca int peek(); // Daje nam sledeci karakter sa povecavanjem brojaca int consume(); // Trazi za sledeci token 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; } }