progress
This commit is contained in:
parent
a0c3b2e9a7
commit
738410da8c
4 changed files with 340 additions and 72 deletions
|
|
@ -1,7 +1,8 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(MultiversalHeaders)
|
||||
|
||||
set(CXX_STANDARD_REQUIRED 17)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 17)
|
||||
|
||||
set(CMAKE_PROGRAM_PATH ${CMAKE_PROGRAM_PATH} "/usr/local/opt/bison/bin")
|
||||
find_package(BISON 3.0.2)
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ static std::string strip(const char *p, const char *q)
|
|||
%option noyywrap
|
||||
|
||||
%x preamble
|
||||
%x executor_only
|
||||
|
||||
%%
|
||||
using hp = yy::HeaderParser;
|
||||
using token = hp::token;
|
||||
atBOL = false;
|
||||
|
||||
^"#if !defined(_"[A-Z_]+_H_")"$ BEGIN(preamble);
|
||||
^"#if !defined(_"[A-Za-z0-9_]+_H_")"$ BEGIN(preamble);
|
||||
|
||||
<preamble>^"namespace Executor" BEGIN(INITIAL);
|
||||
<preamble>.|\n ;
|
||||
|
|
@ -92,7 +93,11 @@ static std::string strip(const char *p, const char *q)
|
|||
|
||||
[[:alpha:]_][[:alnum:]_]* return hp::make_IDENTIFIER(yytext);
|
||||
|
||||
^" "*#.* ;
|
||||
^" "*#.*(\\\n.*)* return hp::make_EXECUTOR_ONLY(yytext);
|
||||
|
||||
^"BEGIN_EXECUTOR_ONLY"\n BEGIN(executor_only);
|
||||
<executor_only>^"END_EXECUTOR_ONLY"\n BEGIN(INITIAL); atBOL = true;
|
||||
<executor_only>.*\n return hp::make_EXECUTOR_ONLY(std::string(yytext, yytext + yyleng - 1));
|
||||
|
||||
"/*"[^*]*("*"+[^*/]*)*"*"+"/" {
|
||||
if(atBOL)
|
||||
|
|
|
|||
385
HeaderParser.yy
385
HeaderParser.yy
|
|
@ -15,6 +15,7 @@
|
|||
%token<std::string> CHARLIT;
|
||||
%token<std::string> COMMENT;
|
||||
%token<std::string> RIGHTCOMMENT;
|
||||
%token<std::string> EXECUTOR_ONLY;
|
||||
|
||||
%token LEFTBRACE "{";
|
||||
%token RIGHTBRACE "}";
|
||||
|
|
@ -71,15 +72,13 @@
|
|||
|
||||
%token FOURCC "FOURCC";
|
||||
|
||||
%type <YAML::Node> declaration enum struct typedef lowmem trap function size_assertion enum_value
|
||||
%type <std::vector<YAML::Node>> enum_values enum_values1
|
||||
%type <std::string> comments rcomment
|
||||
%type <std::vector<YAML::Node>> struct_members
|
||||
%type <YAML::Node> struct_member
|
||||
%type <std::string> expression
|
||||
%left EXECUTOR_ONLY;
|
||||
%right COMMENT;
|
||||
|
||||
%code requires {
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
}
|
||||
%code provides {
|
||||
yy::HeaderParser::symbol_type yylex();
|
||||
|
|
@ -87,7 +86,34 @@
|
|||
%code {
|
||||
#include <stack>
|
||||
|
||||
YAML::Emitter yamlout;
|
||||
std::vector<YAML::Node> things;
|
||||
std::unordered_map<std::string, int> names;
|
||||
int gAnonymousIndex = 0;
|
||||
|
||||
std::ostringstream executorOnly;
|
||||
|
||||
void declare(YAML::Node node)
|
||||
{
|
||||
things.push_back(std::move(node));
|
||||
if(node.begin()->second["name"])
|
||||
names[node.begin()->second["name"].as<std::string>()] = things.size() - 1;
|
||||
}
|
||||
|
||||
void renameThing(const std::string& name, const std::string& newName)
|
||||
{
|
||||
auto p = names.find(name);
|
||||
if(p != names.end())
|
||||
{
|
||||
int idx = p->second;
|
||||
names.erase(p);
|
||||
names[newName] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
YAML::Node& thingByName(const std::string& name)
|
||||
{
|
||||
return things[names[name]];
|
||||
}
|
||||
|
||||
void yy::HeaderParser::error(std::string const& err)
|
||||
{
|
||||
|
|
@ -160,56 +186,71 @@
|
|||
%start header;
|
||||
|
||||
header:
|
||||
"{" declarations "}"
|
||||
"{" declarations "}" postamble
|
||||
;
|
||||
|
||||
postamble:
|
||||
%empty
|
||||
| postamble EXECUTOR_ONLY
|
||||
;
|
||||
|
||||
declarations:
|
||||
%empty
|
||||
| declarations comments declaration rcomment
|
||||
{
|
||||
if($3.size())
|
||||
{
|
||||
addComment($3, true, $2, $4);
|
||||
yamlout << $3;
|
||||
}
|
||||
}
|
||||
| declarations declaration
|
||||
;
|
||||
|
||||
%type <std::string> comments;
|
||||
comments:
|
||||
%empty { $$ = ""; }
|
||||
| comments COMMENT
|
||||
{ $$ = concatComments($1, $2); }
|
||||
;
|
||||
|
||||
%type <std::string> rcomment;
|
||||
rcomment:
|
||||
%empty { $$ = ""; }
|
||||
| RIGHTCOMMENT
|
||||
;
|
||||
|
||||
|
||||
declaration:
|
||||
enum ";"
|
||||
| struct ";"
|
||||
| typedef ";"
|
||||
| lowmem ";"
|
||||
| trap ";"
|
||||
| function ";"
|
||||
| size_assertion ";"
|
||||
enum_decl
|
||||
| struct_decl
|
||||
| typedef
|
||||
| lowmem
|
||||
| trap
|
||||
| function
|
||||
| size_assertion
|
||||
| executor_only
|
||||
;
|
||||
|
||||
enum:
|
||||
"enum" "{" enum_values "}"
|
||||
enum_decl:
|
||||
comments enum ";" rcomment
|
||||
{
|
||||
$$ = wrap("enum", wrap("values", sequence($3)));
|
||||
addComment($2, true, $1, $4);
|
||||
declare($2);
|
||||
}
|
||||
;
|
||||
|
||||
%type <YAML::Node> enum;
|
||||
enum:
|
||||
"enum" optional_identifier "{" enum_values "}"
|
||||
{
|
||||
YAML::Node node;
|
||||
if(!$2.empty())
|
||||
node["name"] = $2;
|
||||
node["values"] = sequence($4);
|
||||
$$ = wrap("enum", node);
|
||||
}
|
||||
;
|
||||
|
||||
%type <std::vector<YAML::Node>> enum_values;
|
||||
enum_values:
|
||||
%empty { }
|
||||
| enum_values1
|
||||
| enum_values1 ","
|
||||
;
|
||||
|
||||
%type <std::vector<YAML::Node>> enum_values1;
|
||||
enum_values1:
|
||||
comments enum_value rcomment
|
||||
{
|
||||
|
|
@ -225,6 +266,7 @@ enum_values1:
|
|||
}
|
||||
;
|
||||
|
||||
%type <YAML::Node> enum_value;
|
||||
enum_value:
|
||||
IDENTIFIER
|
||||
{
|
||||
|
|
@ -237,6 +279,7 @@ enum_value:
|
|||
}
|
||||
;
|
||||
|
||||
%type <std::string> expression;
|
||||
expression:
|
||||
INTLIT
|
||||
| CHARLIT
|
||||
|
|
@ -245,18 +288,60 @@ expression:
|
|||
auto q = [](const std::string& a) { return a.substr(1, a.size()-2); };
|
||||
$$ = "'" + q($3) + q($5) + q($7) + q($9) + "'";
|
||||
}
|
||||
| IDENTIFIER
|
||||
| "-" expression { $$ = "-" + $2; }
|
||||
| "(" expression ")" { $$ = $2; }
|
||||
;
|
||||
|
||||
struct:
|
||||
"struct" IDENTIFIER "{" struct_members "}"
|
||||
struct_decl:
|
||||
comments struct ";" rcomment
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = $2;
|
||||
node["members"] = sequence($4);
|
||||
$$ = wrap("struct", node);
|
||||
addComment($2, true, $1, $4);
|
||||
declare($2);
|
||||
}
|
||||
;
|
||||
|
||||
%type <YAML::Node> struct;
|
||||
struct:
|
||||
struct_or_union IDENTIFIER optional_struct_body
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = $2;
|
||||
if($3)
|
||||
{
|
||||
node["members"] = sequence(*$3);
|
||||
$$ = wrap($1 ? "union" : "struct", node);
|
||||
}
|
||||
else
|
||||
$$ = wrap("forward_struct", node);
|
||||
}
|
||||
| struct_or_union "{" struct_members "}"
|
||||
{
|
||||
YAML::Node node;
|
||||
node["members"] = sequence($3);
|
||||
$$ = wrap($1 ? "union" : "struct", node);
|
||||
}
|
||||
;
|
||||
|
||||
%type <std::optional<std::vector<YAML::Node>>> optional_struct_body;
|
||||
optional_struct_body:
|
||||
%empty {}
|
||||
| "{" struct_members "}" { $$ = $2; }
|
||||
;
|
||||
|
||||
%type <std::string> optional_identifier;
|
||||
optional_identifier:
|
||||
%empty {}
|
||||
| IDENTIFIER
|
||||
;
|
||||
|
||||
%type <bool> struct_or_union;
|
||||
struct_or_union:
|
||||
"struct" { $$ = false; }
|
||||
| "union" { $$ = true; }
|
||||
;
|
||||
|
||||
%type <std::vector<YAML::Node>> struct_members;
|
||||
struct_members:
|
||||
%empty { $$ = {}; }
|
||||
| "GUEST_STRUCT" ";" { $$ = {}; }
|
||||
|
|
@ -264,84 +349,250 @@ struct_members:
|
|||
{ $$ = std::move($1); $$.push_back($2); }
|
||||
;
|
||||
|
||||
%type <YAML::Node> struct_member;
|
||||
struct_member:
|
||||
comments type_pre IDENTIFIER type_post ";" rcomment
|
||||
comments type_pre type_op IDENTIFIER type_post ";" rcomment
|
||||
{
|
||||
$$["name"] = $3;
|
||||
$$["name"] = $4;
|
||||
$$["type"] = $2 + $3 + $5;
|
||||
addComment($$, false, $1, $7);
|
||||
}
|
||||
;
|
||||
|
||||
%type <std::string> type;
|
||||
type:
|
||||
type_pre type_post
|
||||
type_pre type_op type_post { $$ = $1 + $2 + $3; }
|
||||
;
|
||||
|
||||
|
||||
%type <std::string> type_pre;
|
||||
type_pre:
|
||||
"GUEST" "<" type ">"
|
||||
"GUEST" "<" type ">" { $$ = $3; }
|
||||
| IDENTIFIER
|
||||
| intlike_type
|
||||
| type_pre "*"
|
||||
| "const" type_pre
|
||||
| enum
|
||||
| struct
|
||||
{
|
||||
if($1 != 5)
|
||||
$1 &= ~1;
|
||||
switch($1)
|
||||
{
|
||||
case 0: $$ = "int32_t"; break;
|
||||
case 2: $$ = "uint32_t"; break;
|
||||
case 4: $$ = "char"; break;
|
||||
case 5: $$ = "int8_t"; break;
|
||||
case 6: $$ = "uint8_t"; break;
|
||||
case 8: $$ = "int16_t"; break;
|
||||
case 10: $$ = "uint16_t"; break;
|
||||
case 16: $$ = "int32_t"; break;
|
||||
case 18: $$ = "uint32_t"; break;
|
||||
default: $$ = "invalid_int_type"; break;
|
||||
}
|
||||
}
|
||||
| "const" type_pre { $$ = "const " + $2; }
|
||||
;
|
||||
|
||||
%type <std::string> type_op;
|
||||
type_op:
|
||||
%empty {}
|
||||
| type_op "*" { $$ = $1 + "*"; }
|
||||
;
|
||||
|
||||
%type <int> intlike_type;
|
||||
intlike_type:
|
||||
intlike_type_elem
|
||||
| intlike_type intlike_type_elem
|
||||
intlike_type_elem
|
||||
| intlike_type intlike_type_elem { $$ = $1 | $2; }
|
||||
;
|
||||
|
||||
%type <int> intlike_type_elem;
|
||||
intlike_type_elem:
|
||||
INT
|
||||
| UNSIGNED
|
||||
| SHORT
|
||||
| LONG
|
||||
| CHAR
|
||||
| SIGNED
|
||||
INT { $$ = 0; }
|
||||
| SIGNED { $$ = 1; }
|
||||
| UNSIGNED { $$ = 2; }
|
||||
| CHAR { $$ = 4; }
|
||||
| SHORT { $$ = 8; }
|
||||
| LONG { $$ = 16; }
|
||||
;
|
||||
|
||||
%type <std::string> type_post;
|
||||
type_post:
|
||||
%empty
|
||||
| type_post "[" expression "]"
|
||||
%empty {}
|
||||
| type_post "[" expression "]" { $$ = $1 + "[" + $3 + "]"; }
|
||||
;
|
||||
|
||||
%type <YAML::Node> funptr;
|
||||
funptr:
|
||||
"UPP" "<" type "(" argument_list ")" ">"
|
||||
{
|
||||
YAML::Node node;
|
||||
node["return"] = $3;
|
||||
if($5.size())
|
||||
node["args"] = $5;
|
||||
$$ = wrap("funptr", node);
|
||||
}
|
||||
;
|
||||
|
||||
typedef:
|
||||
"typedef" type_pre IDENTIFIER type_post
|
||||
| "using" IDENTIFIER "=" type
|
||||
| "typedef" "UPP" "<" type "(" argument_list ")" ">" IDENTIFIER
|
||||
| "using" IDENTIFIER "=" "UPP" "<" type "(" argument_list ")" ">"
|
||||
comments "typedef" type_pre typedef_declarator_list ";" rcomment
|
||||
{
|
||||
bool first = true;
|
||||
for(auto [typeOpPost, name] : $4)
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = name;
|
||||
node["type"] = $3 + typeOpPost;
|
||||
if(first)
|
||||
addComment(node, false, $1);
|
||||
first = false;
|
||||
declare(wrap("typedef", node));
|
||||
}
|
||||
addComment(things.back(), true, $6);
|
||||
}
|
||||
| comments "typedef" complex_type typedef_declarator_list ";" rcomment
|
||||
{
|
||||
std::string typeName = "";
|
||||
if($3.begin()->second["name"])
|
||||
typeName = $3.begin()->second["name"].as<std::string>();
|
||||
|
||||
if(typeName.empty())
|
||||
{
|
||||
for(auto [typeOpPost, name] : $4)
|
||||
{
|
||||
if(typeOpPost.empty())
|
||||
{
|
||||
typeName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(typeName.empty())
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << "_anonymous" << ++gAnonymousIndex; // FIXME: file name?
|
||||
typeName = str.str();
|
||||
}
|
||||
$3.begin()->second["name"] = typeName;
|
||||
}
|
||||
declare($3);
|
||||
|
||||
bool first = true;
|
||||
for(auto [typeOpPost, name] : $4)
|
||||
{
|
||||
if(name == typeName)
|
||||
{
|
||||
if(!typeOpPost.empty())
|
||||
error("contradictory: " + name);
|
||||
}
|
||||
else
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = name;
|
||||
node["type"] = typeName + typeOpPost;
|
||||
if(first)
|
||||
addComment(node, false, $1);
|
||||
first = false;
|
||||
declare(wrap("typedef", node));
|
||||
}
|
||||
}
|
||||
addComment(things.back(), true, $6);
|
||||
}
|
||||
|
||||
| "using" IDENTIFIER "=" "UPP" "<" type "(" argument_list ")" ">"*/
|
||||
;
|
||||
|
||||
%type <YAML::Node> complex_type;
|
||||
complex_type:
|
||||
struct
|
||||
| enum
|
||||
| funptr
|
||||
;
|
||||
|
||||
%type <std::vector<std::pair<std::string, std::string>>> typedef_declarator_list;
|
||||
typedef_declarator_list:
|
||||
type_op IDENTIFIER type_post
|
||||
{ $$ = { {$1 + $3, $2} }; }
|
||||
| typedef_declarator_list "," type_op IDENTIFIER type_post
|
||||
{ $$ = std::move($1); $$.emplace_back($3 + $5, $4); }
|
||||
;
|
||||
|
||||
%type <YAML::Node> argument_list;
|
||||
argument_list:
|
||||
%empty
|
||||
%empty {}
|
||||
| argument_list1
|
||||
;
|
||||
|
||||
%type <YAML::Node> argument_list1;
|
||||
argument_list1:
|
||||
argument
|
||||
| argument_list1 "," argument
|
||||
argument { $$.push_back($1); }
|
||||
| argument_list1 "," argument { $$ = std::move($1); $$.push_back($3); }
|
||||
;
|
||||
|
||||
%type <YAML::Node> argument;
|
||||
argument:
|
||||
type
|
||||
| type IDENTIFIER
|
||||
{
|
||||
$$["type"] = $1;
|
||||
}
|
||||
| type_pre type_op IDENTIFIER type_post
|
||||
{
|
||||
$$["name"] = $3;
|
||||
$$["type"] = $1 + $2 + $4;
|
||||
}
|
||||
;
|
||||
|
||||
lowmem:
|
||||
"const" "LowMemGlobal" "<" type ">" IDENTIFIER "{" INTLIT "}"
|
||||
comments "const" "LowMemGlobal" "<" type ">" IDENTIFIER "{" INTLIT "}" ";" rcomment
|
||||
;
|
||||
|
||||
trap:
|
||||
"DISPATCHER_TRAP" "(" IDENTIFIER "," INTLIT "," IDENTIFIER ")"
|
||||
| "PASCAL_TRAP" "(" IDENTIFIER "," INTLIT ")"
|
||||
| "PASCAL_FUNCTION" "(" IDENTIFIER ")"
|
||||
| "PASCAL_SUBTRAP" "(" IDENTIFIER "," INTLIT "," INTLIT "," IDENTIFIER ")"
|
||||
"DISPATCHER_TRAP" "(" IDENTIFIER "," INTLIT "," IDENTIFIER ")" ";"
|
||||
| "PASCAL_TRAP" "(" IDENTIFIER "," INTLIT ")" ";"
|
||||
{
|
||||
renameThing("C_"+$3, $3);
|
||||
thingByName($3).begin()->second["trap"] = $5;
|
||||
}
|
||||
| "PASCAL_FUNCTION" "(" IDENTIFIER ")" ";"
|
||||
| "PASCAL_SUBTRAP" "(" IDENTIFIER "," INTLIT "," INTLIT "," IDENTIFIER ")" ";"
|
||||
{
|
||||
renameThing("C_"+$3, $3);
|
||||
auto& fun = thingByName($3);
|
||||
fun.begin()->second["dispatcher"] = $9;
|
||||
fun.begin()->second["trap"] = $5;
|
||||
fun.begin()->second["selector"] = $7;
|
||||
}
|
||||
;
|
||||
|
||||
function:
|
||||
"extern" type_pre IDENTIFIER "(" argument_list ")"
|
||||
comments "extern" type_pre type_op IDENTIFIER "(" argument_list ")" ";" rcomment
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = $5;
|
||||
node["return"] = $3 + $4;
|
||||
if($7.size())
|
||||
node["args"] = $7;
|
||||
addComment(node, false, $1, $10);
|
||||
declare(wrap("function", node));
|
||||
}
|
||||
;
|
||||
|
||||
size_assertion:
|
||||
"static_assert" "(" "sizeof" "(" IDENTIFIER ")" EQUAL INTLIT ")"
|
||||
"static_assert" "(" "sizeof" "(" IDENTIFIER ")" EQUAL INTLIT ")" ";"
|
||||
{
|
||||
things[names[$5]].begin()->second["size"] = $8;
|
||||
}
|
||||
;
|
||||
|
||||
executor_only:
|
||||
comments EXECUTOR_ONLY
|
||||
{
|
||||
if(things.size() && things.back().begin()->first.as<std::string>() == "executor_only")
|
||||
{
|
||||
things.back().begin()->second["code"]
|
||||
= things.back().begin()->second["code"].as<std::string>() + "\n"
|
||||
+ ($1.empty() ? $2 : "// " + $1 + "\n" + $2);
|
||||
}
|
||||
else
|
||||
{
|
||||
YAML::Node node;
|
||||
node["code"] = $1.empty() ? $2 : "// " + $1 + "\n" + $2;
|
||||
declare(wrap("executor_only", node));
|
||||
}
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
|
|
|||
|
|
@ -2,14 +2,25 @@
|
|||
#include <iostream>
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
extern YAML::Emitter yamlout;
|
||||
extern std::vector<YAML::Node> things;
|
||||
extern std::unordered_map<std::string, int> names;
|
||||
|
||||
int main()
|
||||
{
|
||||
yy::HeaderParser parser;
|
||||
|
||||
yamlout << YAML::BeginSeq;
|
||||
parser.parse();
|
||||
YAML::Emitter yamlout;
|
||||
|
||||
yamlout << YAML::BeginSeq;
|
||||
bool first = true;
|
||||
for(const auto& n : things)
|
||||
{
|
||||
if(!first)
|
||||
yamlout << YAML::Newline << YAML::Newline << YAML::Comment("####") << YAML::Newline;
|
||||
first = false;
|
||||
yamlout << n;
|
||||
}
|
||||
yamlout << YAML::EndSeq;
|
||||
|
||||
std::cout << yamlout.c_str() << std::endl;
|
||||
|
|
|
|||
Loading…
Reference in a new issue