Advertisement
rdujardin

C++ Lexical Analyser for JavaScript : lexical.cpp

May 1st, 2015
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.03 KB | None | 0 0
  1. /* lexical.cpp -- version 0.2, May 1st, 2015
  2.  
  3.   Copyright (C) 2015 Raphaël Dujardin
  4.  
  5.   This software is provided 'as-is', without any express or implied
  6.   warranty.  In no event will the authors be held liable for any damages
  7.   arising from the use of this software.
  8.  
  9.   Permission is granted to anyone to use this software for any purpose,
  10.   including commercial applications, and to alter it and redistribute it
  11.   freely, subject to the following restrictions:
  12.  
  13.   1. The origin of this software must not be misrepresented; you must not
  14.      claim that you wrote the original software. If you use this software
  15.      in a product, an acknowledgment in the product documentation would be
  16.      appreciated but is not required.
  17.   2. Altered source versions must be plainly marked as such, and must not be
  18.      misrepresented as being the original software.
  19.   3. This notice may not be removed or altered from any source distribution.
  20.  
  21.   Raphaël Dujardin
  22.   rdujardin.com
  23.  
  24. */
  25.  
  26. #include "lexical.h"
  27.  
  28. namespace lex
  29. {
  30.    
  31.     Token::Token(TokenType _type,std::string _value)
  32.     {
  33.         type=_type;
  34.         value=_value;
  35.     }
  36.    
  37.     Token::Token(const Token& token)
  38.     {
  39.         (*this)=token;
  40.     }
  41.    
  42.     Token::~Token()
  43.     {
  44.         //.
  45.     }
  46.    
  47.     void Token::print(std::ostream& out,bool withValue,bool withEol) const
  48.     {
  49.         switch(type)
  50.         {
  51.         case NULLTOKEN:
  52.             out << "NULLTOKEN";
  53.             if(withEol) out << std::endl;
  54.             break;
  55.         case INTEGER:
  56.             out << "INTEGER";
  57.             if(withValue) out << " # " << value;
  58.             if(withEol) out << std::endl;
  59.             break;
  60.         case FLOATING:
  61.             out << "FLOATING";
  62.             if(withValue) out << " # " << value;
  63.             if(withEol) out << std::endl;
  64.             break;
  65.         case STRING:
  66.             out << "STRING";
  67.             if(withValue) out << " # " << value;
  68.             if(withEol) out << std::endl;
  69.             break;
  70.         case NAME:
  71.             out << "NAME";
  72.             if(withValue) out << " # " << value;
  73.             if(withEol) out << std::endl;
  74.             break;
  75.         case PLUS:
  76.             out << "PLUS";
  77.             if(withEol) out << std::endl;
  78.             break;
  79.         case MINUS:
  80.             out << "MINUS";
  81.             if(withEol) out << std::endl;
  82.             break;
  83.         case MULTIPLY:
  84.             out << "MULTIPLY";
  85.             if(withEol) out << std::endl;
  86.             break;
  87.         case DIVIDE:
  88.             out << "DIVIDE";
  89.             if(withEol) out << std::endl;
  90.             break;
  91.         case MODULO:
  92.             out << "MODULO";
  93.             if(withEol) out << std::endl;
  94.             break;
  95.         case EQUAL:
  96.             out << "EQUAL";
  97.             if(withEol) out << std::endl;
  98.             break;
  99.         case LPARENTHESIS:
  100.             out << "LPARENTHESIS";
  101.             if(withEol) out << std::endl;
  102.             break;
  103.         case RPARENTHESIS:
  104.             out << "RPARENTHESIS";
  105.             if(withEol) out << std::endl;
  106.             break;
  107.         case LBRACKET:
  108.             out << "LBRACKET";
  109.             if(withEol) out << std::endl;
  110.             break;
  111.         case RBRACKET:
  112.             out << "RBRACKET";
  113.             if(withEol) out << std::endl;
  114.             break;
  115.         case LSQUARE:
  116.             out << "LSQUARE";
  117.             if(withEol) out << std::endl;
  118.             break;
  119.         case RSQUARE:
  120.             out << "RSQUARE";
  121.             if(withEol) out << std::endl;
  122.             break;
  123.         case COMMA:
  124.             out << "COMMA";
  125.             if(withEol) out << std::endl;
  126.             break;
  127.         case SEMICOLON:
  128.             out << "SEMICOLON";
  129.             if(withEol) out << std::endl;
  130.             break;
  131.         case INFERIOR:
  132.             out << "INFERIOR";
  133.             if(withEol) out << std::endl;
  134.             break;
  135.         case SUPERIOR:
  136.             out << "SUPERIOR";
  137.             if(withEol) out << std::endl;
  138.             break;
  139.         case BREAK:
  140.             out << "BREAK";
  141.             if(withEol) out << std::endl;
  142.             break;
  143.         case CASE:
  144.             out << "CASE";
  145.             if(withEol) out << std::endl;
  146.             break;
  147.         case CATCH:
  148.             out << "CATCH";
  149.             if(withEol) out << std::endl;
  150.             break;
  151.         case CONST:
  152.             out << "CONST";
  153.             if(withEol) out << std::endl;
  154.             break;
  155.         case CONTINUE:
  156.             out << "CONTINUE";
  157.             if(withEol) out << std::endl;
  158.             break;
  159.         case DEBUGGER:
  160.             out << "DEBUGGER";
  161.             if(withEol) out << std::endl;
  162.             break;
  163.         case DO:
  164.             out << "DO";
  165.             if(withEol) out << std::endl;
  166.             break;
  167.         case ELSE:
  168.             out << "ELSE";
  169.             if(withEol) out << std::endl;
  170.             break;
  171.         case FINALLY:
  172.             out << "FINALLY";
  173.             if(withEol) out << std::endl;
  174.             break;
  175.         case FOR:
  176.             out << "FOR";
  177.             if(withEol) out << std::endl;
  178.             break;
  179.         case FUNCTION:
  180.             out << "FUNCTION";
  181.             if(withEol) out << std::endl;
  182.             break;
  183.         case IF:
  184.             out << "IF";
  185.             if(withEol) out << std::endl;
  186.             break;
  187.         case IN:
  188.             out << "IN";
  189.             if(withEol) out << std::endl;
  190.             break;
  191.         case INSTANCEOF:
  192.             out << "INSTANCEOF";
  193.             if(withEol) out << std::endl;
  194.             break;
  195.         case LET:
  196.             out << "LET";
  197.             if(withEol) out << std::endl;
  198.             break;
  199.         case NEW:
  200.             out << "NEW";
  201.             if(withEol) out << std::endl;
  202.             break;
  203.         case RETURN:
  204.             out << "RETURN";
  205.             if(withEol) out << std::endl;
  206.             break;
  207.         case SWITCH:
  208.             out << "SWITCH";
  209.             if(withEol) out << std::endl;
  210.             break;
  211.         case THIS:
  212.             out << "THIS";
  213.             if(withEol) out << std::endl;
  214.             break;
  215.         case THROW:
  216.             out << "THROW";
  217.             if(withEol) out << std::endl;
  218.             break;
  219.         case TRY:
  220.             out << "TRY";
  221.             if(withEol) out << std::endl;
  222.             break;
  223.         case TYPEOF:
  224.             out << "TYPEOF";
  225.             if(withEol) out << std::endl;
  226.             break;
  227.         case VAR:
  228.             out << "VAR";
  229.             if(withEol) out << std::endl;
  230.             break;
  231.         case VOID:
  232.             out << "VOID";
  233.             if(withEol) out << std::endl;
  234.             break;
  235.         case WHILE:
  236.             out << "WHILE";
  237.             if(withEol) out << std::endl;
  238.             break;
  239.         case DBEQUAL:
  240.             out << "DBEQUAL";
  241.             if(withEol) out << std::endl;
  242.             break;
  243.         case DBPLUS:
  244.             out << "DBPLUS";
  245.             if(withEol) out << std::endl;
  246.             break;
  247.         case DBMINUS:
  248.             out << "DBMINUS";
  249.             if(withEol) out << std::endl;
  250.             break;
  251.         default:
  252.             out << "?ERROR?";
  253.             if(withEol) out << std::endl;
  254.             break;
  255.         }
  256.     }
  257.    
  258.     void Token::printType(std::ostream& out) const
  259.     {
  260.         print(out,false);
  261.     }
  262.    
  263.     void Token::printCode(std::ostream& out) const
  264.     {
  265.         out << value;
  266.     }
  267.    
  268.     Token& Token::operator=(const Token &token)
  269.     {
  270.         type=token.type;
  271.         value=token.value;
  272.         return *this;
  273.     }
  274.    
  275.     Sequence::Sequence()
  276.     {
  277.         //.
  278.     }
  279.    
  280.     Sequence::Sequence(const std::string& code)
  281.     {
  282.         lex(code);
  283.     }
  284.    
  285.     Sequence::Sequence(const Token& token)
  286.     {
  287.         (*this)+=token;
  288.     }
  289.    
  290.     Sequence::Sequence(const Sequence& sequence)
  291.     {
  292.         (*this)=sequence;
  293.     }
  294.    
  295.     Sequence::~Sequence()
  296.     {
  297.         //.
  298.     }
  299.    
  300.     void Sequence::print(std::ostream& out,bool compact) const
  301.     {
  302.         if(!compact) out << std::endl;
  303.         out << "[";
  304.         if(!compact) out << std::endl;
  305.         for(std::deque<Token>::const_iterator it=tokens.begin();it!=tokens.end();it++)
  306.         {
  307.             (*it).print(out,true,!compact);
  308.             out << ((compact)?((it+1==tokens.end())?" ":" | "):"");
  309.         }
  310.         if(!compact) out << std::endl;
  311.         out << "]";
  312.         if(!compact) out << std::endl;
  313.     }
  314.    
  315.     void Sequence::printCode(std::ostream& out) const
  316.     {
  317.         for(std::deque<Token>::const_iterator it=tokens.begin();it!=tokens.end();it++)
  318.         {
  319.             it->printCode(out);
  320.         }
  321.     }
  322.    
  323.     Sequence& Sequence::operator=(const Sequence &sequence)
  324.     {
  325.         tokens=sequence.tokens;
  326.         return *this;
  327.     }
  328.    
  329.     Sequence& Sequence::operator+=(const Sequence &sequence)
  330.     {
  331.         tokens.insert(tokens.end(),sequence.tokens.begin(),sequence.tokens.end());
  332.         return *this;
  333.     }
  334.    
  335.     Sequence& Sequence::operator+=(const Token &token)
  336.     {
  337.         tokens.insert(tokens.end(),token);
  338.         return *this;
  339.     }
  340.    
  341.     std::string Sequence::toStr(const std::vector<char> &buf)
  342.     {
  343.         return std::string(buf.begin(),buf.end());
  344.     }
  345.    
  346.     std::pair<TokenType,std::vector<char>::const_iterator> Sequence::numberBuf(const std::vector<char> &buf)
  347.     {
  348.         bool isInteger=true;
  349.         for(std::vector<char>::const_iterator it=buf.begin();it!=buf.end();it++)
  350.         {
  351.             if(*it<0x30 or *it>0x39)
  352.             {
  353.                 if(*it=='.' and isInteger) isInteger=false;
  354.                 else return std::pair<TokenType,std::vector<char>::const_iterator>((isInteger)?INTEGER:FLOATING,it);
  355.             }
  356.         }
  357.         return std::pair<TokenType,std::vector<char>::const_iterator>((isInteger)?INTEGER:FLOATING,buf.end());
  358.     }
  359.    
  360.     Sequence Sequence::analyzeBuf(const std::vector<char> &buf)
  361.     {
  362.         std::pair<TokenType,std::vector<char>::const_iterator> num=numberBuf(buf);
  363.         if(num.second==buf.end()) return Sequence(Token(num.first,toStr(buf)));
  364.         else
  365.         {
  366.             if(num.second!=buf.begin())
  367.             {
  368.                 return Sequence(Token(num.first,std::string(buf.begin(),num.second)))+Token(NAME,std::string(num.second,buf.end()));
  369.             }
  370.         }
  371.         std::string s=toStr(buf);
  372.         if(s=="==") return Sequence(Token(DBEQUAL));
  373.         if(s=="break") return Sequence(Token(BREAK));
  374.         if(s=="case") return Sequence(Token(CASE));
  375.         if(s=="catch") return Sequence(Token(CATCH));
  376.         if(s=="const") return Sequence(Token(CONST));
  377.         if(s=="continue") return Sequence(Token(CONTINUE));
  378.         if(s=="debugger") return Sequence(Token(DEBUGGER));
  379.         if(s=="do") return Sequence(Token(DO));
  380.         if(s=="else") return Sequence(Token(ELSE));
  381.         if(s=="finally") return Sequence(Token(FINALLY));
  382.         if(s=="for") return Sequence(Token(FOR));
  383.         if(s=="function") return Sequence(Token(FUNCTION));
  384.         if(s=="if") return Sequence(Token(IF));
  385.         if(s=="in") return Sequence(Token(IN));
  386.         if(s=="instanceof") return Sequence(Token(INSTANCEOF));
  387.         if(s=="let") return Sequence(Token(LET));
  388.         if(s=="new") return Sequence(Token(NEW));
  389.         if(s=="return") return Sequence(Token(RETURN));
  390.         if(s=="switch") return Sequence(Token(SWITCH));
  391.         if(s=="this") return Sequence(Token(THIS));
  392.         if(s=="throw") return Sequence(Token(THROW));
  393.         if(s=="try") return Sequence(Token(TRY));
  394.         if(s=="typeof") return Sequence(Token(TYPEOF));
  395.         if(s=="var") return Sequence(Token(VAR));
  396.         if(s=="void") return Sequence(Token(VOID));
  397.         if(s=="while") return Sequence(Token(WHILE));
  398.         return Sequence(Token(NAME,s));
  399.     }
  400.    
  401.     void Sequence::lex(const std::string& code)
  402.     {
  403.         std::vector<char> buffer;
  404.         char temp=0;
  405.         bool multiCommentary=false, lineCommentary=false, quoteString=false, dbQuoteString=false;
  406.        
  407.         for(std::string::const_iterator it=code.begin();it!=code.end();it++)
  408.         {
  409.             if(multiCommentary)
  410.             {
  411.                 if(*it=='/' and temp=='*') { temp=0; multiCommentary=false; }
  412.                 if(*it=='*') temp=*it;
  413.                 else temp=0;
  414.             }
  415.             else if(lineCommentary)
  416.             {
  417.                 if(*it=='\n') { lineCommentary=false; }
  418.             }
  419.             else if(quoteString)
  420.             {
  421.                 if(*it=='\'' and temp!='\\')
  422.                 {
  423.                     temp=0; quoteString=false;
  424.                     (*this)+=Token(STRING,toStr(buffer));
  425.                     buffer.clear();
  426.                 }
  427.                 else
  428.                 {
  429.                     if(*it=='\\') { temp=*it; }
  430.                     else { temp=0; }
  431.                     buffer.push_back(*it);
  432.                 }
  433.             }
  434.             else if(dbQuoteString)
  435.             {
  436.                 if(*it=='"' and temp!='\\')
  437.                 {
  438.                     temp=0; dbQuoteString=false;
  439.                     (*this)+=Token(STRING,toStr(buffer));
  440.                     buffer.clear();
  441.                 }
  442.                 else
  443.                 {
  444.                     if(*it=='\\') { temp=*it; }
  445.                     else { temp=0; buffer.push_back(*it); }
  446.                 }
  447.             }
  448.             else
  449.             {
  450.                 if(*it=='<' or *it=='>' or *it==' ' or *it=='\n' or *it=='\r' or *it=='\t' or *it=='+' or *it=='-' or *it=='*' or *it=='/' or *it=='%' or *it=='=' or *it=='(' or *it==')' or *it=='{' or *it=='}' or *it=='[' or *it==']' or *it==',' or *it==';' or *it=='\'' or *it=='"')
  451.                 {
  452.                     if(!buffer.empty())
  453.                     {
  454.                         (*this)+=analyzeBuf(buffer);
  455.                         buffer.clear();
  456.                     }
  457.                    
  458.                     Token token;
  459.                     bool add=true;
  460.                     if(*it=='<') token.type=INFERIOR;
  461.                     if(*it=='>') token.type=SUPERIOR;
  462.                     if(*it=='+') { if(tokens.back().type==PLUS) { tokens[tokens.size()-1].type=DBPLUS; add=false; } else token.type=PLUS;}
  463.                     if(*it=='-') { if(tokens.back().type==MINUS) { tokens[tokens.size()-1].type=DBMINUS; add=false; } else token.type=MINUS;}
  464.                     if(*it=='*') { if(tokens.back().type==DIVIDE) { tokens.pop_back(); multiCommentary=true; add=false; } else token.type=MULTIPLY; }
  465.                     if(*it=='/') { if(tokens.back().type==DIVIDE) { tokens.pop_back(); lineCommentary=true; add=false; } else token.type=DIVIDE; }
  466.                     if(*it=='%') token.type=MODULO;
  467.                     if(*it=='\'') { quoteString=true; add=false; }
  468.                     if(*it=='"') { dbQuoteString=true; add=false; }
  469.                     if(*it==',') token.type=COMMA;
  470.                     if(*it==';') token.type=SEMICOLON;
  471.                     if(*it=='(') token.type=LPARENTHESIS;
  472.                     if(*it==')') token.type=RPARENTHESIS;
  473.                     if(*it=='{') token.type=LBRACKET;
  474.                     if(*it=='}') token.type=RBRACKET;
  475.                     if(*it=='[') token.type=LSQUARE;
  476.                     if(*it==']') token.type=RSQUARE;
  477.                     if(*it=='=') { if(tokens.back().type==EQUAL) { tokens[tokens.size()-1].type=DBEQUAL; add=false; } else token.type=EQUAL;}
  478.                    
  479.                     if(*it!=' ' && *it!='\n' && *it!='\r' && *it!='\t' && add) { (*this)+=token; }
  480.                 }
  481.                 else buffer.push_back(*it);
  482.             }
  483.         }
  484.         if(!buffer.empty())
  485.         {
  486.             (*this)+=analyzeBuf(buffer);
  487.         }
  488.     }
  489.    
  490. }
  491.  
  492. std::ostream& operator<<(std::ostream& stream,const lex::TokenType &tokenType)
  493. {
  494.     lex::Token(tokenType).printType(stream);
  495.     return stream;
  496. }
  497.  
  498. std::ostream& operator<<(std::ostream& stream,const lex::Token& token)
  499. {
  500.     token.print(stream);
  501.     return stream;
  502. }
  503.  
  504. std::ostream& operator<<(std::ostream& stream,const lex::Sequence& sequence)
  505. {
  506.     sequence.print(stream);
  507.     return stream;
  508. }
  509.  
  510. lex::Sequence operator+(const lex::Sequence &seq1,const lex::Sequence &seq2)
  511. {
  512.     lex::Sequence seqr(seq1);
  513.     seqr+=seq2;
  514.     return seqr;
  515. }
  516.  
  517. lex::Sequence operator+(const lex::Sequence &seq,const lex::Token &token)
  518. {
  519.     lex::Sequence seqr(seq);
  520.     seqr+=token;
  521.     return seqr;
  522. }
  523.  
  524. lex::Sequence operator+(const lex::Token &token1,const lex::Token &token2)
  525. {
  526.     lex::Sequence seqr(token1);
  527.     seqr+=token2;
  528.     return seqr;
  529. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement