From e3936c5fc5b846f90d8cdfc589960c6881caa019 Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Sun, 27 Mar 2022 11:57:00 -0600 Subject: Lexer funcional --- exceptions.cpp | 8 ++++++++ include/exceptions.hpp | 11 ++++++++--- include/lexer.hpp | 4 ++-- lexer.cpp | 21 +++++++++++++++++---- main.cpp | 39 +++++++++++++++++++++++++++++++++++++++ makefile | 4 ++-- 6 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 exceptions.cpp create mode 100644 main.cpp diff --git a/exceptions.cpp b/exceptions.cpp new file mode 100644 index 0000000..23ca88b --- /dev/null +++ b/exceptions.cpp @@ -0,0 +1,8 @@ +#include +#include "include/exceptions.hpp" + +using std::string; + +string Exception::showMsg(){ + return error_msg; +} diff --git a/include/exceptions.hpp b/include/exceptions.hpp index 0469784..4b5fcfa 100644 --- a/include/exceptions.hpp +++ b/include/exceptions.hpp @@ -1,4 +1,9 @@ +/* PIA - Lenguajes Modernos de Programación + * FACULTAD DE CIENCIAS FÍSICO MATEMÁTICAS + * Luis Sebastián Martínez Vega - LCC */ + #include + #ifndef EXCEPTIONS_H #define EXCEPTIONS_H @@ -6,18 +11,18 @@ class Exception{ private: std::string error_msg; public: - Exception(const std::string &error_msg); + explicit Exception(const std::string &error_msg): error_msg(error_msg){} std::string showMsg(); }; class LexerException: public Exception{ public: - LexerException(const std::string &error_msg): Exception(error_msg){} + explicit LexerException(const std::string &error_msg): Exception(error_msg){} }; class ParserException: public Exception{ public: - ParserException(const std::string &error_msg): Exception(error_msg){} + explicit ParserException(const std::string &error_msg): Exception(error_msg){} }; #endif /* EXCEPTIONS_H */ diff --git a/include/lexer.hpp b/include/lexer.hpp index e674999..27779ea 100644 --- a/include/lexer.hpp +++ b/include/lexer.hpp @@ -33,7 +33,7 @@ enum token_type{ struct Token{ token_type type; std::string value; - Token(token_type type, std::string value) : type(type), value(value){} + Token(token_type type, const std::string &value) : type(type), value(value){} }; class Lexer{ @@ -42,7 +42,7 @@ private: std::string text; size_t current_char; Token current_token; - bool matchFunction(std::string function_name); + bool matchFunction(const std::string &function_name); std::string createNumber(); public: Lexer(std::string text = {}); diff --git a/lexer.cpp b/lexer.cpp index 9cfb2f7..666b999 100644 --- a/lexer.cpp +++ b/lexer.cpp @@ -16,6 +16,7 @@ Lexer::Lexer(string text): current_token(nil, {}){ void Lexer::setText(string text){ this->text = text; // Inicializamos el lexer. + current_char = 0; current_token = nextToken(); var_name = '\0'; } @@ -24,8 +25,8 @@ Token Lexer::getCurrentToken(){ return current_token; } -bool Lexer::matchFunction(string function_name){ - string name = text.substr(current_char, 2); +bool Lexer::matchFunction(const string &function_name){ + string name = text.substr(current_char, 3); bool matched = name == function_name; // Si hubo una coincidencia movemos el puntero. @@ -48,8 +49,12 @@ string Lexer::createNumber(){ } Token Lexer::match(){ + // Si ya consumimos todo el texto, + // regresamos nil. + if(current_char >= text.length()) + return Token(nil, {}); // Probamos las funciones. - if(current_char + 2 < text.length()) + if(isalpha(text[current_char]) && current_char + 2 <= text.length()) { if(matchFunction("sin")) return Token(function, "sin"); @@ -71,7 +76,12 @@ Token Lexer::match(){ /* Si es la primera vez que se lee un token variable o si la variable leída es igual a la anteriormente leída. */ if(var_name == '\0' || var_name == text[current_char]) + { + var_name = text[current_char]; + ++current_char; + return Token(variable, string(1, var_name)); + } // Error, se introdujo una expresión con dos o más variables. throw LexerException("Encontrada más de una variable."); @@ -103,11 +113,14 @@ Token Lexer::match(){ ++current_char; return Token(right_parens, {}); default: - throw LexerException("Carácter inválido."); + return Token(nil, {}); } } Token Lexer::nextToken(){ + if(text[current_char] == ' ') + ++current_char; + current_token = match(); return current_token; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ee376c2 --- /dev/null +++ b/main.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include "include/lexer.hpp" + +using std::string, std::cin, std::cout, std::getline, std::vector, + std::begin, std::end; + +string types[] = {string(1, '+'), string(1, '-'), string(1, '/'), string(1, '*'), + string(1, '^'), "variable", "número", "función", string(1, '('), string(1, ')'), "nil"}; + + +void print_tokens(const vector< Token > &tokens){ + for(auto i = begin(tokens); i != end(tokens); ++i) + { + if(i->type == variable || i->type == number || i->type == function) + cout << "Tipo: " << types[i->type] << "\nValor: " << i->value << '\n'; + else + cout << "Tipo: " << types[i->type] << '\n'; + } +} + +int main(){ + vector< Token > tokens; + string input; + Lexer lexer; + getline(cin, input); + lexer.setText(input); + + while(lexer.getCurrentToken().type != nil) + { + tokens.push_back(lexer.getCurrentToken()); + lexer.nextToken(); + } + print_tokens(tokens); + + return 0; +} diff --git a/makefile b/makefile index 552120b..98d091e 100644 --- a/makefile +++ b/makefile @@ -1,7 +1,7 @@ CC=g++ CFLAGS= -std=gnu++17 -g -DEPS = lexer.hpp -OBJ = lexer.o main.o +DEPS = include/lexer.hpp include/exceptions.hpp +OBJ = lexer.o exceptions.o main.o %.o : %.cpp $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) -- cgit v1.2.3