Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Lexer, modifiche e malfunzionamenti molesti
Forum - C/C++ - Lexer, modifiche e malfunzionamenti molesti

Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 22:28
Giovedì, 21/08/2014
L' altra sera ero felice che il mio lexer funzionasse bene, così ho deciso di modificare il lexer: vector<Token> è diventato vector<Token>*. La modifica ha avuto successo, così ho deciso di memorizzare nei token anche il numero di carattere nella riga corrispondente a quel token e qui sono cominciati i problemi: lancio l' esecuzione del programma e mi viene stampato a video numero commenti: 0 e numero commenti multiriga: 0 e non c'è nessun token nel vettore. Non riesco a capire cosa non va, aiuto.

Codice sorgente - presumibilmente C++

  1. /*
  2.  * Lexer.h
  3.  *
  4.  *  Created on: 14/08/2014
  5.  *      Author: Denis
  6.  */
  7.  
  8. #ifndef __LEXER__
  9. #define __LEXER__
  10.  
  11. #include "Token.h"
  12.  
  13. #include <string.h>
  14. #include <vector>
  15. #include <memory>
  16.  
  17. using namespace std;
  18.  
  19. #define EMPTY_BUFFER -1
  20. #define NULL_BUFFER -2
  21. #define NO_ERRORS 0
  22.  
  23. enum LexReading {
  24.         MultiLineComment,
  25.         SingleLineComment,
  26.         Number,
  27.         String,
  28.         Identifier,
  29.         Source
  30. };
  31.  
  32. class Lexer {
  33. public:
  34.         Lexer(char*, vector<Token>*);
  35.         short Analyze(void);
  36.  
  37.         //lexer data
  38.         char* buffer;
  39.         unsigned long bufferLength;
  40.  
  41.         //lex result
  42.         vector<Token>* Tokens;
  43.  
  44.         //statistics
  45.         unsigned long MultiLineFoundComments;
  46.         unsigned long SingleLineFoundComments;
  47. };
  48.  
  49. #endif /* __LEXER__ */



