should work
[c11concurrency-benchmarks.git] / mabain / binaries / expr_parser.cpp
1 /**
2  * Copyright (C) 2017 Cisco Inc.
3  *
4  * This program is free software: you can redistribute it and/or  modify
5  * it under the terms of the GNU General Public License, version 2,
6  * as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 // @author Changxue Deng <chadeng@cisco.com>
18
19 #include <string.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <iostream>
23
24 #include "expr_parser.h"
25 #include "hexbin.h"
26
27 ExprParser::ExprParser(const std::string &exp)
28 {
29     pos = 0;
30     expr = exp;
31     err_str = "";
32 }
33
34 ExprParser::~ExprParser()
35 {
36 }
37
38 int ExprParser::Evaluate(std::string &result)
39 {
40     result = "";
41     int rval = Parse(result);
42     if(rval < 0)
43     {
44         std::cout << err_str << "\n";
45     }
46     else if(rval == 0 && pos < expr.length())
47     {
48         std::cout << "extra string " + expr.substr(pos)
49                   << " found at the end of expression\n";
50         return -1;
51     }
52
53     return rval;
54 }
55
56 // Grammer:
57 //    S ---> E
58 //    E ---> bin( E )
59 //    E ---> hex( E )
60 //    E ---> T
61 //    E ---> T + E (NOT IMPLEMENTED YET)
62 //    T ---> literal string
63 // Sample expressions
64 // literal string: 'abcdefg'
65 // convert hex to binary: bin('0001ff01')
66 // convert hex to binary and back to hex:
67 // hex(bin('4da32feebf1611e7bd98c0b13cdb778c'))=='4da32feebf1611e7bd98c0b13cdb778c'
68 int ExprParser::Parse(std::string &result)
69 {
70     if(pos >= expr.length())
71         return 0;
72
73     int rval;
74     switch(expr[pos])
75     {
76         case 'b':
77             if(expr.find("in(", pos+1, 3) == std::string::npos)
78             {
79                 err_str = "unrecognized expression " + expr.substr(pos);
80                 return -1;
81             }
82             pos += 4;
83             rval = Parse(result);
84             if(rval < 0)
85                 return rval;
86             if(expr[pos] != ')')
87             {
88                 err_str = "missing ) at the end of " + expr.substr(0, pos);
89                 return -1;
90             }
91             pos++;
92             rval = hex_2_bin(result.c_str(), result.length(), buffer,
93                              EXPR_PARSER_BUFFER_SIZE);
94             if(rval < 0)
95             {
96                 err_str = "failed to convert hex string " + result + " to binary format";
97                 return -1;
98             }
99             result = std::string((char *)buffer, rval);
100             break;
101         case 'h':
102             if(expr.find("ex(", pos+1, 3) == std::string::npos)
103             {
104                 err_str = "unrecognized expression " + expr.substr(pos);
105                 return -1;
106             }
107             pos += 4;
108             rval = Parse(result);
109             if(rval < 0)
110                 return rval;
111             if(expr[pos] != ')')
112             {
113                 err_str = "missing ) at the end of " + expr.substr(0, pos);
114                 return -1;
115             }
116             pos++;
117             rval = bin_2_hex((const uint8_t *)result.data(), result.size(),
118                              (char *)buffer, EXPR_PARSER_BUFFER_SIZE);
119             if(rval < 0)
120             {
121                 err_str = "failed to convert binary string to hex";
122                 return -1;
123             }
124             result = std::string((char *)buffer, rval);
125             break;
126         case '\'':
127             {
128                 size_t endp = expr.find('\'', pos+1);
129                 if(endp ==  std::string::npos)
130                 {
131                     err_str = "expression " + expr.substr(0, pos) + " missing closing \'";
132                     return -1;
133                 }
134                 result = expr.substr(pos+1, endp-pos-1);
135                 pos = endp + 1;
136             }
137             break;
138         default:
139             err_str  = "unrecognized expression " + expr.substr(pos) + "\n";
140             err_str += "                        ^";
141             return -1; 
142     }
143
144     return 0;
145 }