1 /*
2  * Copyright (c) 2015 PLUMgrid, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #ifndef yyFlexLexerOnce
20 #undef yyFlexLexer
21 #define yyFlexLexer ebpfccFlexLexer
22 #include <FlexLexer.h>
23 #endif
24 
25 #undef YY_DECL
26 #define YY_DECL int ebpf::cc::Lexer::yylex()
27 
28 #include <iostream> // NOLINT
29 #include <list>
30 #include "parser.yy.hh"
31 
32 namespace ebpf {
33 namespace cc {
34 
35 typedef BisonParser::token::yytokentype Tok;
36 
37 class Lexer : public yyFlexLexer {
38  public:
Lexer(std::istream * in)39   explicit Lexer(std::istream* in)
40       : yyFlexLexer(in), prev_tok_(Tok::TSEMI), lines_({""}), yylval_(NULL), yylloc_(NULL) {
41     if (!in || !*in)
42       fprintf(stderr, "Unable to open input stream\n");
43   }
yylex(BisonParser::semantic_type * lval,BisonParser::location_type * lloc)44   int yylex(BisonParser::semantic_type *lval, BisonParser::location_type *lloc) {
45     yylval_ = lval;
46     yylloc_ = lloc;
47     return yylex();
48   }
text(const BisonParser::location_type & loc)49   std::string text(const BisonParser::location_type& loc) const {
50     return text(loc.begin, loc.end);
51   }
text(const position & begin,const position & end)52   std::string text(const position& begin, const position& end) const {
53     std::string result;
54     for (size_t i = begin.line; i <= end.line; ++i) {
55       if (i == begin.line && i == end.line) {
56         result += lines_.at(i - 1).substr(begin.column - 1, end.column - begin.column);
57       } else if (i == begin.line && i < end.line) {
58         result += lines_.at(i - 1).substr(begin.column - 1);
59       } else if (i > begin.line && i == end.line) {
60         result += lines_.at(i - 1).substr(0, end.column);
61       } else if (i > begin.line && i == end.line) {
62         result += lines_.at(i - 1);
63       }
64     }
65     return result;
66   }
67  private:
68 
69   // true if a semicolon should be replaced here
next_line()70   bool next_line() {
71     lines_.push_back("");
72     yylloc_->lines();
73     yylloc_->step();
74     switch (prev_tok_) {
75     case Tok::TIDENTIFIER:
76     case Tok::TINTEGER:
77     case Tok::THEXINTEGER:
78     case Tok::TRBRACE:
79     case Tok::TRPAREN:
80     case Tok::TRBRACK:
81     case Tok::TTRUE:
82     case Tok::TFALSE:
83       // uncomment to add implicit semicolons
84       //return true;
85     default:
86       break;
87     }
88     return false;
89   }
90 
91   Tok save(Tok tok, bool ignore_text = false) {
92     if (!ignore_text) {
93       save_text();
94     }
95 
96     switch (tok) {
97     case Tok::TIDENTIFIER:
98     case Tok::TINTEGER:
99     case Tok::THEXINTEGER:
100       yylval_->string = new std::string(yytext, yyleng);
101       break;
102     default:
103       yylval_->token = tok;
104     }
105     prev_tok_ = tok;
106     return tok;
107   }
108 
109   /*
110   std::string * alloc_string(const char *c, size_t len) {
111     strings_.push_back(std::unique_ptr<std::string>(new std::string(c, len)));
112     return strings_.back().get();
113   }
114 
115   std::string * alloc_string(const std::string &s) {
116     strings_.push_back(std::unique_ptr<std::string>(new std::string(s)));
117     return strings_.back().get();
118   }
119   */
120 
save_text()121   void save_text() {
122     lines_.back().append(yytext, yyleng);
123     yylloc_->columns(yyleng);
124   }
125 
126   int yylex();
127   Tok prev_tok_;
128   std::vector<std::string> lines_;
129   //std::list<std::unique_ptr<std::string>> strings_;
130   BisonParser::semantic_type *yylval_;
131   BisonParser::location_type *yylloc_;
132 };
133 
134 }  // namespace cc
135 }  // namespace ebpf
136