1117 lines
30 KiB
Plaintext
1117 lines
30 KiB
Plaintext
/*
|
|
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
|
* See included license file for license details.
|
|
*/
|
|
|
|
/* write header with token defines */
|
|
%defines
|
|
|
|
/* make it reentrant */
|
|
%pure-parser
|
|
|
|
/* put more info in error messages */
|
|
%error-verbose
|
|
|
|
/* enable location processing */
|
|
%locations
|
|
|
|
%{
|
|
#include "ElftosbLexer.h"
|
|
#include "ElftosbAST.h"
|
|
#include "Logging.h"
|
|
#include "Blob.h"
|
|
#include "format_string.h"
|
|
#include "Value.h"
|
|
#include "ConversionController.h"
|
|
|
|
using namespace elftosb;
|
|
|
|
//! Our special location type.
|
|
#define YYLTYPE token_loc_t
|
|
|
|
// this indicates that we're using our own type. it should be unset automatically
|
|
// but that's not working for some reason with the .hpp file.
|
|
#if defined(YYLTYPE_IS_TRIVIAL)
|
|
#undef YYLTYPE_IS_TRIVIAL
|
|
#define YYLTYPE_IS_TRIVIAL 0
|
|
#endif
|
|
|
|
//! Default location action
|
|
#define YYLLOC_DEFAULT(Current, Rhs, N) \
|
|
do { \
|
|
if (N) \
|
|
{ \
|
|
(Current).m_firstLine = YYRHSLOC(Rhs, 1).m_firstLine; \
|
|
(Current).m_lastLine = YYRHSLOC(Rhs, N).m_lastLine; \
|
|
} \
|
|
else \
|
|
{ \
|
|
(Current).m_firstLine = (Current).m_lastLine = YYRHSLOC(Rhs, 0).m_lastLine; \
|
|
} \
|
|
} while (0)
|
|
|
|
//! Forward declaration of yylex().
|
|
static int yylex(YYSTYPE * lvalp, YYLTYPE * yylloc, ElftosbLexer * lexer);
|
|
|
|
// Forward declaration of error handling function.
|
|
static void yyerror(YYLTYPE * yylloc, ElftosbLexer * lexer, CommandFileASTNode ** resultAST, const char * error);
|
|
|
|
%}
|
|
|
|
/* symbol types */
|
|
%union {
|
|
int m_num;
|
|
elftosb::SizedIntegerValue * m_int;
|
|
Blob * m_blob;
|
|
std::string * m_str;
|
|
elftosb::ASTNode * m_ast; // must use full name here because this is put into *.tab.hpp
|
|
}
|
|
|
|
/* extra parameters for the parser and lexer */
|
|
%parse-param {ElftosbLexer * lexer}
|
|
%parse-param {CommandFileASTNode ** resultAST}
|
|
%lex-param {ElftosbLexer * lexer}
|
|
|
|
/* token definitions */
|
|
%token <m_str> TOK_IDENT "identifier"
|
|
%token <m_str> TOK_STRING_LITERAL "string"
|
|
%token <m_int> TOK_INT_LITERAL "integer"
|
|
%token <m_str> TOK_SECTION_NAME "section name"
|
|
%token <m_str> TOK_SOURCE_NAME "source name"
|
|
%token <m_blob> TOK_BLOB "binary object"
|
|
%token '('
|
|
%token ')'
|
|
%token '{'
|
|
%token '}'
|
|
%token '['
|
|
%token ']'
|
|
%token '='
|
|
%token ','
|
|
%token ';'
|
|
%token ':'
|
|
%token '>'
|
|
%token '.'
|
|
%token TOK_DOT_DOT ".."
|
|
%token '~'
|
|
%token '&'
|
|
%token '|'
|
|
%token '<'
|
|
%token '!'
|
|
%token TOK_AND "&&"
|
|
%token TOK_OR "||"
|
|
%token TOK_GEQ ">="
|
|
%token TOK_LEQ "<="
|
|
%token TOK_EQ "=="
|
|
%token TOK_NEQ "!="
|
|
%token TOK_POWER "**"
|
|
%token TOK_LSHIFT "<<"
|
|
%token TOK_RSHIFT ">>"
|
|
%token <m_int> TOK_INT_SIZE "integer size"
|
|
%token TOK_OPTIONS "options"
|
|
%token TOK_CONSTANTS "constants"
|
|
%token TOK_SOURCES "sources"
|
|
%token TOK_FILTERS "filters"
|
|
%token TOK_SECTION "section"
|
|
%token TOK_EXTERN "extern"
|
|
%token TOK_FROM "from"
|
|
%token TOK_RAW "raw"
|
|
%token TOK_LOAD "load"
|
|
%token TOK_JUMP "jump"
|
|
%token TOK_CALL "call"
|
|
%token TOK_MODE "mode"
|
|
%token TOK_ERASE "erase"
|
|
%token TOK_ALL "all"
|
|
%token TOK_IF "if"
|
|
%token TOK_ELSE "else"
|
|
%token TOK_DEFINED "defined"
|
|
%token TOK_INFO "info"
|
|
%token TOK_WARNING "warning"
|
|
%token TOK_ERROR "error"
|
|
%token TOK_SIZEOF "sizeof"
|
|
%token TOK_DCD "dcd"
|
|
%token TOK_HAB "hab"
|
|
%token TOK_IVT "ivt"
|
|
%token TOK_UNSECURE "unsecure"
|
|
%token TOK_RESET "reset"
|
|
%token TOK_JUMP_SP "jump_sp"
|
|
%token TOK_ENABLE "enable"
|
|
%token TOK_KEYBLOB "keyblob"
|
|
%token TOK_ENCRYPT "encrypt"
|
|
%token TOK_KEYWRAP "keywrap"
|
|
|
|
/* operator precedence */
|
|
%left "&&" "||"
|
|
%left '>' '<' ">=" "<=" "==" "!="
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left "<<" ">>"
|
|
%left "**"
|
|
%left '+' '-'
|
|
%left '*' '/' '%'
|
|
%left '.'
|
|
%right UNARY_OP
|
|
|
|
/* nonterminal types - most nonterminal symbols are subclasses of ASTNode */
|
|
%type <m_ast> command_file blocks_list pre_section_block options_block const_def_list const_def_list_elem
|
|
%type <m_ast> const_def const_expr expr int_const_expr unary_expr int_value constants_block
|
|
%type <m_ast> sources_block source_def_list source_def_list_elem source_def
|
|
%type <m_ast> section_defs section_def section_contents full_stmt_list full_stmt_list_elem
|
|
%type <m_ast> basic_stmt load_stmt call_stmt from_stmt load_data load_target call_target
|
|
%type <m_ast> address_or_range load_target_opt call_arg_opt basic_stmt_list basic_stmt_list_elem
|
|
%type <m_ast> source_attr_list source_attr_list_elem source_attrs_opt
|
|
%type <m_ast> section_list section_list_elem symbol_ref mode_stmt
|
|
%type <m_ast> section_options_opt source_attr_list_opt
|
|
%type <m_ast> if_stmt else_opt message_stmt erase_stmt
|
|
%type <m_ast> bool_expr ivt_def assignment_list_opt
|
|
%type <m_ast> reset_stmt enable_stmt mem_opt jump_sp_stmt load_opt keywrap_stmt
|
|
%type <m_ast> keyblob_block encrypt_stmt keyblob_def_list keyblob_def_list_elem keyblob_def
|
|
|
|
%type <m_num> call_or_jump
|
|
|
|
%destructor { delete $$; } TOK_IDENT TOK_STRING_LITERAL TOK_SECTION_NAME TOK_SOURCE_NAME TOK_BLOB TOK_INT_SIZE TOK_INT_LITERAL
|
|
|
|
%%
|
|
|
|
command_file : blocks_list section_defs
|
|
{
|
|
CommandFileASTNode * commandFile = new CommandFileASTNode();
|
|
commandFile->setBlocks(dynamic_cast<ListASTNode*>($1));
|
|
commandFile->setSections(dynamic_cast<ListASTNode*>($2));
|
|
commandFile->setLocation(@1, @2);
|
|
*resultAST = commandFile;
|
|
}
|
|
;
|
|
|
|
blocks_list : pre_section_block
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| blocks_list pre_section_block
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
pre_section_block
|
|
: options_block { $$ = $1; }
|
|
| constants_block { $$ = $1; }
|
|
| sources_block { $$ = $1; }
|
|
| keyblob_block { $$ = $1; }
|
|
;
|
|
|
|
options_block : "options" '{' const_def_list '}'
|
|
{
|
|
$$ = new OptionsBlockASTNode(dynamic_cast<ListASTNode *>($3));
|
|
}
|
|
;
|
|
|
|
constants_block : "constants" '{' const_def_list '}'
|
|
{
|
|
$$ = new ConstantsBlockASTNode(dynamic_cast<ListASTNode *>($3));
|
|
}
|
|
;
|
|
|
|
const_def_list : const_def_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| const_def_list const_def_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
const_def_list_elem : const_def ';' { $$ = $1; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
const_def : TOK_IDENT '=' const_expr
|
|
{
|
|
$$ = new AssignmentASTNode($1, $3);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
;
|
|
|
|
keyblob_block : "keyblob" '(' int_const_expr ')' '{' keyblob_def_list '}'
|
|
{
|
|
KeyblobBlockASTNode * keyblob = new KeyblobBlockASTNode(dynamic_cast<ListASTNode *>($6));
|
|
keyblob->setKeyblobNumberExpr(dynamic_cast<ExprASTNode *>($3));
|
|
$$ = keyblob;
|
|
}
|
|
;
|
|
|
|
keyblob_def_list : keyblob_def_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| keyblob_def_list keyblob_def_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
keyblob_def_list_elem : keyblob_def { $$ = $1; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
keyblob_def : '(' assignment_list_opt ')'
|
|
{
|
|
KeyblobEntryASTNode * entry = new KeyblobEntryASTNode();
|
|
if ($2)
|
|
{
|
|
entry->setFieldAssignments(dynamic_cast<ListASTNode*>($2));
|
|
}
|
|
entry->setLocation(@1, @3);
|
|
$$ = entry;
|
|
}
|
|
;
|
|
|
|
sources_block : "sources" '{' source_def_list '}'
|
|
{
|
|
$$ = new SourcesBlockASTNode(dynamic_cast<ListASTNode *>($3));
|
|
}
|
|
;
|
|
|
|
source_def_list : source_def_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| source_def_list source_def_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
source_def_list_elem
|
|
: source_def source_attrs_opt ';'
|
|
{
|
|
// tell the lexer that this is the name of a source file
|
|
SourceDefASTNode * node = dynamic_cast<SourceDefASTNode*>($1);
|
|
if ($2)
|
|
{
|
|
node->setAttributes(dynamic_cast<ListASTNode*>($2));
|
|
}
|
|
node->setLocation(node->getLocation(), @3);
|
|
lexer->addSourceName(node->getName());
|
|
$$ = $1;
|
|
}
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
source_def : TOK_IDENT '=' TOK_STRING_LITERAL
|
|
{
|
|
$$ = new PathSourceDefASTNode($1, $3);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| TOK_IDENT '=' "extern" '(' int_const_expr ')'
|
|
{
|
|
$$ = new ExternSourceDefASTNode($1, dynamic_cast<ExprASTNode*>($5));
|
|
$$->setLocation(@1, @6);
|
|
}
|
|
;
|
|
|
|
source_attrs_opt
|
|
: '(' source_attr_list ')' { $$ = $2; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
source_attr_list
|
|
: source_attr_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| source_attr_list ',' source_attr_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($3);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
source_attr_list_elem
|
|
: TOK_IDENT '=' const_expr
|
|
{
|
|
$$ = new AssignmentASTNode($1, $3);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
;
|
|
|
|
section_defs : section_def
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| section_defs section_def
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
section_def : "section" '(' int_const_expr section_options_opt ')' section_contents
|
|
{
|
|
SectionContentsASTNode * sectionNode = dynamic_cast<SectionContentsASTNode*>($6);
|
|
if (sectionNode)
|
|
{
|
|
ExprASTNode * exprNode = dynamic_cast<ExprASTNode*>($3);
|
|
sectionNode->setSectionNumberExpr(exprNode);
|
|
sectionNode->setOptions(dynamic_cast<ListASTNode*>($4));
|
|
sectionNode->setLocation(@1, sectionNode->getLocation());
|
|
}
|
|
$$ = $6;
|
|
}
|
|
;
|
|
|
|
section_options_opt
|
|
: ';' source_attr_list_opt
|
|
{
|
|
$$ = $2;
|
|
}
|
|
| /* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
;
|
|
|
|
source_attr_list_opt
|
|
: source_attr_list
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| /* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
;
|
|
|
|
section_contents
|
|
: "<=" load_data ';'
|
|
{
|
|
DataSectionContentsASTNode * dataSection = new DataSectionContentsASTNode($2);
|
|
dataSection->setLocation(@1, @3);
|
|
$$ = dataSection;
|
|
}
|
|
| '{' full_stmt_list '}'
|
|
{
|
|
ListASTNode * listNode = dynamic_cast<ListASTNode*>($2);
|
|
$$ = new BootableSectionContentsASTNode(listNode);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
;
|
|
|
|
full_stmt_list : full_stmt_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| full_stmt_list full_stmt_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
full_stmt_list_elem
|
|
: basic_stmt ';' { $$ = $1; }
|
|
| from_stmt { $$ = $1; }
|
|
| encrypt_stmt { $$ = $1; }
|
|
| keywrap_stmt { $$ = $1; }
|
|
| if_stmt { $$ = $1; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
basic_stmt_list : basic_stmt_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| basic_stmt_list basic_stmt_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($2);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
basic_stmt_list_elem
|
|
: basic_stmt ';' { $$ = $1; }
|
|
| if_stmt { $$ = $1; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
basic_stmt : load_stmt { $$ = $1; }
|
|
| call_stmt { $$ = $1; }
|
|
| erase_stmt { $$ = $1; }
|
|
| mode_stmt { $$ = $1; }
|
|
| message_stmt { $$ = $1; }
|
|
| reset_stmt { $$ = $1; }
|
|
| jump_sp_stmt { $$ = $1; }
|
|
| enable_stmt { $$ = $1; }
|
|
;
|
|
|
|
load_stmt : "load" load_opt load_data load_target_opt
|
|
{
|
|
LoadStatementASTNode * stmt = new LoadStatementASTNode();
|
|
stmt->setLoadOption($2);
|
|
stmt->setData($3);
|
|
stmt->setTarget($4);
|
|
// set char locations for the statement
|
|
if ($4)
|
|
{
|
|
stmt->setLocation(@1, @4);
|
|
}
|
|
else
|
|
{
|
|
stmt->setLocation(@1, @3);
|
|
}
|
|
$$ = stmt;
|
|
}
|
|
;
|
|
|
|
load_opt : TOK_IDENT
|
|
{
|
|
$$ = new StringConstASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
load_data : int_const_expr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| TOK_STRING_LITERAL
|
|
{
|
|
$$ = new StringConstASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| TOK_SOURCE_NAME
|
|
{
|
|
$$ = new SourceASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| section_list
|
|
{
|
|
$$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($1));
|
|
$$->setLocation(@1);
|
|
}
|
|
| section_list "from" TOK_SOURCE_NAME
|
|
{
|
|
$$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($1), $3);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| TOK_SOURCE_NAME '[' section_list ']'
|
|
{
|
|
$$ = new SectionMatchListASTNode(dynamic_cast<ListASTNode*>($3), $1);
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
| TOK_BLOB
|
|
{
|
|
$$ = new BlobConstASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| ivt_def
|
|
{
|
|
}
|
|
;
|
|
|
|
section_list : section_list_elem
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($1);
|
|
$$ = list;
|
|
}
|
|
| section_list ',' section_list_elem
|
|
{
|
|
dynamic_cast<ListASTNode*>($1)->appendNode($3);
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
section_list_elem
|
|
: TOK_SECTION_NAME
|
|
{
|
|
$$ = new SectionASTNode($1, SectionASTNode::kInclude);
|
|
$$->setLocation(@1);
|
|
}
|
|
| '~' TOK_SECTION_NAME
|
|
{
|
|
$$ = new SectionASTNode($2, SectionASTNode::kExclude);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
;
|
|
|
|
load_target_opt : '>' load_target
|
|
{
|
|
$$ = $2;
|
|
}
|
|
| /* empty */
|
|
{
|
|
$$ = new NaturalLocationASTNode();
|
|
// $$->setLocation();
|
|
}
|
|
;
|
|
|
|
load_target : '.'
|
|
{
|
|
$$ = new NaturalLocationASTNode();
|
|
$$->setLocation(@1);
|
|
}
|
|
| address_or_range
|
|
{
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
ivt_def : "ivt" '(' assignment_list_opt ')'
|
|
{
|
|
IVTConstASTNode * ivt = new IVTConstASTNode();
|
|
if ($3)
|
|
{
|
|
ivt->setFieldAssignments(dynamic_cast<ListASTNode*>($3));
|
|
}
|
|
ivt->setLocation(@1, @4);
|
|
$$ = ivt;
|
|
}
|
|
;
|
|
|
|
assignment_list_opt : source_attr_list { $$ = $1; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
call_stmt : call_or_jump call_target call_arg_opt
|
|
{
|
|
CallStatementASTNode * stmt = new CallStatementASTNode();
|
|
switch ($1)
|
|
{
|
|
case 1:
|
|
stmt->setCallType(CallStatementASTNode::kCallType);
|
|
break;
|
|
case 2:
|
|
stmt->setCallType(CallStatementASTNode::kJumpType);
|
|
break;
|
|
default:
|
|
yyerror(&yylloc, lexer, resultAST, "invalid call_or_jump value");
|
|
YYABORT;
|
|
break;
|
|
}
|
|
stmt->setTarget($2);
|
|
stmt->setArgument($3);
|
|
stmt->setIsHAB(false);
|
|
if ($3)
|
|
{
|
|
stmt->setLocation(@1, @3);
|
|
}
|
|
else
|
|
{
|
|
stmt->setLocation(@1, @2);
|
|
}
|
|
$$ = stmt;
|
|
}
|
|
| "hab" call_or_jump address_or_range call_arg_opt
|
|
{
|
|
if (!elftosb::g_enableHABSupport)
|
|
{
|
|
yyerror(&yylloc, lexer, resultAST, "HAB features not supported with the selected family");
|
|
YYABORT;
|
|
}
|
|
|
|
CallStatementASTNode * stmt = new CallStatementASTNode();
|
|
switch ($2)
|
|
{
|
|
case 1:
|
|
stmt->setCallType(CallStatementASTNode::kCallType);
|
|
break;
|
|
case 2:
|
|
stmt->setCallType(CallStatementASTNode::kJumpType);
|
|
break;
|
|
default:
|
|
yyerror(&yylloc, lexer, resultAST, "invalid call_or_jump value");
|
|
YYABORT;
|
|
break;
|
|
}
|
|
stmt->setTarget($3);
|
|
stmt->setArgument($4);
|
|
stmt->setIsHAB(true);
|
|
if ($4)
|
|
{
|
|
stmt->setLocation(@1, @4);
|
|
}
|
|
else
|
|
{
|
|
stmt->setLocation(@1, @3);
|
|
}
|
|
$$ = stmt;
|
|
}
|
|
;
|
|
|
|
jump_sp_stmt : "jump_sp" int_const_expr call_target call_arg_opt
|
|
{
|
|
CallStatementASTNode * stmt = new CallStatementASTNode();
|
|
stmt->setCallType(CallStatementASTNode::kJumpType);
|
|
stmt->setStackPointer($2);
|
|
stmt->setTarget($3);
|
|
stmt->setArgument($4);
|
|
stmt->setIsHAB(false);
|
|
if ($4)
|
|
{
|
|
stmt->setLocation(@1, @4);
|
|
}
|
|
else
|
|
{
|
|
stmt->setLocation(@1, @3);
|
|
}
|
|
$$ = stmt;
|
|
}
|
|
;
|
|
|
|
call_or_jump : "call" { $$ = 1; }
|
|
| "jump" { $$ = 2; }
|
|
;
|
|
|
|
call_target : TOK_SOURCE_NAME
|
|
{
|
|
$$ = new SymbolASTNode(NULL, $1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| int_const_expr
|
|
{
|
|
$$ = new AddressRangeASTNode($1, NULL);
|
|
$$->setLocation($1);
|
|
}
|
|
;
|
|
|
|
call_arg_opt : '(' int_const_expr ')' { $$ = $2; }
|
|
| '(' ')' { $$ = NULL; }
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
erase_stmt : "erase" address_or_range
|
|
{
|
|
$$ = new EraseStatementASTNode($2);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
| "erase" mem_opt "all"
|
|
{
|
|
EraseStatementASTNode * eraseNode = new EraseStatementASTNode();
|
|
eraseNode->setEraseAll(true);
|
|
eraseNode->setMemOption($2);
|
|
if ($2)
|
|
{
|
|
eraseNode->setLocation(@1, @3);
|
|
}
|
|
else
|
|
{
|
|
eraseNode->setLocation(@1, @2);
|
|
}
|
|
$$ = eraseNode;
|
|
}
|
|
| "erase" "unsecure" "all"
|
|
{
|
|
EraseStatementASTNode * eraseNode = new EraseStatementASTNode();
|
|
eraseNode->setEraseAllUnsecure(true);
|
|
eraseNode->setLocation(@1, @3);
|
|
$$ = eraseNode;
|
|
}
|
|
;
|
|
|
|
mem_opt : TOK_IDENT
|
|
{
|
|
$$ = new StringConstASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
|
|
from_stmt : "from" TOK_SOURCE_NAME '{' basic_stmt_list '}'
|
|
{
|
|
$$ = new FromStatementASTNode($2, dynamic_cast<ListASTNode*>($4));
|
|
$$->setLocation(@1, @5);
|
|
}
|
|
;
|
|
|
|
encrypt_stmt : "encrypt" '(' int_const_expr ')' '{' basic_stmt_list '}'
|
|
{
|
|
EncryptStatementASTNode * encryptNode = new EncryptStatementASTNode(dynamic_cast<ListASTNode*>($6));
|
|
encryptNode->setKeyblobNumberExpr(dynamic_cast<ExprASTNode *>($3));
|
|
encryptNode->setLocation(@1, @7);
|
|
$$ = encryptNode;
|
|
}
|
|
;
|
|
|
|
keywrap_stmt : "keywrap" '(' int_const_expr ')' '{' basic_stmt_list '}'
|
|
{
|
|
KeywrapStatementASTNode * keywrapNode = new KeywrapStatementASTNode(dynamic_cast<ListASTNode*>($6));
|
|
keywrapNode->setKeyblobNumberExpr(dynamic_cast<ExprASTNode *>($3));
|
|
keywrapNode->setLocation(@1, @7);
|
|
$$ = keywrapNode;
|
|
}
|
|
;
|
|
|
|
mode_stmt : "mode" int_const_expr
|
|
{
|
|
$$ = new ModeStatementASTNode(dynamic_cast<ExprASTNode*>($2));
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
;
|
|
|
|
reset_stmt : "reset"
|
|
{
|
|
$$ = new ResetStatementASTNode();
|
|
$$->setLocation(@1, @1);
|
|
}
|
|
;
|
|
|
|
enable_stmt : "enable" mem_opt address_or_range
|
|
{
|
|
MemEnableStatementASTNode * enableNode = new MemEnableStatementASTNode($3);
|
|
enableNode->setMemOption($2);
|
|
enableNode->setLocation(@1, @3);
|
|
$$ = enableNode;
|
|
}
|
|
;
|
|
|
|
message_stmt : "info" TOK_STRING_LITERAL
|
|
{
|
|
$$ = new MessageStatementASTNode(MessageStatementASTNode::kInfo, $2);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
| "warning" TOK_STRING_LITERAL
|
|
{
|
|
$$ = new MessageStatementASTNode(MessageStatementASTNode::kWarning, $2);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
| "error" TOK_STRING_LITERAL
|
|
{
|
|
$$ = new MessageStatementASTNode(MessageStatementASTNode::kError, $2);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
;
|
|
|
|
if_stmt : "if" bool_expr '{' full_stmt_list '}' else_opt
|
|
{
|
|
IfStatementASTNode * ifStmt = new IfStatementASTNode();
|
|
ifStmt->setConditionExpr(dynamic_cast<ExprASTNode*>($2));
|
|
ifStmt->setIfStatements(dynamic_cast<ListASTNode*>($4));
|
|
ifStmt->setElseStatements(dynamic_cast<ListASTNode*>($6));
|
|
ifStmt->setLocation(@1, @6);
|
|
$$ = ifStmt;
|
|
}
|
|
;
|
|
|
|
else_opt : "else" '{' full_stmt_list '}'
|
|
{
|
|
$$ = $3;
|
|
}
|
|
| "else" if_stmt
|
|
{
|
|
ListASTNode * list = new ListASTNode();
|
|
list->appendNode($2);
|
|
$$ = list;
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
| /* empty */ { $$ = NULL; }
|
|
;
|
|
|
|
address_or_range : int_const_expr
|
|
{
|
|
$$ = new AddressRangeASTNode($1, NULL);
|
|
$$->setLocation($1);
|
|
}
|
|
| int_const_expr ".." int_const_expr
|
|
{
|
|
$$ = new AddressRangeASTNode($1, $3);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
;
|
|
|
|
const_expr : bool_expr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| TOK_STRING_LITERAL
|
|
{
|
|
$$ = new StringConstASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
;
|
|
|
|
bool_expr : int_const_expr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| bool_expr '<' bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kLessThan, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr '>' bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kGreaterThan, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr ">=" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kGreaterThanEqual, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr "<=" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kLessThanEqual, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr "==" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kEqual, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr "!=" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kNotEqual, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr "&&" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBooleanAnd, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| bool_expr "||" bool_expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBooleanOr, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| '!' bool_expr %prec UNARY_OP
|
|
{
|
|
$$ = new BooleanNotExprASTNode(dynamic_cast<ExprASTNode*>($2));
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
| TOK_IDENT '(' TOK_SOURCE_NAME ')'
|
|
{
|
|
$$ = new SourceFileFunctionASTNode($1, $3);
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
| '(' bool_expr ')'
|
|
{
|
|
$$ = $2;
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| "defined" '(' TOK_IDENT ')'
|
|
{
|
|
$$ = new DefinedOperatorASTNode($3);
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
;
|
|
|
|
int_const_expr : expr { $$ = $1; }
|
|
;
|
|
|
|
symbol_ref : TOK_SOURCE_NAME ':' TOK_IDENT
|
|
{
|
|
$$ = new SymbolASTNode($3, $1);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| ':' TOK_IDENT
|
|
{
|
|
$$ = new SymbolASTNode($2);
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
;
|
|
|
|
|
|
expr : int_value
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| TOK_IDENT
|
|
{
|
|
$$ = new VariableExprASTNode($1);
|
|
$$->setLocation(@1);
|
|
}
|
|
| symbol_ref
|
|
{
|
|
$$ = new SymbolRefExprASTNode(dynamic_cast<SymbolASTNode*>($1));
|
|
$$->setLocation(@1);
|
|
}
|
|
/* | expr '..' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new RangeExprASTNode(left, right);
|
|
}
|
|
*/ | expr '+' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kAdd, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '-' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kSubtract, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '*' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kMultiply, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '/' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kDivide, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '%' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kModulus, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr "**" expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kPower, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '&' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseAnd, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '|' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseOr, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr '^' expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kBitwiseXor, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr "<<" expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kShiftLeft, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| expr ">>" expr
|
|
{
|
|
ExprASTNode * left = dynamic_cast<ExprASTNode*>($1);
|
|
ExprASTNode * right = dynamic_cast<ExprASTNode*>($3);
|
|
$$ = new BinaryOpExprASTNode(left, BinaryOpExprASTNode::kShiftRight, right);
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| unary_expr
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| expr '.' TOK_INT_SIZE
|
|
{
|
|
$$ = new IntSizeExprASTNode(dynamic_cast<ExprASTNode*>($1), $3->getWordSize());
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| '(' expr ')'
|
|
{
|
|
$$ = $2;
|
|
$$->setLocation(@1, @3);
|
|
}
|
|
| "sizeof" '(' symbol_ref ')'
|
|
{
|
|
$$ = new SizeofOperatorASTNode(dynamic_cast<SymbolASTNode*>($3));
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
| "sizeof" '(' TOK_IDENT ')'
|
|
{
|
|
$$ = new SizeofOperatorASTNode($3);
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
| "sizeof" '(' TOK_SOURCE_NAME ')'
|
|
{
|
|
$$ = new SizeofOperatorASTNode($3);
|
|
$$->setLocation(@1, @4);
|
|
}
|
|
;
|
|
|
|
unary_expr : '+' expr %prec UNARY_OP
|
|
{
|
|
$$ = $2;
|
|
}
|
|
| '-' expr %prec UNARY_OP
|
|
{
|
|
$$ = new NegativeExprASTNode(dynamic_cast<ExprASTNode*>($2));
|
|
$$->setLocation(@1, @2);
|
|
}
|
|
;
|
|
|
|
int_value : TOK_INT_LITERAL
|
|
{
|
|
$$ = new IntConstExprASTNode($1->getValue(), $1->getWordSize());
|
|
$$->setLocation(@1);
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
/* code goes here */
|
|
|
|
static int yylex(YYSTYPE * lvalp, YYLTYPE * yylloc, ElftosbLexer * lexer)
|
|
{
|
|
int token = lexer->yylex();
|
|
*yylloc = lexer->getLocation();
|
|
lexer->getSymbolValue(lvalp);
|
|
return token;
|
|
}
|
|
|
|
static void yyerror(YYLTYPE * yylloc, ElftosbLexer * lexer, CommandFileASTNode ** resultAST, const char * error)
|
|
{
|
|
throw syntax_error(format_string("line %d: %s\n", yylloc->m_firstLine, error));
|
|
}
|
|
|