You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

121 lines
2.4 KiB

%require "3.2"
%language "c++"
%define api.prefix {ifdata}
%define api.namespace {a2l}
%define api.parser.class {IfDataParser}
%code requires {
#include <string>
#include <vector>
#include <map>
#include <utility>
#include "a2l/ifdataitem.h"
namespace a2l {
class IfDataScanner;
}
}
%parse-param { a2l::IfDataScanner &scanner }
%code {
#include <sstream>
#include "ifdatascanner.h"
#include "a2lhelper.h"
#include <limits>
#undef yylex
#define yylex scanner.ifdatalex
}
%define api.value.type variant
%token IF_DATA_BEGIN
%token IF_DATA_END
%token <uint64_t> UINT
%token <uint64_t> HEX
%token <int64_t> INT
%token <double> FLOAT
%token <std::string> IDENT
%token IF_DATA
%token <std::string> STRING
%nterm <std::string> protocol
%nterm <std::vector<a2l::IfDataItem>> block_data_list
%nterm <a2l::IfDataItem> block_data
%nterm <std::string> item_value
%nterm <std::string> block_name
%nterm <std::vector<a2l::IfDataItem>> item_list
%start if_data_block
%%
if_data_block: %empty
| IF_DATA_BEGIN IF_DATA protocol block_data_list IF_DATA_END IF_DATA {
scanner.Protocol($3);
scanner.ItemList($4);
};
protocol: IDENT;
block_data_list: %empty {}
| block_data_list block_data {
$$ = $1;
$$.emplace_back($2);
}
| block_data_list item_value {
$$ = $1;
IfDataItem item;
item.Value = $2;
$$.emplace_back($2);
};
block_data: IF_DATA_BEGIN block_name item_list IF_DATA_END block_name {
IfDataItem block;
block.BlockName = $2;
block.ItemList = $3;
$$ = block;
};
block_name: IDENT { $$ = $1; };
item_list: %empty {}
| item_list block_data {
$$ = $1;
$$.emplace_back($2);
}
| item_list item_value {
$$ = $1;
IfDataItem item;
item.Value = $2;
$$.emplace_back($2);
};
item_value: IDENT { $$ = $1; }
| STRING { $$ = $1; }
| HEX { $$ = std::to_string($1); }
| UINT { $$ = std::to_string($1); }
| INT { $$ = std::to_string($1); }
| FLOAT { $$ = std::to_string($1); };
%%
void a2l::IfDataParser::error(const std::string& err) {
const auto line = scanner.lineno();
// const auto column = scanner.YYLeng();
const std::string near = scanner.YYText() != nullptr ? scanner.YYText() : "";
std::ostringstream error;
error << "Parser error: " << err
<< ", Line: " << line
<< ", Near: " << near;
scanner.LastError(error.str());
}