Codice sorgente - presumibilmente VB.NET

  1. #include "Lexer.h"
  2.  
  3. Lexer::Lexer(char* buffer, vector<Token>* tokens)
  4. {
  5.         this->buffer = buffer; //save the buffer pointer
  6.         this->bufferLength = strlen(buffer); //save the buffer length
  7.         this->Tokens = tokens; //save the pointer
  8.  
  9.         //setup everything
  10.         this->MultiLineFoundComments = 0L;
  11.         this->SingleLineFoundComments = 0L;
  12. }
  13.  
  14. short Lexer::Analyze(void)
  15. {
  16.         //check if the buffer is null or empty and return the proper error if so
  17.         if (this->buffer == (char*)NULL)
  18.                 return NULL_BUFFER;
  19.         else if (this->bufferLength == 0)
  20.                 return EMPTY_BUFFER;
  21.  
  22.         //what is the lexer reading?
  23.         LexReading currentlyReading;
  24.  
  25.         unsigned long currentBufferCharacter = 0L; //the character that the lexer will read
  26.         unsigned long currentBufferRow = 1L; //the user will know the exact line of an error (or warning) if any
  27.         unsigned long currentBufferColumn = 1L; //the user will know the exact line of an error (or warning) if any
  28.         vector<char> temp; //a temporary vector to store the characters of identifiers, numbers, strings and chars
  29.  
  30.         while (currentBufferCharacter < this->bufferLength)
  31.         {
  32.                 switch (currentlyReading)
  33.                 {
  34.                         case MultiLineComment:
  35.                                 //if this is the end of the comment
  36.                                 if ((this->buffer[currentBufferCharacter] == '*') && (this->buffer[currentBufferCharacter + 1] == '/'))
  37.                                 {
  38.                                         currentlyReading = Source; //the lexer is going to read source code again
  39.                                         this->MultiLineFoundComments++; //update the number of multi line comments lexed
  40.                                         currentBufferCharacter++; //the lexer won't read the / character the next step
  41.                                 } else if (this->buffer[currentBufferCharacter] == '\n') {
  42.                                         currentBufferRow++; //update the row number
  43.                                         currentBufferColumn = 1L; //update the column number
  44.                                 }
  45.                                 //else do nothing, I don't care about comments
  46.                                 break;
  47.  
  48.                         case SingleLineComment:
  49.                                 //if this is the end of the line
  50.                                 if (this->buffer[currentBufferCharacter] == '\n')
  51.                                 {
  52.                                         currentlyReading = Source; //the lexer is going to read source code again
  53.                                         this->SingleLineFoundComments++; //update the number of single line comments lexed
  54.                                         currentBufferRow++; //update the row number
  55.                                         currentBufferColumn = 1L; //update the column number
  56.                                 }
  57.                                 //else do nothing, I don't care about comments
  58.                                 break;
  59.  
  60.                         case Number:
  61.                                 //if this is the end of the number
  62.                                 if (((this->buffer[currentBufferCharacter] < 48) || (this->buffer[currentBufferCharacter] > 57)) && ((this->buffer[currentBufferCharacter] != '.') && (this->buffer[currentBufferCharacter] != 'D') && (this->buffer[currentBufferCharacter] != 'X') && (this->buffer[currentBufferCharacter] != 'B') && (this->buffer[currentBufferCharacter] != 'd') && (this->buffer[currentBufferCharacter] != 'x') && (this->buffer[currentBufferCharacter] != 'b') && (this->buffer[currentBufferCharacter] != 'a')&& (this->buffer[currentBufferCharacter] != 'A') && (this->buffer[currentBufferCharacter] != 'b') && (this->buffer[currentBufferCharacter] != 'C') && (this->buffer[currentBufferCharacter] != 'c') && (this->buffer[currentBufferCharacter] != 'd') && (this->buffer[currentBufferCharacter] != 'D') && (this->buffer[currentBufferCharacter] != 'e') && (this->buffer[currentBufferCharacter] != 'E') && (this->buffer[currentBufferCharacter] != 'f') && (this->buffer[currentBufferCharacter] != 'F')))
  63.                                 { //then save the number stored in temp
  64.                                         size_t characters = temp.size();
  65.                                         char* numberStringFromTemp = new char[characters + 1];
  66.                                         numberStringFromTemp[characters] = (char)0x00;
  67.                                         size_t currentChar;
  68.                                         for (currentChar = 0L; currentChar < characters; currentChar++)
  69.                                                 numberStringFromTemp[currentChar] = temp[currentChar];
  70.                                         //create the token
  71.                                         Token numberToken;
  72.                                         numberToken.type = TNUMBER;
  73.                                         numberToken.row = currentBufferRow;
  74.                                         numberToken.column = currentBufferColumn;
  75.                                         numberToken.data = numberStringFromTemp;
  76.                                         this->Tokens->push_back(numberToken); //save the new token
  77.                                         temp.clear(); //clear the temp buffer after having saved the number stored in
  78.                                         currentlyReading = Source; //prepare the lexer for the next character
  79.                                         currentBufferCharacter--; //the lexer have to re-read the current character
  80.                                 } else { //else save the character to the temp
  81.                                         temp.push_back(this->buffer[currentBufferCharacter]); //store the read character
  82.                                 }
  83.                                 break;
  84.  
  85.                         case String:
  86.                                 //if this is the end of a string
  87.                                 if (this->buffer[currentBufferCharacter] == '"')
  88.                                 { //then save the string stored in temp
  89.                                         size_t characters = temp.size();
  90.                                         char* stringFromTemp = new char[characters + 1];
  91.                                         stringFromTemp[characters] = (char)0x00;
  92.                                         size_t currentChar;
  93.                                         for (currentChar = 0L; currentChar < characters; currentChar++)
  94.                                                 stringFromTemp[currentChar] = temp[currentChar];
  95.                                         //create the token
  96.                                         Token stringToken;
  97.                                         stringToken.type = TSTRING;
  98.                                         stringToken.row = currentBufferRow;
  99.                                         stringToken.column = currentBufferColumn;
  100.                                         stringToken.data = stringFromTemp;
  101.                                         this->Tokens->push_back(stringToken); //save the new token
  102.                                         temp.clear(); //clear the temp buffer after having saved the string stored in
  103.                                         currentlyReading = Source; //prepare the lexer for the next character
  104.                                 } else if (this->buffer[currentBufferCharacter] == '\n') {
  105.                                         temp.push_back('\\'); //store the read character
  106.                                         temp.push_back('n'); //as it should be stored
  107.                                         currentBufferRow++; //update the row number
  108.                                         currentBufferColumn = 1L; //update the column number
  109.  
  110.                                         /* FUCK YOU! STUPID USER! */
  111.  
  112.                                 } else if (this->buffer[currentBufferCharacter] == '\t') {
  113.                                         temp.push_back('\\'); //store the read character
  114.                                         temp.push_back('t'); //as it should be stored
  115.  
  116.                                         /* FUCK YOU! STUPID USER! */
  117.  
  118.                                 } else if (this->buffer[currentBufferCharacter] == '\b') {
  119.                                         temp.push_back('\\'); //store the read character
  120.                                         temp.push_back('b'); //as it should be stored
  121.  
  122.                                         /* FUCK YOU! STUPID USER! */
  123.  
  124.                                 } else if (this->buffer[currentBufferCharacter] == '\f') {
  125.                                         temp.push_back('\\'); //store the read character
  126.                                         temp.push_back('f'); //as it should be stored
  127.  
  128.                                         /* FUCK YOU! STUPID USER! */
  129.  
  130.                                 } else if (this->buffer[currentBufferCharacter] == '\v') {
  131.                                         temp.push_back('\\'); //store the read character
  132.                                         temp.push_back('v'); //as it should be stored
  133.  
  134.                                         /* FUCK YOU! STUPID USER! */
  135.  
  136.                                 } else if (this->buffer[currentBufferCharacter] == '\r') {
  137.                                         temp.push_back('\\'); //store the read character
  138.                                         temp.push_back('r'); //as it should be stored
  139.  
  140.                                         /* FUCK YOU! STUPID USER! */
  141.  
  142.                                 } else if (this->buffer[currentBufferCharacter] == '\?') {
  143.                                         temp.push_back('\\'); //store the read character
  144.                                         temp.push_back('?'); //as it should be stored
  145.  
  146.                                         /* FUCK YOU! STUPID USER! */
  147.  
  148.                                 } else { //else save the character to the temp
  149.                                         temp.push_back(this->buffer[currentBufferCharacter]); //store the read character
  150.                                 }
  151.                                 break;
  152.  
  153.                         case Identifier:
  154.                                 //if this is a character that is part of an identifier
  155.                                 if (((this->buffer[currentBufferCharacter] >= 65) && (this->buffer[currentBufferCharacter] <= 90)) || ((this->buffer[currentBufferCharacter] >= 97) && (this->buffer[currentBufferCharacter] <= 122)) || (this->buffer[currentBufferCharacter] == '_'))
  156.                                 {
  157.                                         temp.push_back(this->buffer[currentBufferCharacter]); //store the read character
  158.                                 } else { //save the string stored in temp
  159.                                         size_t characters = temp.size();
  160.                                         char* identifierStringFromTemp = new char[characters + 1];
  161.                                         identifierStringFromTemp[characters] = (char)0x00;
  162.                                         size_t currentChar;
  163.                                         for (currentChar = 0L; currentChar < characters; currentChar++)
  164.                                                 identifierStringFromTemp[currentChar] = temp[currentChar];
  165.                                         //create the token
  166.                                         Token identifierToken;
  167.                                         identifierToken.type = TIDENTIFIER;
  168.                                         identifierToken.row = currentBufferRow;
  169.                                         identifierToken.column = currentBufferColumn;
  170.                                         identifierToken.data = identifierStringFromTemp;
  171.                                         this->Tokens->push_back(identifierToken); //save the new token
  172.                                         temp.clear(); //clear the temp buffer after having saved the identifier stored in
  173.                                         currentlyReading = Source; //prepare the lexer for the next character
  174.                                         currentBufferCharacter--; //the lexer have to re-read the current character
  175.                                 }
  176.                                 break;
  177.  
  178.                         case Source:
  179.                                 if (this->buffer[currentBufferCharacter] == '\n')
  180.                                 {
  181.                                         currentBufferRow++; //update the row number
  182.                                         currentBufferColumn = 1L; //update the column number
  183.                                 }
  184.                                 else if (this->buffer[currentBufferCharacter] == '#') //single line comments aren't C-like
  185.                                 {
  186.                                         currentlyReading = SingleLineComment; //the lexer is going to read a single line comment
  187.                                 }
  188.                                 else if ((this->buffer[currentBufferCharacter] == '/') && (this->buffer[currentBufferCharacter + 1] == '*')) //multi line comments are C-like
  189.                                 {
  190.                                         currentlyReading = MultiLineComment; //the lexer is going to read a multi line comment
  191.                                         currentBufferCharacter++; //the lexer won't read the * simbol
  192.                                 }
  193.                                 else if (this->buffer[currentBufferCharacter] == '"') //start of a string
  194.                                 {
  195.                                         currentlyReading = String; //the lexer is going to read a string
  196.                                 }
  197.                                 else if ((this->buffer[currentBufferCharacter] >= 48) && (this->buffer[currentBufferCharacter] <= 57)) // ASCII code of 0 is 48 and of 9 is 57
  198.                                 {
  199.                                         currentlyReading = Number; //the lexer is going to read a number
  200.                                         currentBufferCharacter--; //a little trick: i want the lexer to read this character again (when the lexer will expect a number)
  201.                                 }
  202.                                 else if (((this->buffer[currentBufferCharacter] >= 65) && (this->buffer[currentBufferCharacter] <= 90)) || ((this->buffer[currentBufferCharacter] >= 97) && (this->buffer[currentBufferCharacter] <= 122)) || (this->buffer[currentBufferCharacter] == '_'))
  203.                                 {
  204.                                         currentlyReading = Identifier; //the lexer is going to read an identifier
  205.                                         currentBufferCharacter--; //the same little trick: i want the lexer to read this character again (when the lexer will expect an identifier)
  206.                                 }
  207.                                 else if (this->buffer[currentBufferCharacter] == ';')
  208.                                 {
  209.                                         Token newToken;
  210.                                         newToken.type = TDOTCOMMA;
  211.                                         newToken.row = currentBufferRow;
  212.                                         newToken.column = currentBufferColumn;
  213.                                         newToken.data = (char*)NULL;
  214.                                         this->Tokens->push_back(newToken);
  215.                                 }
  216.                                 else if (this->buffer[currentBufferCharacter] == '.')
  217.                                 {
  218.                                         Token newToken;
  219.                                         newToken.type = TDOT;
  220.                                         newToken.row = currentBufferRow;
  221.                                         newToken.column = currentBufferColumn;
  222.                                         newToken.data = (char*)NULL;
  223.                                         this->Tokens->push_back(newToken);
  224.                                 }
  225.                                 else if (this->buffer[currentBufferCharacter] == ',')
  226.                                 {
  227.                                         Token newToken;
  228.                                         newToken.type = TCOMMA;
  229.                                         newToken.row = currentBufferRow;
  230.                                         newToken.column = currentBufferColumn;
  231.                                         newToken.data = (char*)NULL;
  232.                                         this->Tokens->push_back(newToken);
  233.                                 }
  234.                                 else if (this->buffer[currentBufferCharacter] == '{')
  235.                                 {
  236.                                         Token newToken;
  237.                                         newToken.type = TLBRACE;
  238.                                         newToken.row = currentBufferRow;
  239.                                         newToken.column = currentBufferColumn;
  240.                                         newToken.data = (char*)NULL;
  241.                                         this->Tokens->push_back(newToken);
  242.                                 }
  243.                                 else if (this->buffer[currentBufferCharacter] == '}')
  244.                                 {
  245.                                         Token newToken;
  246.                                         newToken.type = TRBRACE;
  247.                                         newToken.row = currentBufferRow;
  248.                                         newToken.column = currentBufferColumn;
  249.                                         newToken.data = (char*)NULL;
  250.                                         this->Tokens->push_back(newToken);
  251.                                 }
  252.                                 else if (this->buffer[currentBufferCharacter] == '(')
  253.                                 {
  254.                                         Token newToken;
  255.                                         newToken.type = TLPAREN;
  256.                                         newToken.row = currentBufferRow;
  257.                                         newToken.column = currentBufferColumn;
  258.                                         newToken.data = (char*)NULL;
  259.                                         this->Tokens->push_back(newToken);
  260.                                 }
  261.                                 else if (this->buffer[currentBufferCharacter] == ')')
  262.                                 {
  263.                                         Token newToken;
  264.                                         newToken.type = TRPAREN;
  265.                                         newToken.row = currentBufferRow;
  266.                                         newToken.column = currentBufferColumn;
  267.                                         newToken.data = (char*)NULL;
  268.                                         this->Tokens->push_back(newToken);
  269.                                 }
  270.                                 else if (this->buffer[currentBufferCharacter] == '[')
  271.                                 {
  272.                                         Token newToken;
  273.                                         newToken.type = TLSQRPAREN;
  274.                                         newToken.row = currentBufferRow;
  275.                                         newToken.column = currentBufferColumn;
  276.                                         newToken.data = (char*)NULL;
  277.                                         this->Tokens->push_back(newToken);
  278.                                 }
  279.                                 else if (this->buffer[currentBufferCharacter] == ']')
  280.                                 {
  281.                                         Token newToken;
  282.                                         newToken.type = TRSQRPAREN;
  283.                                         newToken.row = currentBufferRow;
  284.                                         newToken.column = currentBufferColumn;
  285.                                         newToken.data = (char*)NULL;
  286.                                         this->Tokens->push_back(newToken);
  287.                                 }
  288.                                 break;
  289.  
  290.                         default:
  291.                                 break;
  292.                 }
  293.                 currentBufferColumn++; //update the number of the character in the current line
  294.                 currentBufferCharacter++; //next time I'll read the next character
  295.         }
  296.         //check if the lexer reached the end unexpectly
  297.         if ((currentlyReading != Source) && (currentlyReading != SingleLineComment))
  298.         {
  299.                 if (currentlyReading == Identifier)
  300.                 {
  301.                         size_t characters = temp.size();
  302.                         char* identifierStringFromTemp = new char[characters + 1];
  303.                         identifierStringFromTemp[characters] = (char)0x00;
  304.                         size_t currentChar;
  305.                         for (currentChar = 0L; currentChar < characters; currentChar++)
  306.                                 identifierStringFromTemp[currentChar] = temp[currentChar];
  307.                         //create the token
  308.                         Token identifierToken;
  309.                         identifierToken.type = TIDENTIFIER;
  310.                         identifierToken.row = currentBufferRow;
  311.                         identifierToken.column = currentBufferColumn;
  312.                         identifierToken.data = identifierStringFromTemp;
  313.                         this->Tokens->push_back(identifierToken); //save the new token
  314.  
  315.                         /* FUCK YOU! STUPID USER! */
  316.  
  317.                 } else if (currentlyReading == Number) {
  318.                         size_t characters = temp.size();
  319.                         char* numberStringFromTemp = new char [characters + 1];
  320.                         numberStringFromTemp[characters] = (char)0x00;
  321.                         size_t currentChar;
  322.                         for (currentChar = 0L; currentChar < characters; currentChar++)
  323.                                 numberStringFromTemp[currentChar] = temp[currentChar];
  324.                         //create the token
  325.                         Token numberToken;
  326.                         numberToken.type = TNUMBER;
  327.                         numberToken.row = currentBufferRow;
  328.                         numberToken.column = currentBufferColumn;
  329.                         numberToken.data = numberStringFromTemp;
  330.                         this->Tokens->push_back(numberToken); //save the new token
  331.  
  332.                         /* FUCK YOU! STUPID USER! */
  333.  
  334.                 } else if (currentlyReading == String) {
  335.                         //return an error
  336.                 } else { //MultiLineComment
  337.                         //return an error
  338.                 }
  339.         }
  340.         //the lexer's job is done
  341.         return NO_ERRORS;
  342. }



Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <vector>
  4.  
  5. #include "Lexer.h"
  6.  
  7. int main(int argc, char** argv)
  8. {
  9.         char* src = "/* sd */ \"This should be displayed \"...# /*s5d*/\n/*cd \"This should not be displayed\"*/#f\n55 6.5H\n5.9B /* 5.7 */ 5f, 5,f\n \"a slash and a n should be displayed: \n\" \"'\"  #comment\n\n ";
  10.         vector<Token> TokensList;
  11.         Lexer Analyzer(src, &TokensList);
  12.         if (Analyzer.Analyze() != 0)
  13.         {
  14.                 printf("Si e' verificato un errore!");
  15.         } else {
  16.                 printf("Commenti multilinea: %u\nCommenti: %u\n", Analyzer.MultiLineFoundComments, Analyzer.SingleLineFoundComments );
  17.         }
  18.  
  19.         size_t i;
  20.         for (i = 0; i < TokensList.size(); i++)
  21.         {
  22.                 printf("\n\nToken numer %u: \nType: ", (i + 1));
  23.                 if (TokensList[i].type == TIDENTIFIER)
  24.                 {
  25.                         printf("identifier\nValue: ");
  26.                         puts(TokensList[i].data);
  27.                 }
  28.                 else if (TokensList[i].type == TNUMBER)
  29.                 {
  30.                         printf("number\nValue: ");
  31.                         puts(TokensList[i].data);
  32.                 }
  33.                 else if (TokensList[i].type == TCHAR)
  34.                 {
  35.                         printf("character\nValue: ");
  36.                         puts(TokensList[i].data);
  37.                 }
  38.                 else if (TokensList[i].type == TSTRING)
  39.                 {
  40.                         printf("string\nValue: ");
  41.                         puts(TokensList[i].data);
  42.                 }
  43.         }
  44.         return 0;
  45. }



