| 1 |
|
|---|
| 2 |
/**********************************************************************/ |
|---|
| 3 |
/**********************************************************************/ |
|---|
| 4 |
/* DEFINITIONS */ |
|---|
| 5 |
/**********************************************************************/ |
|---|
| 6 |
/**********************************************************************/ |
|---|
| 7 |
|
|---|
| 8 |
%{ |
|---|
| 9 |
#define RPC_PARSER_YY_INCLUDED |
|---|
| 10 |
|
|---|
| 11 |
#include <string> |
|---|
| 12 |
#include <vector> |
|---|
| 13 |
#include <list> |
|---|
| 14 |
#include <iostream> |
|---|
| 15 |
#include <stdarg.h> |
|---|
| 16 |
#include "net/rpc/parser/rpc-parser.h" |
|---|
| 17 |
#include "net/rpc/parser/rpc-ptypes.h" |
|---|
| 18 |
#include "net/rpc/parser/export/rpc-base-types.h" |
|---|
| 19 |
#include "common/base/log.h" |
|---|
| 20 |
%} |
|---|
| 21 |
|
|---|
| 22 |
%option noyywrap |
|---|
| 23 |
%option yylineno |
|---|
| 24 |
%option yyclass="rpc::Parser" |
|---|
| 25 |
|
|---|
| 26 |
// The same definition order must be used in function StateName(..) |
|---|
| 27 |
%x S_COMMENT |
|---|
| 28 |
%x S_SERVICE_HEAD |
|---|
| 29 |
%x S_SERVICE_BODY |
|---|
| 30 |
%x S_FUNCTION_RETURN |
|---|
| 31 |
%x S_FUNCTION_NAME |
|---|
| 32 |
%x S_FUNCTION_PARAM_TYPE |
|---|
| 33 |
%x S_FUNCTION_PARAM_NAME |
|---|
| 34 |
%x S_CUSTOMTYPE_HEAD |
|---|
| 35 |
%x S_CUSTOMTYPE_BODY |
|---|
| 36 |
%x S_CUSTOMTYPE_ATTR |
|---|
| 37 |
%x S_CUSTOMTYPE_ATTR_CODE |
|---|
| 38 |
%x S_TYPE |
|---|
| 39 |
%x S_VERBATIM_HEAD |
|---|
| 40 |
%x S_VERBATIM_BODY |
|---|
| 41 |
|
|---|
| 42 |
// ! All C/C++ code must be indented by at least 1 space |
|---|
| 43 |
// or enclosed between %{} |
|---|
| 44 |
%{ |
|---|
| 45 |
|
|---|
| 46 |
// Another name for start condition INITIAL |
|---|
| 47 |
#define S_INITIAL 0 // INITIAL == 0 |
|---|
| 48 |
|
|---|
| 49 |
// Returns: name of the given start condition. |
|---|
| 50 |
const char * StateName(int sc); |
|---|
| 51 |
|
|---|
| 52 |
// Change start condition. This macro does not alter execution (like REJECT does). |
|---|
| 53 |
// Current state is lost; the lexer goes in the newState state. |
|---|
| 54 |
#define ChangeState(newState) {\ |
|---|
| 55 |
PRINT_INFO << "StateChange: " << StateName(YY_START) << " -> " << StateName(newState) << " at line " << lineno() << PRINT_END;\ |
|---|
| 56 |
BEGIN(newState);\ |
|---|
| 57 |
} |
|---|
| 58 |
|
|---|
| 59 |
// Change start condition. This macro does not alter execution (like REJECT does). |
|---|
| 60 |
// Current state is saved; the lexer goes to newState state; the old state can be restored with PopState. |
|---|
| 61 |
#define PushState(newState) {\ |
|---|
| 62 |
PRINT_INFO << "StateChange: " << StateName(YY_START) << " -> " << StateName(newState) << " at line " << lineno() << PRINT_END;\ |
|---|
| 63 |
yy_push_state(newState); /* save current state and BEGIN(newState) */\ |
|---|
| 64 |
} |
|---|
| 65 |
|
|---|
| 66 |
// Change back start condition to the one before the last PushState call. |
|---|
| 67 |
#define PopState() {\ |
|---|
| 68 |
int old_sc = YY_START;\ |
|---|
| 69 |
yy_pop_state(); /* restore last saved state */\ |
|---|
| 70 |
int new_sc = YY_START;\ |
|---|
| 71 |
PRINT_INFO << "StateChange: " << StateName(old_sc) << " -> " << StateName(new_sc) << " at line " << lineno() << PRINT_END;\ |
|---|
| 72 |
} |
|---|
| 73 |
|
|---|
| 74 |
#define SET_CRT_LOCATION(pfileinfo) { pfileinfo.filename_ = strFilename_; pfileinfo.lineno_ = lineno(); } |
|---|
| 75 |
|
|---|
| 76 |
// parser log. This log uses lexer's current state information. |
|---|
| 77 |
// |
|---|
| 78 |
#define PRINT_ERROR bErrorsFound_ = true; std::cerr << strFilename_ << ":" << lineno() << " error: " |
|---|
| 79 |
#define PRINT_WARNING std::cerr << strFilename_ << ":" << lineno() << " warning: " |
|---|
| 80 |
#define PRINT_INFO if(!bPrintInfo_); else std::cout << strFilename_ << ":" << lineno() << " info: " |
|---|
| 81 |
#define PRINT_END std::endl; |
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
%} |
|---|
| 85 |
|
|---|
| 86 |
DIGIT [0-9] |
|---|
| 87 |
ALPHA [a-zA-Z_] |
|---|
| 88 |
NAME [a-zA-Z_][a-zA-Z_0-9]* |
|---|
| 89 |
INTEGER {DIGIT}+ |
|---|
| 90 |
WS [ \t]+ |
|---|
| 91 |
TOKEN [^ \t\n]+ |
|---|
| 92 |
|
|---|
| 93 |
//SIMPLE_TYPENAME NAME |
|---|
| 94 |
//ARRAY_TYPENAME "array<"{NAME}">" |
|---|
| 95 |
//MAP_TYPENAME "map<"{NAME} |
|---|
| 96 |
|
|---|
| 97 |
//TYPENAME SIMPLE_TYPENAME | ARRAY_TYPENAME | MAP_TYPENAME |
|---|
| 98 |
|
|---|
| 99 |
/********************************************************************/ |
|---|
| 100 |
/********************************************************************/ |
|---|
| 101 |
%% /* RULES */ |
|---|
| 102 |
/********************************************************************/ |
|---|
| 103 |
/********************************************************************/ |
|---|
| 104 |
|
|---|
| 105 |
// ! All C/C++ code must be indented by at least 1 space or enclosed between %{} |
|---|
| 106 |
// All code in this section is local to the yylex() routine and executed |
|---|
| 107 |
// every time yylex() is called. |
|---|
| 108 |
|
|---|
| 109 |
PService crtService; // the current service. |
|---|
| 110 |
PFunction crtFunction; // the current function. |
|---|
| 111 |
PParam crtParam; // the current function parameter. |
|---|
| 112 |
PCustomType crtCustomType; // the current custom type. |
|---|
| 113 |
PAttribute crtAttribute; // the current custom type's attribute. |
|---|
| 114 |
bool crtAttributeRequirementSet = false; // true is "required" or "optional" was found. False otherwise. |
|---|
| 115 |
PType crtType; // the current type. |
|---|
| 116 |
PVerbatim crtVerbatim; // current verbatim stuff |
|---|
| 117 |
int verbatim_brackets = 0; |
|---|
| 118 |
|
|---|
| 119 |
// the current subtype (of the current type). Points to a node under crtType tree. |
|---|
| 120 |
// Used only by S_TYPE. |
|---|
| 121 |
PType * pcrtSubtype = &crtType; |
|---|
| 122 |
|
|---|
| 123 |
/*************************************/ |
|---|
| 124 |
/* verbatim */ |
|---|
| 125 |
/*************************************/ |
|---|
| 126 |
<S_VERBATIM_HEAD>{NAME} { |
|---|
| 127 |
if (crtVerbatim.language_ != "") { |
|---|
| 128 |
REJECT; |
|---|
| 129 |
} |
|---|
| 130 |
crtVerbatim.language_ = yytext; |
|---|
| 131 |
} |
|---|
| 132 |
<S_VERBATIM_HEAD>"{" { |
|---|
| 133 |
PopState(); |
|---|
| 134 |
PushState(S_VERBATIM_BODY); |
|---|
| 135 |
verbatim_brackets = 1; |
|---|
| 136 |
} |
|---|
| 137 |
|
|---|
| 138 |
<S_VERBATIM_BODY>"{" { |
|---|
| 139 |
crtVerbatim.verbatim_ += "{"; |
|---|
| 140 |
verbatim_brackets++; |
|---|
| 141 |
} |
|---|
| 142 |
<S_VERBATIM_BODY>"}" { |
|---|
| 143 |
verbatim_brackets--; |
|---|
| 144 |
if ( verbatim_brackets <= 0 ) { |
|---|
| 145 |
verbatim_.push_back(crtVerbatim); |
|---|
| 146 |
crtVerbatim.Clear(); |
|---|
| 147 |
PopState(); |
|---|
| 148 |
} else { |
|---|
| 149 |
crtVerbatim.verbatim_ += "}"; |
|---|
| 150 |
} |
|---|
| 151 |
} |
|---|
| 152 |
<S_VERBATIM_BODY>. { |
|---|
| 153 |
crtVerbatim.verbatim_ += yytext; |
|---|
| 154 |
} |
|---|
| 155 |
<S_VERBATIM_BODY>{NAME} { |
|---|
| 156 |
crtVerbatim.verbatim_ += yytext; |
|---|
| 157 |
} |
|---|
| 158 |
|
|---|
| 159 |
|
|---|
| 160 |
<*>"/""*"+ PushState(S_COMMENT); // save current state and BEGIN(S_COMMENT) |
|---|
| 161 |
<S_COMMENT>[^*]* /* eat anything that's not a '*' */ |
|---|
| 162 |
<S_COMMENT>"*"+[^/] /* eat up '*'s not followed by '/'s */ |
|---|
| 163 |
<S_COMMENT>"*"+"/" PopState(); // restore last saved state |
|---|
| 164 |
|
|---|
| 165 |
<*>"//".* { /* eat up one-line comments, without the \n terminator */ |
|---|
| 166 |
//yytext[yyleng-1]=0; // cut newline terminator |
|---|
| 167 |
//PRINT_INFO << "one line comment, at line " << lieno() << ": \"" << yytext << "\"" << PRINT_END; |
|---|
| 168 |
} |
|---|
| 169 |
|
|---|
| 170 |
<*>{WS} /* eat up whitespace */ |
|---|
| 171 |
|
|---|
| 172 |
<*>"*/" PRINT_WARNING << "Bad Comment Terminator" << PRINT_END; |
|---|
| 173 |
|
|---|
| 174 |
|
|---|
| 175 |
/*************************************/ |
|---|
| 176 |
/* initial */ |
|---|
| 177 |
/*************************************/ |
|---|
| 178 |
<INITIAL>"Service" { |
|---|
| 179 |
crtService.Clear(); |
|---|
| 180 |
SET_CRT_LOCATION(crtService); |
|---|
| 181 |
PushState(S_SERVICE_HEAD); |
|---|
| 182 |
} |
|---|
| 183 |
<INITIAL>"Type" { |
|---|
| 184 |
crtCustomType.Clear(); |
|---|
| 185 |
SET_CRT_LOCATION(crtCustomType); |
|---|
| 186 |
PushState(S_CUSTOMTYPE_HEAD); |
|---|
| 187 |
} |
|---|
| 188 |
<INITIAL>"Verbatim" { |
|---|
| 189 |
crtVerbatim.Clear(); |
|---|
| 190 |
SET_CRT_LOCATION(crtVerbatim); |
|---|
| 191 |
PushState(S_VERBATIM_HEAD); |
|---|
| 192 |
} |
|---|
| 193 |
|
|---|
| 194 |
/*************************************/ |
|---|
| 195 |
/* serviceheader */ |
|---|
| 196 |
/*************************************/ |
|---|
| 197 |
<S_SERVICE_HEAD>{NAME} { |
|---|
| 198 |
if(crtService.name_ != "") |
|---|
| 199 |
{ |
|---|
| 200 |
REJECT; // bad token after service name |
|---|
| 201 |
} |
|---|
| 202 |
crtService.name_ = yytext; |
|---|
| 203 |
PRINT_INFO << "Service: '" << crtService.name_ << "'" << PRINT_END; |
|---|
| 204 |
} |
|---|
| 205 |
|
|---|
| 206 |
<S_SERVICE_HEAD>"{" { |
|---|
| 207 |
PopState(); // exit S_SERVICE state |
|---|
| 208 |
PushState(S_SERVICE_BODY); // upon returning from S_SERVICE_BODY |
|---|
| 209 |
} |
|---|
| 210 |
|
|---|
| 211 |
/*************************************/ |
|---|
| 212 |
/* servicebody */ |
|---|
| 213 |
/*************************************/ |
|---|
| 214 |
<S_SERVICE_BODY>""/{NAME} { |
|---|
| 215 |
// found a function return type |
|---|
| 216 |
PushState(S_FUNCTION_RETURN); // enter S_FUNCTION_RETURN |
|---|
| 217 |
} |
|---|
| 218 |
<S_SERVICE_BODY>"}" { |
|---|
| 219 |
services_.push_back(crtService); |
|---|
| 220 |
crtService.Clear(); |
|---|
| 221 |
PopState(); // end of S_SERVICE_BODY |
|---|
| 222 |
} |
|---|
| 223 |
|
|---|
| 224 |
|
|---|
| 225 |
/*************************************/ |
|---|
| 226 |
/* function */ |
|---|
| 227 |
/*************************************/ |
|---|
| 228 |
<S_FUNCTION_RETURN>""/{NAME} { |
|---|
| 229 |
CHECK(crtFunction.output_.name_.empty()); |
|---|
| 230 |
CHECK(crtType.name_.empty()); |
|---|
| 231 |
|
|---|
| 232 |
// this is function return type |
|---|
| 233 |
PopState(); // exit S_FUNCTION_RETURN now |
|---|
| 234 |
PushState(S_FUNCTION_NAME); // enter S_FUNCTION_NAME |
|---|
| 235 |
PushState(S_TYPE); // enter S_TYPE (it will return to S_FUNCTION_NAME) |
|---|
| 236 |
} |
|---|
| 237 |
|
|---|
| 238 |
<S_FUNCTION_NAME>{NAME} { |
|---|
| 239 |
if(!crtType.name_.empty()) |
|---|
| 240 |
{ |
|---|
| 241 |
CHECK(crtFunction.output_.name_.empty()); |
|---|
| 242 |
|
|---|
| 243 |
crtFunction.output_ = crtType; |
|---|
| 244 |
crtType.Clear(); |
|---|
| 245 |
} |
|---|
| 246 |
|
|---|
| 247 |
if(crtFunction.name_.empty()) |
|---|
| 248 |
{ |
|---|
| 249 |
// this is function name |
|---|
| 250 |
crtFunction.name_ = yytext; |
|---|
| 251 |
SET_CRT_LOCATION(crtFunction); |
|---|
| 252 |
PRINT_INFO << "Function: '" << crtFunction.name_ << "'" << PRINT_END; |
|---|
| 253 |
} |
|---|
| 254 |
else |
|---|
| 255 |
{ |
|---|
| 256 |
PRINT_ERROR << "in function '" << crtFunction.name_ << "': unexpected identifier '" << yytext << "' after function name" << PRINT_END; |
|---|
| 257 |
} |
|---|
| 258 |
} |
|---|
| 259 |
|
|---|
| 260 |
<S_FUNCTION_NAME>"(" { |
|---|
| 261 |
if(!crtFunction.input_.empty()) |
|---|
| 262 |
{ |
|---|
| 263 |
// this function already has params. e.g. "void Foo (int) (float)" |
|---|
| 264 |
PRINT_ERROR << "in function '" << crtFunction.name_ << "': unexpected '(' after parameters list" << PRINT_END; |
|---|
| 265 |
yyterminate(); // fatal. Parsing these parameters would add up. Ignoring will screw up the following text. |
|---|
| 266 |
} |
|---|
| 267 |
PushState(S_FUNCTION_PARAM_TYPE); |
|---|
| 268 |
} |
|---|
| 269 |
|
|---|
| 270 |
<S_FUNCTION_NAME>";" { |
|---|
| 271 |
PRINT_INFO << "Function '" << crtFunction.name_ << "' declaration end" << PRINT_END; |
|---|
| 272 |
crtService.functions_.push_back(crtFunction); |
|---|
| 273 |
crtFunction.Clear(); |
|---|
| 274 |
|
|---|
| 275 |
// function declaration ended |
|---|
| 276 |
PopState(); |
|---|
| 277 |
} |
|---|
| 278 |
|
|---|
| 279 |
<S_FUNCTION_PARAM_TYPE>""/{NAME} { |
|---|
| 280 |
ChangeState(S_FUNCTION_PARAM_NAME); // return to S_FUNCTION_PARAM_NAME |
|---|
| 281 |
PushState(S_TYPE); // after reading type |
|---|
| 282 |
} |
|---|
| 283 |
<S_FUNCTION_PARAM_TYPE>")" { |
|---|
| 284 |
CHECK(crtType.name_.empty()); |
|---|
| 285 |
if(crtFunction.input_.empty()) |
|---|
| 286 |
{ // no parameter at all. This is legal: e.g. "void Foo()" |
|---|
| 287 |
} |
|---|
| 288 |
else // no type after comma. This is bad: e.g. "void Foo(int,)" |
|---|
| 289 |
{ |
|---|
| 290 |
PRINT_ERROR << "in function '" << crtFunction.name_ << "': expected type before ')'" << PRINT_END; |
|---|
| 291 |
} |
|---|
| 292 |
PopState(); |
|---|
| 293 |
} |
|---|
| 294 |
<S_FUNCTION_PARAM_TYPE>"," { // e.g. "void Foo(,int)" |
|---|
| 295 |
PRINT_ERROR << "in function '" << crtFunction.name_ << "': expected type before ','" << PRINT_END; |
|---|
| 296 |
} |
|---|
| 297 |
|
|---|
| 298 |
<S_FUNCTION_PARAM_NAME>{NAME} { |
|---|
| 299 |
CHECK(!crtType.name_.empty()); // you cannot reach S_FUNCTION_PARAM_NAME without reading a type first |
|---|
| 300 |
if(!crtParam.name_.empty()) |
|---|
| 301 |
{ |
|---|
| 302 |
// e.g. "void Foo(int x y);" // the 'y' was matched here. |
|---|
| 303 |
PRINT_ERROR << "multiple parameter names. First was '" << crtParam.name_ << "' and now '" << yytext << "'." << PRINT_END; |
|---|
| 304 |
break; |
|---|
| 305 |
} |
|---|
| 306 |
crtParam.name_ = yytext; |
|---|
| 307 |
PRINT_INFO << "Param name: " << crtParam.name_ << PRINT_END; |
|---|
| 308 |
} |
|---|
| 309 |
|
|---|
| 310 |
<S_FUNCTION_PARAM_NAME>"," | |
|---|
| 311 |
<S_FUNCTION_PARAM_NAME>")" { |
|---|
| 312 |
CHECK(!crtType.name_.empty()); |
|---|
| 313 |
|
|---|
| 314 |
crtParam.type_ = crtType; |
|---|
| 315 |
crtType.Clear(); |
|---|
| 316 |
|
|---|
| 317 |
// if not specified, auto-generate parameter name |
|---|
| 318 |
if(crtParam.name_.empty()) |
|---|
| 319 |
{ |
|---|
| 320 |
char szName[8] = {0,}; |
|---|
| 321 |
#if __WORDSIZE == 64 |
|---|
| 322 |
snprintf(szName, sizeof(szName), "arg%ld", crtFunction.input_.size()); |
|---|
| 323 |
#else |
|---|
| 324 |
snprintf(szName, sizeof(szName), "arg%d", crtFunction.input_.size()); |
|---|
| 325 |
#endif |
|---|
| 326 |
crtParam.name_ = szName; |
|---|
| 327 |
} |
|---|
| 328 |
PRINT_INFO << "Add function parameter: '" << crtParam.type_ << " " << crtParam.name_ << "' on current symbol: '" << yytext << "'" << PRINT_END; |
|---|
| 329 |
crtFunction.input_.push_back(crtParam); |
|---|
| 330 |
crtParam.Clear(); |
|---|
| 331 |
|
|---|
| 332 |
if(yytext[0] == ',') |
|---|
| 333 |
{ |
|---|
| 334 |
ChangeState(S_FUNCTION_PARAM_TYPE); // type expected after ',' |
|---|
| 335 |
} |
|---|
| 336 |
else // yytext[0] == ')' |
|---|
| 337 |
{ |
|---|
| 338 |
PopState(); // parameters list ended |
|---|
| 339 |
} |
|---|
| 340 |
} |
|---|
| 341 |
|
|---|
| 342 |
/*************************************/ |
|---|
| 343 |
/* custom type name */ |
|---|
| 344 |
/*************************************/ |
|---|
| 345 |
<S_CUSTOMTYPE_HEAD>{NAME} { |
|---|
| 346 |
if(crtCustomType.name_.empty()) |
|---|
| 347 |
{ |
|---|
| 348 |
crtCustomType.name_ = yytext; |
|---|
| 349 |
PRINT_INFO << "CustomType: " << crtCustomType.name_ << PRINT_END; |
|---|
| 350 |
} |
|---|
| 351 |
else |
|---|
| 352 |
{ // e.g. "Type Person XXX {' // 'XXX' is matched here |
|---|
| 353 |
PRINT_ERROR << "unexpected identifier '" << yytext << "' after custom type name" << PRINT_END; |
|---|
| 354 |
} |
|---|
| 355 |
} |
|---|
| 356 |
|
|---|
| 357 |
<S_CUSTOMTYPE_HEAD>"{" { |
|---|
| 358 |
CHECK(crtCustomType.attributes_.empty()); |
|---|
| 359 |
PopState(); // exit current state |
|---|
| 360 |
PushState(S_CUSTOMTYPE_BODY); // on return from body |
|---|
| 361 |
} |
|---|
| 362 |
|
|---|
| 363 |
/*************************************/ |
|---|
| 364 |
/* custom type body */ |
|---|
| 365 |
/*************************************/ |
|---|
| 366 |
<S_CUSTOMTYPE_BODY>""/{NAME} { |
|---|
| 367 |
crtAttribute.Clear(); |
|---|
| 368 |
crtAttributeRequirementSet = false; |
|---|
| 369 |
SET_CRT_LOCATION(crtAttribute); |
|---|
| 370 |
PushState(S_CUSTOMTYPE_ATTR); // a new attribute begins |
|---|
| 371 |
} |
|---|
| 372 |
<S_CUSTOMTYPE_BODY>"}" { |
|---|
| 373 |
customTypes_.push_back(crtCustomType); |
|---|
| 374 |
crtCustomType.Clear(); |
|---|
| 375 |
PopState(); |
|---|
| 376 |
} |
|---|
| 377 |
|
|---|
| 378 |
<S_CUSTOMTYPE_ATTR>"optional" | |
|---|
| 379 |
<S_CUSTOMTYPE_ATTR>"required" { |
|---|
| 380 |
if(crtAttributeRequirementSet) |
|---|
| 381 |
{ |
|---|
| 382 |
// e.g. "optional required int x;" // matches the "required" keyword |
|---|
| 383 |
PRINT_ERROR << "duplicate required/optional keyword" << PRINT_END; |
|---|
| 384 |
break; |
|---|
| 385 |
} |
|---|
| 386 |
crtAttribute.isOptional_ = (yytext[0] == 'o'); |
|---|
| 387 |
crtAttributeRequirementSet = true; |
|---|
| 388 |
} |
|---|
| 389 |
<S_CUSTOMTYPE_ATTR>""/{NAME} { |
|---|
| 390 |
if(!crtType.name_.empty() || !crtAttribute.type_.name_.empty()) |
|---|
| 391 |
{ |
|---|
| 392 |
REJECT; // type already found |
|---|
| 393 |
} |
|---|
| 394 |
PushState(S_TYPE); |
|---|
| 395 |
} |
|---|
| 396 |
<S_CUSTOMTYPE_ATTR>{NAME} { |
|---|
| 397 |
if(!crtType.name_.empty()) // copy crtType to crtAttribute |
|---|
| 398 |
{ |
|---|
| 399 |
CHECK(crtAttribute.type_.name_.empty()); |
|---|
| 400 |
crtAttribute.type_ = crtType; |
|---|
| 401 |
crtType.Clear(); |
|---|
| 402 |
} |
|---|
| 403 |
|
|---|
| 404 |
if(crtAttribute.name_.empty()) |
|---|
| 405 |
{ |
|---|
| 406 |
crtAttribute.name_ = yytext; |
|---|
| 407 |
PRINT_INFO << "Attribute name: " << crtAttribute.name_ << PRINT_END; |
|---|
| 408 |
} |
|---|
| 409 |
else |
|---|
| 410 |
{ |
|---|
| 411 |
// e.g. "int x y = 7" // 'y' is matched here |
|---|
| 412 |
PRINT_ERROR << "missing ';' after \"" << crtAttribute.name_ << "\"" << PRINT_END; |
|---|
| 413 |
PRINT_ERROR << "unexpected identifier '" << yytext << "' after attribute name '" << crtAttribute.name_ << "'" << PRINT_END; |
|---|
| 414 |
} |
|---|
| 415 |
} |
|---|
| 416 |
<S_CUSTOMTYPE_ATTR>";" { |
|---|
| 417 |
bool bError = false; |
|---|
| 418 |
if(!crtType.name_.empty()) // copy crtType to crtAttribute |
|---|
| 419 |
{ |
|---|
| 420 |
CHECK(crtAttribute.type_.name_.empty()); |
|---|
| 421 |
crtAttribute.type_ = crtType; |
|---|
| 422 |
crtType.Clear(); |
|---|
| 423 |
} |
|---|
| 424 |
if(crtAttribute.type_.name_.empty()) |
|---|
| 425 |
{ |
|---|
| 426 |
PRINT_ERROR << "missing attribute type before ';'" << PRINT_END; |
|---|
| 427 |
bError = true; |
|---|
| 428 |
} |
|---|
| 429 |
if(crtAttribute.name_.empty()) |
|---|
| 430 |
{ |
|---|
| 431 |
PRINT_ERROR << "missing attribute name before ';'" << PRINT_END; |
|---|
| 432 |
bError = true; |
|---|
| 433 |
} |
|---|
| 434 |
|
|---|
| 435 |
if(!bError) |
|---|
| 436 |
{ |
|---|
| 437 |
crtCustomType.attributes_.push_back(crtAttribute); |
|---|
| 438 |
} |
|---|
| 439 |
|
|---|
| 440 |
crtAttribute.Clear(); |
|---|
| 441 |
crtAttributeRequirementSet = false; |
|---|
| 442 |
PopState(); |
|---|
| 443 |
} |
|---|
| 444 |
<S_CUSTOMTYPE_ATTR>"}" { |
|---|
| 445 |
if(!crtType.name_.empty()) // copy crtType to crtAttribute |
|---|
| 446 |
{ |
|---|
| 447 |
CHECK(crtAttribute.type_.name_.empty()); |
|---|
| 448 |
crtAttribute.type_ = crtType; |
|---|
| 449 |
crtType.Clear(); |
|---|
| 450 |
} |
|---|
| 451 |
CHECK(!crtAttribute.type_.name_.empty()); // we are inside an attribute, so at least the typename should have been matched |
|---|
| 452 |
if(crtAttribute.name_.empty()) |
|---|
| 453 |
{ |
|---|
| 454 |
PRINT_ERROR << "missing identifier after type \"" << crtAttribute.type_.name_ << "\"" << PRINT_END; |
|---|
| 455 |
} |
|---|
| 456 |
PRINT_ERROR << "missing ';'" << PRINT_END; |
|---|
| 457 |
|
|---|
| 458 |
crtAttribute.Clear(); |
|---|
| 459 |
crtAttributeRequirementSet = false; |
|---|
| 460 |
PopState(); // exit S_CUSTOMTYPE_ATTR to S_CUSTOMTYPE_BODY |
|---|
| 461 |
crtCustomType.Clear(); |
|---|
| 462 |
PopState(); // exit S_CUSTOMTYPE_BODY to INITIAL |
|---|
| 463 |
} |
|---|
| 464 |
|
|---|
| 465 |
/*************************************/ |
|---|
| 466 |
/* type */ |
|---|
| 467 |
/*************************************/ |
|---|
| 468 |
<S_TYPE>{NAME} { |
|---|
| 469 |
if(crtType.name_.empty()) |
|---|
| 470 |
{ |
|---|
| 471 |
pcrtSubtype = &crtType; // begin from top level |
|---|
| 472 |
} |
|---|
| 473 |
if(!pcrtSubtype->name_.empty()) |
|---|
| 474 |
{ |
|---|
| 475 |
PRINT_ERROR << "unexpected identifier '" << yytext << "' while waiting for terminator '>'" << PRINT_END; |
|---|
| 476 |
yyterminate(); // fatal. Forgeting a '>' => the rest of the text is interpreted as type. |
|---|
| 477 |
} |
|---|
| 478 |
pcrtSubtype->name_ = yytext; |
|---|
| 479 |
PRINT_INFO << "Simple type name: " << pcrtSubtype->name_ << PRINT_END; |
|---|
| 480 |
PopState(); |
|---|
| 481 |
} |
|---|
| 482 |
<S_TYPE>"array<" { // cannot use RPC_ARRAY instead of "array". Flex analyzer does not expand macros. |
|---|
| 483 |
pcrtSubtype->name_ = RPC_ARRAY; |
|---|
| 484 |
pcrtSubtype->subtype1_ = new PType(); |
|---|
| 485 |
pcrtSubtype->subtype1_->parent_ = pcrtSubtype; |
|---|
| 486 |
pcrtSubtype = pcrtSubtype->subtype1_; |
|---|
| 487 |
PushState(S_TYPE); |
|---|
| 488 |
} |
|---|
| 489 |
<S_TYPE>"map<" { |
|---|
| 490 |
pcrtSubtype->name_ = RPC_MAP; |
|---|
| 491 |
pcrtSubtype->subtype1_ = new PType(); |
|---|
| 492 |
pcrtSubtype->subtype1_->parent_ = pcrtSubtype; |
|---|
| 493 |
pcrtSubtype->subtype2_ = new PType(); |
|---|
| 494 |
pcrtSubtype->subtype2_->parent_ = pcrtSubtype; |
|---|
| 495 |
pcrtSubtype = pcrtSubtype->subtype1_; |
|---|
| 496 |
PushState(S_TYPE); |
|---|
| 497 |
} |
|---|
| 498 |
<S_TYPE>"," { |
|---|
| 499 |
CHECK(pcrtSubtype->parent_); |
|---|
| 500 |
if(pcrtSubtype->name_.empty()) |
|---|
| 501 |
{ |
|---|
| 502 |
PRINT_ERROR << "missing template parameter before ','" << PRINT_END; |
|---|
| 503 |
PopState(); |
|---|
| 504 |
} |
|---|
| 505 |
if(pcrtSubtype == pcrtSubtype->parent_->subtype2_) |
|---|
| 506 |
{ |
|---|
| 507 |
PRINT_ERROR << "too many template parameters for type map" << PRINT_END; |
|---|
| 508 |
yyterminate(); //PopState(); |
|---|
| 509 |
} |
|---|
| 510 |
if(pcrtSubtype->parent_->subtype2_ == NULL) |
|---|
| 511 |
{ |
|---|
| 512 |
PRINT_ERROR << "too many template parameters for type array" << PRINT_END; |
|---|
| 513 |
yyterminate(); //PopState(); |
|---|
| 514 |
} |
|---|
| 515 |
pcrtSubtype = pcrtSubtype->parent_; |
|---|
| 516 |
pcrtSubtype = pcrtSubtype->subtype2_; |
|---|
| 517 |
PushState(S_TYPE); |
|---|
| 518 |
} |
|---|
| 519 |
|
|---|
| 520 |
<S_TYPE>">" { |
|---|
| 521 |
CHECK(pcrtSubtype->parent_); |
|---|
| 522 |
if(pcrtSubtype->name_.empty()) |
|---|
| 523 |
{ |
|---|
| 524 |
PRINT_ERROR << "missing template parameter before '>'" << PRINT_END; |
|---|
| 525 |
PopState(); |
|---|
| 526 |
} |
|---|
| 527 |
pcrtSubtype = pcrtSubtype->parent_; |
|---|
| 528 |
if(pcrtSubtype->subtype2_ && pcrtSubtype->subtype2_->name_.empty()) |
|---|
| 529 |
{ |
|---|
| 530 |
PRINT_ERROR << "type map needs 2 template parameters" << PRINT_END; |
|---|
| 531 |
PopState(); |
|---|
| 532 |
} |
|---|
| 533 |
PRINT_INFO << "Complex type name: " << (*pcrtSubtype) << PRINT_END; |
|---|
| 534 |
PopState(); |
|---|
| 535 |
} |
|---|
| 536 |
|
|---|
| 537 |
/*************************************/ |
|---|
| 538 |
/* global rules with low priority */ |
|---|
| 539 |
/*************************************/ |
|---|
| 540 |
|
|---|
| 541 |
<*>\n /* eat up line feeds */ |
|---|
| 542 |
|
|---|
| 543 |
/** |
|---|
| 544 |
* Print an error for unmatched characters. |
|---|
| 545 |
* |
|---|
| 546 |
* NOTE: this MUST be the LAST rule! |
|---|
| 547 |
* Because you may want to match correctly some simple characters like: + - = . |
|---|
| 548 |
* using one of the above rules. The rule here takes action only if all the above |
|---|
| 549 |
* rules failed. |
|---|
| 550 |
*/ |
|---|
| 551 |
<*>{NAME} PRINT_ERROR << "Bad syntax: unrecognized token \"" << yytext << "\"" << PRINT_END; |
|---|
| 552 |
<*>. PRINT_ERROR << "Bad syntax: unrecognized symbol \"" << yytext << "\"" << PRINT_END; |
|---|
| 553 |
|
|---|
| 554 |
/********************************************************************/ |
|---|
| 555 |
/********************************************************************/ |
|---|
| 556 |
%% /* USER CODE */ |
|---|
| 557 |
/********************************************************************/ |
|---|
| 558 |
/********************************************************************/ |
|---|
| 559 |
|
|---|
| 560 |
const char * StateName(int sc) |
|---|
| 561 |
{ |
|---|
| 562 |
switch(sc) |
|---|
| 563 |
{ |
|---|
| 564 |
case S_INITIAL: return "Initial"; |
|---|
| 565 |
case S_COMMENT: return "Comment"; |
|---|
| 566 |
case S_SERVICE_HEAD: return "ServiceHead"; |
|---|
| 567 |
case S_SERVICE_BODY: return "ServiceBody"; |
|---|
| 568 |
case S_FUNCTION_RETURN: return "FunctionReturn"; |
|---|
| 569 |
case S_FUNCTION_NAME: return "FunctionName"; |
|---|
| 570 |
case S_FUNCTION_PARAM_TYPE: return "FunctionParamType"; |
|---|
| 571 |
case S_FUNCTION_PARAM_NAME: return "FunctionParamName"; |
|---|
| 572 |
case S_CUSTOMTYPE_HEAD: return "CustomTypeHead"; |
|---|
| 573 |
case S_CUSTOMTYPE_BODY: return "CustomTypeBody"; |
|---|
| 574 |
case S_CUSTOMTYPE_ATTR: return "CustomTypeAttr"; |
|---|
| 575 |
case S_CUSTOMTYPE_ATTR_CODE: return "CustomTypeAttrCode"; |
|---|
| 576 |
case S_TYPE: return "Type"; |
|---|
| 577 |
default: return "Unrecognized state"; |
|---|
| 578 |
}; |
|---|
| 579 |
} |
|---|
| 580 |
|
|---|
| 581 |
rpc::Parser::Parser(std::istream & input, |
|---|
| 582 |
std::ostream & output, |
|---|
| 583 |
PCustomTypeArray & customTypes, |
|---|
| 584 |
PServiceArray & services, |
|---|
| 585 |
PVerbatimArray & verbatim, |
|---|
| 586 |
const char * filename, |
|---|
| 587 |
bool bPrintInfo) |
|---|
| 588 |
: yyFlexLexer(&input, &output), |
|---|
| 589 |
customTypes_(customTypes), |
|---|
| 590 |
services_(services), |
|---|
| 591 |
verbatim_(verbatim), |
|---|
| 592 |
strFilename_(filename), |
|---|
| 593 |
bErrorsFound_(false), |
|---|
| 594 |
bPrintInfo_(bPrintInfo) |
|---|
| 595 |
{ |
|---|
| 596 |
} |
|---|
| 597 |
rpc::Parser::~Parser() |
|---|
| 598 |
{ |
|---|
| 599 |
} |
|---|
| 600 |
|
|---|
| 601 |
bool rpc::Parser::Run() |
|---|
| 602 |
{ |
|---|
| 603 |
while(yylex() != 0) |
|---|
| 604 |
; |
|---|
| 605 |
return !bErrorsFound_; |
|---|
| 606 |
} |
|---|