initial wip
This commit is contained in:
commit
a0c3b2e9a7
6 changed files with 541 additions and 0 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "yaml-cpp"]
|
||||
path = yaml-cpp
|
||||
url = https://github.com/jbeder/yaml-cpp.git
|
||||
20
CMakeLists.txt
Normal file
20
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(MultiversalHeaders)
|
||||
|
||||
set(CXX_STANDARD_REQUIRED 17)
|
||||
|
||||
set(CMAKE_PROGRAM_PATH ${CMAKE_PROGRAM_PATH} "/usr/local/opt/bison/bin")
|
||||
find_package(BISON 3.0.2)
|
||||
find_package(FLEX)
|
||||
|
||||
bison_target(HeaderParser HeaderParser.yy ${CMAKE_CURRENT_BINARY_DIR}/HeaderParser.cpp)
|
||||
flex_target(HeaderLexer HeaderLexer.l ${CMAKE_CURRENT_BINARY_DIR}/HeaderLexer.cc)
|
||||
add_flex_bison_dependency(HeaderLexer HeaderParser)
|
||||
|
||||
add_executable(ParseExecutorHeaders ParseExecutorHeaders.cc HeaderLexer.cc HeaderParser.cpp)
|
||||
target_include_directories(ParseExecutorHeaders PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(ParseExecutorHeaders yaml-cpp)
|
||||
|
||||
set(YAML_CPP_BUILD_TESTS NO)
|
||||
set(YAML_CPP_BUILD_TOOLS NO)
|
||||
add_subdirectory(yaml-cpp)
|
||||
113
HeaderLexer.l
Normal file
113
HeaderLexer.l
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
%{
|
||||
#include "HeaderParser.hpp"
|
||||
#include <cctype>
|
||||
|
||||
bool atBOL;
|
||||
#define YY_DECL yy::HeaderParser::symbol_type yylex (void)
|
||||
|
||||
static std::string strip(const char *p, const char *q)
|
||||
{
|
||||
while(p < q && std::isspace(*p))
|
||||
++p;
|
||||
while(p < q && std::isspace(q[-1]))
|
||||
--q;
|
||||
return std::string(p,q);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%option noyywrap
|
||||
|
||||
%x preamble
|
||||
|
||||
%%
|
||||
using hp = yy::HeaderParser;
|
||||
using token = hp::token;
|
||||
atBOL = false;
|
||||
|
||||
^"#if !defined(_"[A-Z_]+_H_")"$ BEGIN(preamble);
|
||||
|
||||
<preamble>^"namespace Executor" BEGIN(INITIAL);
|
||||
<preamble>.|\n ;
|
||||
|
||||
\n atBOL = true;
|
||||
[[:space:]] /* */
|
||||
|
||||
"{" return token::LEFTBRACE;
|
||||
"}" return token::RIGHTBRACE;
|
||||
"[" return token::LEFTBRACKET;
|
||||
"]" return token::RIGHTBRACKET;
|
||||
"(" return token::LEFTPAREN;
|
||||
")" return token::RIGHTPAREN;
|
||||
";" return token::SEMICOLON;
|
||||
"," return token::COMMA;
|
||||
"+" return token::PLUS;
|
||||
"-" return token::MINUS;
|
||||
"/" return token::DIVIDE;
|
||||
"*" return token::STAR;
|
||||
"=" return token::ASSIGN;
|
||||
":" return token::COLON;
|
||||
"<<" return token::SHIFTLEFT;
|
||||
">>" return token::SHIFTRIGHT;
|
||||
"==" return token::EQUAL;
|
||||
"!=" return token::NOTEQUAL;
|
||||
"&" return token::AND;
|
||||
"|" return token::OR;
|
||||
"^" return token::XOR;
|
||||
"~" return token::COMPL;
|
||||
"$" return token::DOLLAR;
|
||||
"<" return token::LESS;
|
||||
">" return token::GREATER;
|
||||
|
||||
"enum" return token::ENUM;
|
||||
"struct" return token::STRUCT;
|
||||
"union" return token::UNION;
|
||||
"typedef" return token::TYPEDEF;
|
||||
"using" return token::USING;
|
||||
"extern" return token::EXTERN;
|
||||
"const" return token::CONST;
|
||||
"static_assert" return token::STATIC_ASSERT;
|
||||
"sizeof" return token::SIZEOF;
|
||||
"int" return token::INT;
|
||||
"unsigned" return token::UNSIGNED;
|
||||
"short" return token::SHORT;
|
||||
"long" return token::LONG;
|
||||
"char" return token::CHAR;
|
||||
"signed" return token::SIGNED;
|
||||
"GUEST" return token::GUEST;
|
||||
"GUEST_STRUCT" return token::GUEST_STRUCT;
|
||||
"UPP" return token::UPP;
|
||||
"LowMemGlobal" return token::LOWMEMGLOBAL;
|
||||
"DISPATCHER_TRAP" return token::DISPATCHER_TRAP;
|
||||
"PASCAL_TRAP" return token::PASCAL_TRAP;
|
||||
"PASCAL_SUBTRAP" return token::PASCAL_SUBTRAP;
|
||||
"PASCAL_FUNCTION" return token::PASCAL_FUNCTION;
|
||||
"FOURCC" return token::FOURCC;
|
||||
|
||||
|
||||
[[:digit:]]+ return hp::make_INTLIT(yytext);
|
||||
0x[[:xdigit:]]+ return hp::make_INTLIT(yytext);
|
||||
|
||||
\'.\' return hp::make_CHARLIT(yytext);
|
||||
|
||||
[[:alpha:]_][[:alnum:]_]* return hp::make_IDENTIFIER(yytext);
|
||||
|
||||
^" "*#.* ;
|
||||
|
||||
"/*"[^*]*("*"+[^*/]*)*"*"+"/" {
|
||||
if(atBOL)
|
||||
return hp::make_COMMENT(strip(yytext+2, yytext+yyleng-2));
|
||||
else
|
||||
return hp::make_RIGHTCOMMENT(strip(yytext+2, yytext+yyleng-2));
|
||||
}
|
||||
"//".* {
|
||||
if(atBOL)
|
||||
return hp::make_COMMENT(strip(yytext+2,yytext+yyleng));
|
||||
else
|
||||
return hp::make_RIGHTCOMMENT(strip(yytext+2,yytext+yyleng));
|
||||
}
|
||||
|
||||
|
||||
. std::cout << "Lexer Error: " << yytext << std::endl; std::exit(1);
|
||||
|
||||
%%
|
||||
347
HeaderParser.yy
Normal file
347
HeaderParser.yy
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
%require "3.0.2"
|
||||
%defines
|
||||
|
||||
%define api.parser.class {HeaderParser}
|
||||
%skeleton "lalr1.cc"
|
||||
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
%define parse.assert
|
||||
%define parse.error verbose
|
||||
|
||||
%token<std::string> IDENTIFIER;
|
||||
%token<std::string> STRINGLIT;
|
||||
%token<std::string> INTLIT;
|
||||
%token<std::string> CHARLIT;
|
||||
%token<std::string> COMMENT;
|
||||
%token<std::string> RIGHTCOMMENT;
|
||||
|
||||
%token LEFTBRACE "{";
|
||||
%token RIGHTBRACE "}";
|
||||
%token LEFTBRACKET "[";
|
||||
%token RIGHTBRACKET "]";
|
||||
%token LEFTPAREN "(";
|
||||
%token RIGHTPAREN ")";
|
||||
%token SEMICOLON ";";
|
||||
%token COMMA ",";
|
||||
%token PLUS "+";
|
||||
%token MINUS "-";
|
||||
%token DIVIDE "/";
|
||||
%token STAR "*";
|
||||
%token ASSIGN "=";
|
||||
%token COLON ":";
|
||||
%token SHIFTLEFT "<<";
|
||||
%token SHIFTRIGHT ">>";
|
||||
%token EQUAL "==";
|
||||
%token NOTEQUAL "!=";
|
||||
%token AND "&";
|
||||
%token OR "|";
|
||||
%token XOR "^";
|
||||
%token COMPL "~";
|
||||
%token DOLLAR "$";
|
||||
%token LESS "<";
|
||||
%token GREATER ">";
|
||||
|
||||
%token ENUM "enum";
|
||||
%token STRUCT "struct";
|
||||
%token UNION "union";
|
||||
%token TYPEDEF "typedef";
|
||||
%token USING "using";
|
||||
%token EXTERN "extern";
|
||||
%token CONST "const";
|
||||
%token STATIC_ASSERT "static_assert";
|
||||
%token SIZEOF "sizeof";
|
||||
|
||||
%token INT "int";
|
||||
%token UNSIGNED "unsigned";
|
||||
%token SHORT "short";
|
||||
%token LONG "long";
|
||||
%token CHAR "char";
|
||||
%token SIGNED "signed";
|
||||
|
||||
%token GUEST "GUEST";
|
||||
%token GUEST_STRUCT "GUEST_STRUCT";
|
||||
%token UPP "UPP";
|
||||
%token LOWMEMGLOBAL "LowMemGlobal";
|
||||
|
||||
%token DISPATCHER_TRAP "DISPATCHER_TRAP";
|
||||
%token PASCAL_TRAP "PASCAL_TRAP";
|
||||
%token PASCAL_SUBTRAP "PASCAL_SUBTRAP";
|
||||
%token PASCAL_FUNCTION "PASCAL_FUNCTION";
|
||||
|
||||
%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
|
||||
|
||||
%code requires {
|
||||
#include "yaml-cpp/yaml.h"
|
||||
}
|
||||
%code provides {
|
||||
yy::HeaderParser::symbol_type yylex();
|
||||
}
|
||||
%code {
|
||||
#include <stack>
|
||||
|
||||
YAML::Emitter yamlout;
|
||||
|
||||
void yy::HeaderParser::error(std::string const& err)
|
||||
{
|
||||
std::cout << err << std::endl;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T popstack(std::stack<T>& s)
|
||||
{
|
||||
T x = std::move(s.top());
|
||||
s.pop();
|
||||
return x;
|
||||
}
|
||||
|
||||
YAML::Node wrap(std::string s, YAML::Node n)
|
||||
{
|
||||
YAML::Node d;
|
||||
d[s] = n;
|
||||
return d;
|
||||
}
|
||||
|
||||
template<typename Seq>
|
||||
YAML::Node sequence(const Seq& seq)
|
||||
{
|
||||
YAML::Node seqnode;
|
||||
for(const auto& n : seq)
|
||||
seqnode.push_back(n);
|
||||
return seqnode;
|
||||
}
|
||||
|
||||
std::string concatComments(const std::string& a, const std::string& b)
|
||||
{
|
||||
return a.empty() ? b : a + "\n" + b;
|
||||
}
|
||||
|
||||
void addComment(YAML::Node& node, const std::string& comment)
|
||||
{
|
||||
if(comment.empty())
|
||||
return;
|
||||
if(node["comment"])
|
||||
node["comment"] = node["comment"].as<std::string>()
|
||||
+ "\n" + comment;
|
||||
else
|
||||
node["comment"] = comment;
|
||||
|
||||
}
|
||||
|
||||
void addComment(YAML::Node& node, bool wrapped, const std::string& comment)
|
||||
{
|
||||
if(!wrapped)
|
||||
{
|
||||
addComment(node, comment);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!node || node.size() == 0)
|
||||
return;
|
||||
addComment(node.begin()->second, comment);
|
||||
|
||||
}
|
||||
|
||||
void addComment(YAML::Node& node, bool wrapped, const std::string& pre, const std::string& right)
|
||||
{
|
||||
addComment(node, wrapped, pre);
|
||||
addComment(node, wrapped, right);
|
||||
}
|
||||
}
|
||||
|
||||
%%
|
||||
%start header;
|
||||
|
||||
header:
|
||||
"{" declarations "}"
|
||||
;
|
||||
|
||||
declarations:
|
||||
%empty
|
||||
| declarations comments declaration rcomment
|
||||
{
|
||||
if($3.size())
|
||||
{
|
||||
addComment($3, true, $2, $4);
|
||||
yamlout << $3;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
comments:
|
||||
%empty { $$ = ""; }
|
||||
| comments COMMENT
|
||||
{ $$ = concatComments($1, $2); }
|
||||
;
|
||||
|
||||
rcomment:
|
||||
%empty { $$ = ""; }
|
||||
| RIGHTCOMMENT
|
||||
;
|
||||
|
||||
|
||||
declaration:
|
||||
enum ";"
|
||||
| struct ";"
|
||||
| typedef ";"
|
||||
| lowmem ";"
|
||||
| trap ";"
|
||||
| function ";"
|
||||
| size_assertion ";"
|
||||
;
|
||||
|
||||
enum:
|
||||
"enum" "{" enum_values "}"
|
||||
{
|
||||
$$ = wrap("enum", wrap("values", sequence($3)));
|
||||
}
|
||||
;
|
||||
|
||||
enum_values:
|
||||
%empty { }
|
||||
| enum_values1
|
||||
| enum_values1 ","
|
||||
;
|
||||
|
||||
enum_values1:
|
||||
comments enum_value rcomment
|
||||
{
|
||||
addComment($2, false, $1, $3);
|
||||
$$ = { $2 };
|
||||
}
|
||||
| enum_values1 "," rcomment comments enum_value rcomment
|
||||
{
|
||||
addComment($1.back(), false, $3);
|
||||
addComment($5, false, $4, $6);
|
||||
$1.push_back($5);
|
||||
$$ = std::move($1);
|
||||
}
|
||||
;
|
||||
|
||||
enum_value:
|
||||
IDENTIFIER
|
||||
{
|
||||
$$["name"] = $1;
|
||||
}
|
||||
| IDENTIFIER "=" expression
|
||||
{
|
||||
$$["name"] = $1;
|
||||
$$["value"] = $3;
|
||||
}
|
||||
;
|
||||
|
||||
expression:
|
||||
INTLIT
|
||||
| CHARLIT
|
||||
| "FOURCC" "(" CHARLIT "," CHARLIT "," CHARLIT "," CHARLIT ")"
|
||||
{
|
||||
auto q = [](const std::string& a) { return a.substr(1, a.size()-2); };
|
||||
$$ = "'" + q($3) + q($5) + q($7) + q($9) + "'";
|
||||
}
|
||||
;
|
||||
|
||||
struct:
|
||||
"struct" IDENTIFIER "{" struct_members "}"
|
||||
{
|
||||
YAML::Node node;
|
||||
node["name"] = $2;
|
||||
node["members"] = sequence($4);
|
||||
$$ = wrap("struct", node);
|
||||
}
|
||||
;
|
||||
|
||||
struct_members:
|
||||
%empty { $$ = {}; }
|
||||
| "GUEST_STRUCT" ";" { $$ = {}; }
|
||||
| struct_members struct_member
|
||||
{ $$ = std::move($1); $$.push_back($2); }
|
||||
;
|
||||
|
||||
struct_member:
|
||||
comments type_pre IDENTIFIER type_post ";" rcomment
|
||||
{
|
||||
$$["name"] = $3;
|
||||
}
|
||||
;
|
||||
|
||||
type:
|
||||
type_pre type_post
|
||||
;
|
||||
|
||||
type_pre:
|
||||
"GUEST" "<" type ">"
|
||||
| IDENTIFIER
|
||||
| intlike_type
|
||||
| type_pre "*"
|
||||
| "const" type_pre
|
||||
| enum
|
||||
| struct
|
||||
;
|
||||
|
||||
intlike_type:
|
||||
intlike_type_elem
|
||||
| intlike_type intlike_type_elem
|
||||
;
|
||||
|
||||
intlike_type_elem:
|
||||
INT
|
||||
| UNSIGNED
|
||||
| SHORT
|
||||
| LONG
|
||||
| CHAR
|
||||
| SIGNED
|
||||
;
|
||||
|
||||
type_post:
|
||||
%empty
|
||||
| type_post "[" expression "]"
|
||||
;
|
||||
|
||||
typedef:
|
||||
"typedef" type_pre IDENTIFIER type_post
|
||||
| "using" IDENTIFIER "=" type
|
||||
| "typedef" "UPP" "<" type "(" argument_list ")" ">" IDENTIFIER
|
||||
| "using" IDENTIFIER "=" "UPP" "<" type "(" argument_list ")" ">"
|
||||
;
|
||||
|
||||
argument_list:
|
||||
%empty
|
||||
| argument_list1
|
||||
;
|
||||
|
||||
argument_list1:
|
||||
argument
|
||||
| argument_list1 "," argument
|
||||
;
|
||||
|
||||
argument:
|
||||
type
|
||||
| type IDENTIFIER
|
||||
;
|
||||
|
||||
lowmem:
|
||||
"const" "LowMemGlobal" "<" type ">" IDENTIFIER "{" INTLIT "}"
|
||||
;
|
||||
|
||||
trap:
|
||||
"DISPATCHER_TRAP" "(" IDENTIFIER "," INTLIT "," IDENTIFIER ")"
|
||||
| "PASCAL_TRAP" "(" IDENTIFIER "," INTLIT ")"
|
||||
| "PASCAL_FUNCTION" "(" IDENTIFIER ")"
|
||||
| "PASCAL_SUBTRAP" "(" IDENTIFIER "," INTLIT "," INTLIT "," IDENTIFIER ")"
|
||||
;
|
||||
|
||||
function:
|
||||
"extern" type_pre IDENTIFIER "(" argument_list ")"
|
||||
;
|
||||
|
||||
size_assertion:
|
||||
"static_assert" "(" "sizeof" "(" IDENTIFIER ")" EQUAL INTLIT ")"
|
||||
;
|
||||
%%
|
||||
57
ParseExecutorHeaders.cc
Normal file
57
ParseExecutorHeaders.cc
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "HeaderParser.hpp"
|
||||
#include <iostream>
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
extern YAML::Emitter yamlout;
|
||||
|
||||
int main()
|
||||
{
|
||||
yy::HeaderParser parser;
|
||||
|
||||
yamlout << YAML::BeginSeq;
|
||||
parser.parse();
|
||||
yamlout << YAML::EndSeq;
|
||||
|
||||
std::cout << yamlout.c_str() << std::endl;
|
||||
|
||||
/*yy::HeaderParser::symbol_type token;
|
||||
extern const char* yytext;
|
||||
extern int yyleng;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
auto tok = yylex();
|
||||
if(!tok.token())
|
||||
break;
|
||||
std::cout << tok.token() << ": " << std::string(yytext, yytext+yyleng) << "\n";
|
||||
}*/
|
||||
|
||||
/* YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
out << "foo" << "bar" << "baz";
|
||||
|
||||
YAML::Node node;
|
||||
node["quuxbar"] = "quux";
|
||||
node["quuxbaz"] = "quux";
|
||||
|
||||
YAML::Node node2 = {};//YAML::Node(YAML::NodeType::Sequence);
|
||||
//node[0] = "a";
|
||||
node2.push_back("a");
|
||||
node2.push_back("b");
|
||||
|
||||
node["quux"] = node2;
|
||||
|
||||
YAML::Node node3 = node2;
|
||||
node2 = {};
|
||||
|
||||
node3.push_back("c");
|
||||
|
||||
out << node;
|
||||
|
||||
out << YAML::EndSeq;
|
||||
|
||||
std::cout << out.c_str() << std::endl;*/
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
1
yaml-cpp
Submodule
1
yaml-cpp
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit e0e01d53c27ffee6c86153fa41e7f5e57d3e5c90
|
||||
Loading…
Reference in a new issue