Altra domanda: credete che dovrei usare shared_ptr invece che passarmi il puntatore? Che benefici avrei nel farlo?

P.S. Non ho capito perchè abbia funzionato durante varie prove, ma il problema è legato al fatto che nella classe ci sia vector<Token>* anzichè vector<Token>. A dire la verità mi scoccia parecchia il fatto che anche se ho ricompilato e provato più volte il problema sia sorto in ritardo e ancora di più avere nella classe lexer un vector<Token>. C'è una alternativa più "elegante"?

Ultima modifica effettuata da TheDarkJuster il 21/08/2014 alle 23:01
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 0:48
Sabato, 23/08/2014
Mm, l'unica cosa che e' certamente sbagliata e' il modo in cui popoli il vector Tokens.

Una variabile inizializzata così:

Codice sorgente - presumibilmente Plain Text

  1. { // blocco
  2.    Tipo a;
  3.    // ...
  4. } // fine blocco



Verrà deinizializzata all'uscita del suo scope.

Codice sorgente - presumibilmente C++

  1. #include <iostream>
  2. #include <vector>
  3.  
  4. using namespace std;
  5.  
  6. class Test{
  7. public:
  8.     int n;
  9.     Test(int n) : n(n){ cout << "Creato " << n << endl; }
  10.     ~Test() { cout << "Distrutto " << n << endl; }
  11. };
  12.  
  13. int main(){
  14.     vector<Test> *p = new vector<Test>();
  15.  
  16.     {
  17.       Test a(1);
  18.       Test b(2);
  19.       p->push_back(a);
  20.       p->push_back(b);
  21.     }
  22.    
  23.     cout << "Fine" << endl;
  24. }



Ultima modifica effettuata da pierotofy il 23/08/2014 alle 0:48


Il mio blog: https://piero.dev
PM Quote
Avatar
TheDarkJuster (Member)
Guru^2


Messaggi: 1620
Iscritto: 27/09/2013

Segnala al moderatore
Postato alle 12:09
Sabato, 23/08/2014
Giusto, non ci avevo pensato...
A questo punto mi conviene creare nuovi token e memorizzare nel vettore il puntatore

PM Quote