mirror of
https://github.com/thiagoralves/OpenPLC_v3.git
synced 2026-09-25 00:42:46 +08:00
Update MatIEC version
This commit is contained in:
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Mac",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"macFrameworkPath": [
|
||||
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
|
||||
],
|
||||
"compilerPath": "/usr/bin/clang",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "macos-clang-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"cmake.ignoreCMakeListsMissing": true
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Executable → Regular
+68
-11
@@ -58,6 +58,7 @@ symbol_c::symbol_c(
|
||||
this->last_column = last_column;
|
||||
this->last_order = last_order;
|
||||
this->parent = NULL;
|
||||
this->token = NULL;
|
||||
this->datatype = NULL;
|
||||
this->scope = NULL;
|
||||
}
|
||||
@@ -69,6 +70,7 @@ token_c::token_c(const char *value,
|
||||
int ll, int lc, const char *lfile, long int lorder)
|
||||
:symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder) {
|
||||
this->value = value;
|
||||
this->token = this; // every token is its own reference token.
|
||||
// printf("New token: %s\n", value);
|
||||
}
|
||||
|
||||
@@ -83,7 +85,7 @@ list_c::list_c(
|
||||
int ll, int lc, const char *lfile, long int lorder)
|
||||
:symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder),c(LIST_CAP_INIT) {
|
||||
n = 0;
|
||||
elements = (symbol_c**)malloc(LIST_CAP_INIT*sizeof(symbol_c*));
|
||||
elements = (element_entry_t*)malloc(LIST_CAP_INIT*sizeof(element_entry_t));
|
||||
if (NULL == elements) ERROR_MSG("out of memory");
|
||||
}
|
||||
|
||||
@@ -93,20 +95,59 @@ list_c::list_c(symbol_c *elem,
|
||||
int ll, int lc, const char *lfile, long int lorder)
|
||||
:symbol_c(fl, fc, ffile, forder, ll, lc, lfile, lorder),c(LIST_CAP_INIT) {
|
||||
n = 0;
|
||||
elements = (symbol_c**)malloc(LIST_CAP_INIT*sizeof(symbol_c*));
|
||||
elements = (element_entry_t*)malloc(LIST_CAP_INIT*sizeof(element_entry_t));
|
||||
if (NULL == elements) ERROR_MSG("out of memory");
|
||||
add_element(elem);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/* get element in position pos of the list */
|
||||
/*******************************************/
|
||||
symbol_c *list_c::get_element(int pos) {return elements[pos].symbol;}
|
||||
|
||||
|
||||
|
||||
/******************************************/
|
||||
/* find element associated to token value */
|
||||
/******************************************/
|
||||
symbol_c *list_c::find_element(symbol_c *token) {
|
||||
token_c *t = dynamic_cast<token_c *>(token);
|
||||
if (t == NULL) ERROR;
|
||||
return find_element((const char *)t->value);
|
||||
}
|
||||
|
||||
symbol_c *list_c::find_element(const char *token_value) {
|
||||
// We could use strcasecmp(), but it's best to always use the same
|
||||
// method of string comparison throughout matiec
|
||||
nocasecmp_c ncc;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (!ncc(elements[i].token_value, token_value))
|
||||
return elements[i].symbol;
|
||||
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
|
||||
/***********************************************/
|
||||
/* append a new element to the end of the list */
|
||||
void list_c::add_element(symbol_c *elem) {
|
||||
// printf("list_c::add_element()\n");
|
||||
/***********************************************/
|
||||
void list_c::add_element(symbol_c *elem) {add_element(elem, elem);}
|
||||
|
||||
void list_c::add_element(symbol_c *elem, symbol_c *token) {
|
||||
token_c *t = (token == NULL)? NULL : token->token;
|
||||
add_element(elem, (t == NULL)? NULL : t->value);
|
||||
}
|
||||
|
||||
void list_c::add_element(symbol_c *elem, const char *token_value) {
|
||||
if (c <= n)
|
||||
if (!(elements=(symbol_c**)realloc(elements,(c+=LIST_CAP_INCR)*sizeof(symbol_c *))))
|
||||
if (!(elements=(element_entry_t*)realloc(elements,(c+=LIST_CAP_INCR)*sizeof(element_entry_t))))
|
||||
ERROR_MSG("out of memory");
|
||||
elements[n++] = elem;
|
||||
|
||||
//elements[n++] = {token_value, elem}; // only available from C++11 onwards, best not use it for now.
|
||||
elements[n].symbol = elem;
|
||||
elements[n].token_value = token_value;
|
||||
n++;
|
||||
|
||||
if (NULL == elem) return;
|
||||
/* Sometimes add_element() is called in stage3 or stage4 to temporarily add an AST symbol to the list.
|
||||
* Since this symbol already belongs in some other place in the aST, it will have the 'parent' pointer set,
|
||||
@@ -143,10 +184,21 @@ void list_c::add_element(symbol_c *elem) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* insert a new element before position pos. */
|
||||
/*********************************************/
|
||||
/* To insert into the begining of list, call with pos=0 */
|
||||
/* To insert into the end of list, call with pos=list->n */
|
||||
void list_c::insert_element(symbol_c *elem, int pos) {
|
||||
|
||||
void list_c::insert_element(symbol_c *elem, int pos) {insert_element(elem, elem, pos);}
|
||||
|
||||
void list_c::insert_element(symbol_c *elem, symbol_c *token, int pos) {
|
||||
token_c *t = (token == NULL)? NULL : token->token;
|
||||
insert_element(elem, (t == NULL)? NULL : t->value, pos);
|
||||
}
|
||||
|
||||
void list_c::insert_element(symbol_c *elem, const char *token_value, int pos) {
|
||||
if((pos<0) || (n<pos)) ERROR;
|
||||
|
||||
/* add new element to end of list. Basically alocate required memory... */
|
||||
@@ -155,12 +207,15 @@ void list_c::insert_element(symbol_c *elem, int pos) {
|
||||
/* if not inserting into end position, shift all elements up one position, to open up a slot in pos for new element */
|
||||
if(pos < (n-1)){
|
||||
for(int i=n-2 ; i>=pos ; --i) elements[i+1] = elements[i];
|
||||
elements[pos] = elem;
|
||||
elements[pos].symbol = elem;
|
||||
elements[pos].token_value = token_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/* remove element at position pos. */
|
||||
/***********************************/
|
||||
void list_c::remove_element(int pos) {
|
||||
if((pos<0) || (n<=pos)) ERROR;
|
||||
|
||||
@@ -168,12 +223,14 @@ void list_c::remove_element(int pos) {
|
||||
for (int i = pos; i < n-1; i++) elements[i] = elements[i+1];
|
||||
/* corrent the new size */
|
||||
n--;
|
||||
/* elements = (symbol_c **)realloc(elements, n * sizeof(symbol_c *)); */
|
||||
/* elements = (symbol_c **)realloc(elements, n * sizeof(element_entry_t)); */
|
||||
/* TODO: adjust the location parameters, taking into account the removed element. */
|
||||
}
|
||||
|
||||
|
||||
/* remove element at position pos. */
|
||||
/**********************************/
|
||||
/* Remove all elements from list. */
|
||||
/**********************************/
|
||||
void list_c::clear(void) {
|
||||
n = 0;
|
||||
/* TODO: adjust the location parameters, taking into account the removed element. */
|
||||
|
||||
@@ -267,6 +267,7 @@ SYM_REF0(dword_type_name_c)
|
||||
SYM_REF0(lword_type_name_c)
|
||||
SYM_REF0(string_type_name_c)
|
||||
SYM_REF0(wstring_type_name_c)
|
||||
SYM_REF0(void_type_name_c) /* a non-standard extension! */
|
||||
|
||||
/*****************************************************************/
|
||||
/* Keywords defined in "Safety Software Technical Specification" */
|
||||
@@ -1287,4 +1288,5 @@ SYM_REF2(repeat_statement_c, statement_list, expression)
|
||||
/* EXIT */
|
||||
SYM_REF0(exit_statement_c)
|
||||
|
||||
|
||||
/* continue */
|
||||
SYM_REF0(continue_statement_c)
|
||||
|
||||
Executable → Regular
+51
-22
@@ -154,7 +154,8 @@ class const_value_c {
|
||||
{return (_int64.is_valid() || _uint64.is_valid() || _real64.is_valid() || _bool.is_valid());}
|
||||
};
|
||||
|
||||
|
||||
// A forward declaration
|
||||
class token_c;
|
||||
|
||||
/* The base class of all symbols */
|
||||
class symbol_c {
|
||||
@@ -167,7 +168,18 @@ class symbol_c {
|
||||
* Annotations produced during stage 1_2
|
||||
*/
|
||||
/* Points to the parent symbol in the AST, i.e. the symbol in the AST that will contain the current symbol */
|
||||
symbol_c *parent;
|
||||
symbol_c *parent;
|
||||
/* Some symbols may not be tokens, but may be clearly identified by a token.
|
||||
* For e.g., a FUNCTION declaration is not itself a token, but may be clearly identified by the
|
||||
* token_c object that contains it's name. Another example is an element in a STRUCT declaration,
|
||||
* where the structure_element_declaration_c is not itself a token, but can be clearly identified
|
||||
* by the structure_element_name
|
||||
* To make it easier to find these tokens from the top level object, we will have the stage1_2 populate this
|
||||
* token_c *token wherever it makes sense.
|
||||
* NOTE: This was a late addition to the AST. Not all objects may be currently so populated.
|
||||
* If you need this please make sure the bison code is populating it correctly for your use case.
|
||||
*/
|
||||
token_c *token;
|
||||
|
||||
/* Line number for the purposes of error checking. */
|
||||
int first_line;
|
||||
@@ -260,7 +272,14 @@ class list_c: public symbol_c {
|
||||
virtual const char *absyntax_cname(void) {return "list_c";};
|
||||
|
||||
int c,n; /* c: current capacity of list (malloc'd memory); n: current number of elements in list */
|
||||
symbol_c **elements;
|
||||
private:
|
||||
// symbol_c **elements;
|
||||
typedef struct {
|
||||
const char *token_value;
|
||||
symbol_c *symbol;
|
||||
} element_entry_t;
|
||||
element_entry_t *elements;
|
||||
|
||||
|
||||
public:
|
||||
list_c(int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, /* order in which it is read by lexcial analyser */
|
||||
@@ -271,12 +290,22 @@ class list_c: public symbol_c {
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, /* order in which it is read by lexcial analyser */
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0 /* order in which it is read by lexcial analyser */
|
||||
);
|
||||
/* get element in position pos of the list */
|
||||
virtual symbol_c *get_element(int pos);
|
||||
/* find element associated to token value */
|
||||
virtual symbol_c *find_element(symbol_c *token);
|
||||
virtual symbol_c *find_element(const char *token_value);
|
||||
/* append a new element to the end of the list */
|
||||
virtual void add_element(symbol_c *elem);
|
||||
virtual void add_element(symbol_c *elem, symbol_c *token);
|
||||
virtual void add_element(symbol_c *elem, const char *token_value);
|
||||
/* insert a new element before position pos. */
|
||||
/* To insert into the begining of list, call with pos=0 */
|
||||
/* To insert into the end of list, call with pos=list->n */
|
||||
virtual void insert_element(symbol_c *elem, int pos = 0);
|
||||
virtual void insert_element(symbol_c *elem, const char *token_value, int pos = 0);
|
||||
virtual void insert_element(symbol_c *elem, symbol_c *token, int pos = 0);
|
||||
virtual void insert_element(symbol_c *elem, int pos = 0);
|
||||
//virtual void insert_element(symbol_c *elem, int pos, std::string map_ref);
|
||||
/* remove element at position pos. */
|
||||
virtual void remove_element(int pos = 0);
|
||||
/* remove all elements from list. Does not delete the elements in the list! */
|
||||
@@ -342,7 +371,7 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref1; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
virtual void *accept(visitor_c &visitor); \
|
||||
@@ -358,7 +387,7 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref2; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
symbol_c *ref2 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
@@ -376,9 +405,9 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref3; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
symbol_c *ref2, \
|
||||
symbol_c *ref3, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
symbol_c *ref2 = NULL, \
|
||||
symbol_c *ref3 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
virtual void *accept(visitor_c &visitor); \
|
||||
@@ -396,9 +425,9 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref4; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
symbol_c *ref2, \
|
||||
symbol_c *ref3, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
symbol_c *ref2 = NULL, \
|
||||
symbol_c *ref3 = NULL, \
|
||||
symbol_c *ref4 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
@@ -418,11 +447,11 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref5; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
symbol_c *ref2, \
|
||||
symbol_c *ref3, \
|
||||
symbol_c *ref4, \
|
||||
symbol_c *ref5, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
symbol_c *ref2 = NULL, \
|
||||
symbol_c *ref3 = NULL, \
|
||||
symbol_c *ref4 = NULL, \
|
||||
symbol_c *ref5 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
virtual void *accept(visitor_c &visitor); \
|
||||
@@ -442,11 +471,11 @@ class class_name_c: public symbol_c { \
|
||||
symbol_c *ref6; \
|
||||
__VA_ARGS__ \
|
||||
public: \
|
||||
class_name_c(symbol_c *ref1, \
|
||||
symbol_c *ref2, \
|
||||
symbol_c *ref3, \
|
||||
symbol_c *ref4, \
|
||||
symbol_c *ref5, \
|
||||
class_name_c(symbol_c *ref1 = NULL, \
|
||||
symbol_c *ref2 = NULL, \
|
||||
symbol_c *ref3 = NULL, \
|
||||
symbol_c *ref4 = NULL, \
|
||||
symbol_c *ref5 = NULL, \
|
||||
symbol_c *ref6 = NULL, \
|
||||
int fl = 0, int fc = 0, const char *ffile = NULL /* filename */, long int forder=0, \
|
||||
int ll = 0, int lc = 0, const char *lfile = NULL /* filename */, long int lorder=0); \
|
||||
|
||||
Executable → Regular
+2
-2
@@ -168,7 +168,7 @@ iterator_visitor_c::~iterator_visitor_c(void) {return;}
|
||||
|
||||
void *iterator_visitor_c::visit_list(list_c *list) {
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
list->elements[i]->accept(*this);
|
||||
list->get_element(i)->accept(*this);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -310,7 +310,7 @@ search_visitor_c::~search_visitor_c(void) {return;}
|
||||
|
||||
void *search_visitor_c::visit_list(list_c *list) {
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
void *res = list->elements[i]->accept(*this);
|
||||
void *res = list->get_element(i)->accept(*this);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+1
-1
@@ -84,7 +84,7 @@ add_en_eno_param_decl_c::~add_en_eno_param_decl_c(void) {
|
||||
|
||||
void* add_en_eno_param_decl_c::iterate_list(list_c *list) {
|
||||
for (int i = 0; i < list->n; i++) {
|
||||
list->elements[i]->accept(*this);
|
||||
list->get_element(i)->accept(*this);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+1
-1
@@ -64,7 +64,7 @@
|
||||
void* array_dimension_iterator_c::iterate_list(list_c *list) {
|
||||
void *res;
|
||||
for (int i = 0; i < list->n; i++) {
|
||||
res = list->elements[i]->accept(*this);
|
||||
res = list->get_element(i)->accept(*this);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
+1
-1
@@ -78,7 +78,7 @@ void* case_element_iterator_c::handle_case_element(symbol_c *case_element) {
|
||||
void* case_element_iterator_c::iterate_list(list_c *list) {
|
||||
void *res;
|
||||
for (int i = 0; i < list->n; i++) {
|
||||
res = list->elements[i]->accept(*this);
|
||||
res = list->get_element(i)->accept(*this);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
}
|
||||
|
||||
Executable → Regular
@@ -56,12 +56,12 @@ static void dump_cvalue(const_value_c const_value) {
|
||||
else if (const_value._real64.is_nonconst()) fprintf(stderr, "nc");
|
||||
else fprintf(stderr, "?");
|
||||
fprintf(stderr, ", i=");
|
||||
if (const_value. _int64.is_valid ()) fprintf(stderr, "%"PRId64"", const_value. _int64.get());
|
||||
if (const_value. _int64.is_valid ()) fprintf(stderr, "%" PRId64 "", const_value. _int64.get());
|
||||
else if (const_value. _int64.is_overflow()) fprintf(stderr, "ov");
|
||||
else if (const_value. _int64.is_nonconst()) fprintf(stderr, "nc");
|
||||
else fprintf(stderr, "?");
|
||||
fprintf(stderr, ", u=");
|
||||
if (const_value._uint64.is_valid ()) fprintf(stderr, "%"PRIu64"", const_value._uint64.get());
|
||||
if (const_value._uint64.is_valid ()) fprintf(stderr, "%" PRIu64 "", const_value._uint64.get());
|
||||
else if (const_value._uint64.is_overflow()) fprintf(stderr, "ov");
|
||||
else if (const_value._uint64.is_nonconst()) fprintf(stderr, "nc");
|
||||
else fprintf(stderr, "?");
|
||||
@@ -120,13 +120,16 @@ void print_symbol_c::fcall(symbol_c* symbol) {
|
||||
|
||||
|
||||
void print_symbol_c::dump_symbol(symbol_c* symbol) {
|
||||
fprintf(stderr, "(%s->%03d:%03d..%03d:%03d) \t%s\t", symbol->first_file, symbol->first_line, symbol->first_column, symbol->last_line, symbol->last_column, symbol->absyntax_cname());
|
||||
fprintf(stderr, "(%s->%03d:%03d..%03d:%03d) \t%s", symbol->first_file, symbol->first_line, symbol->first_column, symbol->last_line, symbol->last_column, symbol->absyntax_cname());
|
||||
|
||||
fprintf(stderr, " datatype=");
|
||||
if ((NULL != symbol->token) && (NULL != symbol->token->value))
|
||||
fprintf(stderr, "(%s)", symbol->token->value);
|
||||
|
||||
fprintf(stderr, "\t datatype=");
|
||||
if (NULL == symbol->datatype)
|
||||
fprintf(stderr, "NULL\t\t");
|
||||
else {
|
||||
fprintf(stderr, "%s", symbol->datatype->absyntax_cname());
|
||||
fprintf(stderr, "%s", symbol->datatype->absyntax_cname());
|
||||
}
|
||||
fprintf(stderr, "\t<-{");
|
||||
if (symbol->candidate_datatypes.size() == 0) {
|
||||
@@ -153,26 +156,25 @@ void *print_symbol_c::visit(il_instruction_c *symbol) {
|
||||
dump_symbol(symbol);
|
||||
|
||||
/* NOTE: std::map.size() returns a size_type, whose type is dependent on compiler/platform. To be portable, we need to do an explicit type cast. */
|
||||
fprintf(stderr, " next_il_=%lu ", (unsigned long int)symbol->next_il_instruction.size());
|
||||
fprintf(stderr, " prev_il_=%lu ", (unsigned long int)symbol->prev_il_instruction.size());
|
||||
|
||||
if (symbol->prev_il_instruction.size() == 0)
|
||||
fprintf(stderr, "(----,");
|
||||
fprintf(stderr, "(----)");
|
||||
else if (symbol->prev_il_instruction[0]->datatype == NULL)
|
||||
fprintf(stderr, "(NULL,");
|
||||
fprintf(stderr, "(NULL)");
|
||||
else if (!get_datatype_info_c::is_type_valid(symbol->prev_il_instruction[0]->datatype))
|
||||
fprintf(stderr, "(****,");
|
||||
fprintf(stderr, "(****)");
|
||||
else
|
||||
fprintf(stderr, "( ,");
|
||||
|
||||
fprintf(stderr, "( )");
|
||||
|
||||
fprintf(stderr, " next_il_=%lu ", (unsigned long int)symbol->next_il_instruction.size());
|
||||
if (symbol->next_il_instruction.size() == 0)
|
||||
fprintf(stderr, "----)");
|
||||
fprintf(stderr, "(----)");
|
||||
else if (symbol->next_il_instruction[0]->datatype == NULL)
|
||||
fprintf(stderr, "NULL)");
|
||||
fprintf(stderr, "(NULL)");
|
||||
else if (!get_datatype_info_c::is_type_valid(symbol->next_il_instruction[0]->datatype))
|
||||
fprintf(stderr, "****)");
|
||||
fprintf(stderr, "(****)");
|
||||
else
|
||||
fprintf(stderr, " )");
|
||||
fprintf(stderr, "( )");
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+4
-4
@@ -67,7 +67,7 @@ void *function_call_param_iterator_c::search_list(list_c *list) {
|
||||
switch (current_operation) {
|
||||
case iterate_nf_op:
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
void *res = list->elements[i]->accept(*this);
|
||||
void *res = list->get_element(i)->accept(*this);
|
||||
if (NULL != res) {
|
||||
/* It went through the handle_parameter_assignment() function,
|
||||
* and is therefore a parameter assignment (<param> = <value>),
|
||||
@@ -77,7 +77,7 @@ void *function_call_param_iterator_c::search_list(list_c *list) {
|
||||
} else {
|
||||
param_count++;
|
||||
if (param_count == iterate_nf_next_param) {
|
||||
return list->elements[i];
|
||||
return list->get_element(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ void *function_call_param_iterator_c::search_list(list_c *list) {
|
||||
|
||||
case iterate_f_op:
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
void *res = list->elements[i]->accept(*this);
|
||||
void *res = list->get_element(i)->accept(*this);
|
||||
if (NULL != res) {
|
||||
/* It went through the handle_parameter_assignment() function,
|
||||
* and is therefore a parameter assignment (<param> = <value>),
|
||||
@@ -105,7 +105,7 @@ void *function_call_param_iterator_c::search_list(list_c *list) {
|
||||
|
||||
case search_f_op:
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
void *res = list->elements[i]->accept(*this);
|
||||
void *res = list->get_element(i)->accept(*this);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
}
|
||||
|
||||
Executable → Regular
@@ -167,7 +167,7 @@ void* function_param_iterator_c::handle_param_list(list_c *list) {
|
||||
switch (current_operation) {
|
||||
case iterate_op:
|
||||
if (next_param <= param_count + list->n)
|
||||
return list->elements[next_param - param_count - 1];
|
||||
return list->get_element(next_param - param_count - 1);
|
||||
|
||||
/* the desired param is not on this list... */
|
||||
param_count += list->n;
|
||||
@@ -175,7 +175,7 @@ void* function_param_iterator_c::handle_param_list(list_c *list) {
|
||||
|
||||
case search_op:
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
symbol_c *sym = list->elements[i];
|
||||
symbol_c *sym = list->get_element(i);
|
||||
extensible_input_parameter_c *extensible_parameter = dynamic_cast<extensible_input_parameter_c *>(sym);
|
||||
if (extensible_parameter != NULL) {
|
||||
sym = extensible_parameter->var_name;
|
||||
@@ -243,7 +243,7 @@ void* function_param_iterator_c::handle_single_param(symbol_c *var_name) {
|
||||
void* function_param_iterator_c::iterate_list(list_c *list) {
|
||||
void *res;
|
||||
for (int i = 0; i < list->n; i++) {
|
||||
res = list->elements[i]->accept(*this);
|
||||
res = list->get_element(i)->accept(*this);
|
||||
if (res != NULL)
|
||||
return res;
|
||||
}
|
||||
|
||||
Executable → Regular
@@ -127,6 +127,8 @@ class get_datatype_id_c: null_visitor_c {
|
||||
void *visit(safestring_type_name_c *symbol) {return (void *)symbol;};
|
||||
void *visit(safewstring_type_name_c *symbol) {return (void *)symbol;};
|
||||
|
||||
void *visit(void_type_name_c *symbol) {return (void *)symbol;};
|
||||
|
||||
/********************************/
|
||||
/* B 1.3.3 - Derived data types */
|
||||
/********************************/
|
||||
@@ -260,6 +262,8 @@ class get_datatype_id_str_c: public null_visitor_c {
|
||||
void *visit(safestring_type_name_c *symbol) {return (void *)"SAFESTRING"; };
|
||||
void *visit(safewstring_type_name_c *symbol) {return (void *)"SAFEWSTRING"; };
|
||||
|
||||
void *visit(void_type_name_c *symbol) {return (void *)"VOID"; };
|
||||
|
||||
/********************************/
|
||||
/* B.1.3.2 - Generic data types */
|
||||
/********************************/
|
||||
@@ -358,7 +362,7 @@ class get_struct_info_c : null_visitor_c {
|
||||
void *visit(structure_element_declaration_list_c *symbol) {
|
||||
/* now search the structure declaration */
|
||||
for(int i = 0; i < symbol->n; i++) {
|
||||
void *tmp = symbol->elements[i]->accept(*this);
|
||||
void *tmp = symbol->get_element(i)->accept(*this);
|
||||
if (NULL != tmp) return tmp;
|
||||
}
|
||||
return NULL; // not found!!
|
||||
@@ -709,8 +713,8 @@ bool get_datatype_info_c::is_arraytype_equal_relaxed(symbol_c *first_type, symbo
|
||||
|
||||
// comparison of each subrange start and end elements
|
||||
for (int i = 0; i < subrange_list_1->n; i++) {
|
||||
subrange_c *subrange_1 = dynamic_cast<subrange_c *>(subrange_list_1->elements[i]);
|
||||
subrange_c *subrange_2 = dynamic_cast<subrange_c *>(subrange_list_2->elements[i]);
|
||||
subrange_c *subrange_1 = dynamic_cast<subrange_c *>(subrange_list_1->get_element(i));
|
||||
subrange_c *subrange_2 = dynamic_cast<subrange_c *>(subrange_list_2->get_element(i));
|
||||
if ((NULL == subrange_1) || (NULL == subrange_2)) ERROR;
|
||||
|
||||
/* check whether the subranges have the same values, using the result of the constant folding agorithm.
|
||||
@@ -1352,6 +1356,21 @@ bool get_datatype_info_c::is_ANY_STRING_compatible(symbol_c *type_symbol) {
|
||||
|
||||
|
||||
|
||||
|
||||
bool get_datatype_info_c::is_VOID(symbol_c *type_symbol) {
|
||||
if (type_symbol == NULL) {return false;}
|
||||
if (typeid(*type_symbol) == typeid(void_type_name_c)) {return true;}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Can't we do away with this?? */
|
||||
bool get_datatype_info_c::is_ANY_REAL_literal(symbol_c *type_symbol) {
|
||||
if (type_symbol == NULL) {return true;} /* Please make sure things will work correctly before changing this to false!! */
|
||||
@@ -1381,6 +1400,7 @@ bool get_datatype_info_c::is_ANY_INT_literal(symbol_c *type_symbol) {
|
||||
|
||||
|
||||
invalid_type_name_c get_datatype_info_c::invalid_type_name;
|
||||
generic_type_any_c get_datatype_info_c::any_type_name;
|
||||
|
||||
/**********************/
|
||||
/* B.1.3 - Data types */
|
||||
|
||||
@@ -165,6 +165,8 @@ class get_datatype_info_c {
|
||||
static bool is_ANY_SAFESTRING (symbol_c *type_symbol);
|
||||
static bool is_ANY_STRING_compatible (symbol_c *type_symbol);
|
||||
|
||||
// A non-standard extension --> data type 'VOID' (used for functions that do not return any data)
|
||||
static bool is_VOID (symbol_c *type_symbol);
|
||||
|
||||
|
||||
|
||||
@@ -173,6 +175,9 @@ class get_datatype_info_c {
|
||||
/* This is only used from stage3 onwards. Stages 1 and 2 will never create any instances of invalid_type_name_c */
|
||||
static invalid_type_name_c invalid_type_name;
|
||||
|
||||
/* object used to identify ANY datya type */
|
||||
static generic_type_any_c any_type_name;
|
||||
|
||||
/**********************/
|
||||
/* B.1.3 - Data types */
|
||||
/**********************/
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+18
-24
@@ -184,6 +184,8 @@ void *search_base_type_c::visit(lword_type_name_c *symbol) {return (void
|
||||
void *search_base_type_c::visit(string_type_name_c *symbol) {return (void *)symbol;}
|
||||
void *search_base_type_c::visit(wstring_type_name_c *symbol) {return (void *)symbol;}
|
||||
|
||||
/* A non standard datatype! */
|
||||
void *search_base_type_c::visit(void_type_name_c *symbol) {return (void *)symbol;}
|
||||
|
||||
/******************************************************/
|
||||
/* Extensions to the base standard as defined in */
|
||||
@@ -253,7 +255,7 @@ void *search_base_type_c::visit(subrange_specification_c *symbol) {
|
||||
}
|
||||
|
||||
/* signed_integer DOTDOT signed_integer */
|
||||
void *search_base_type_c::visit(subrange_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(subrange_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* enumerated_type_name ':' enumerated_spec_init */
|
||||
void *search_base_type_c::visit(enumerated_type_declaration_c *symbol) {
|
||||
@@ -291,7 +293,7 @@ void *search_base_type_c::visit(enumerated_value_list_c *symbol) {
|
||||
|
||||
/* enumerated_type_name '#' identifier */
|
||||
// SYM_REF2(enumerated_value_c, type, value)
|
||||
void *search_base_type_c::visit(enumerated_value_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(enumerated_value_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* identifier ':' array_spec_init */
|
||||
void *search_base_type_c::visit(array_type_declaration_c *symbol) {
|
||||
@@ -310,20 +312,20 @@ void *search_base_type_c::visit(array_spec_init_c *symbol) {
|
||||
}
|
||||
|
||||
/* ARRAY '[' array_subrange_list ']' OF non_generic_type_name */
|
||||
void *search_base_type_c::visit(array_specification_c *symbol) {return (void *)symbol;}
|
||||
void *search_base_type_c::visit(array_specification_c *symbol) {return (void *)symbol;}
|
||||
|
||||
/* helper symbol for array_specification */
|
||||
/* array_subrange_list ',' subrange */
|
||||
void *search_base_type_c::visit(array_subrange_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(array_subrange_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* array_initialization: '[' array_initial_elements_list ']' */
|
||||
/* helper symbol for array_initialization */
|
||||
/* array_initial_elements_list ',' array_initial_elements */
|
||||
void *search_base_type_c::visit(array_initial_elements_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(array_initial_elements_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* integer '(' [array_initial_element] ')' */
|
||||
/* array_initial_element may be NULL ! */
|
||||
void *search_base_type_c::visit(array_initial_elements_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(array_initial_elements_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* structure_type_name ':' structure_specification */
|
||||
/* NOTE: structure_specification will point to either a
|
||||
@@ -337,31 +339,27 @@ void *search_base_type_c::visit(structure_type_declaration_c *symbol) {
|
||||
}
|
||||
|
||||
/* var1_list ':' structure_type_name */
|
||||
void *search_base_type_c::visit(structured_var_declaration_c *symbol) {
|
||||
return symbol;
|
||||
}
|
||||
void *search_base_type_c::visit(structured_var_declaration_c *symbol) {return symbol;}
|
||||
|
||||
/* structure_type_name ASSIGN structure_initialization */
|
||||
/* structure_initialization may be NULL ! */
|
||||
void *search_base_type_c::visit(initialized_structure_c *symbol) {
|
||||
return symbol->structure_type_name->accept(*this);
|
||||
}
|
||||
void *search_base_type_c::visit(initialized_structure_c *symbol) {return symbol->structure_type_name->accept(*this);}
|
||||
|
||||
/* helper symbol for structure_declaration */
|
||||
/* structure_declaration: STRUCT structure_element_declaration_list END_STRUCT */
|
||||
/* structure_element_declaration_list structure_element_declaration ';' */
|
||||
void *search_base_type_c::visit(structure_element_declaration_list_c *symbol) {return (void *)symbol;}
|
||||
void *search_base_type_c::visit(structure_element_declaration_list_c *symbol) {return (void *)symbol;}
|
||||
|
||||
/* structure_element_name ':' *_spec_init */
|
||||
void *search_base_type_c::visit(structure_element_declaration_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(structure_element_declaration_c *symbol) {return symbol->spec_init->accept(*this);}
|
||||
|
||||
/* helper symbol for structure_initialization */
|
||||
/* structure_initialization: '(' structure_element_initialization_list ')' */
|
||||
/* structure_element_initialization_list ',' structure_element_initialization */
|
||||
void *search_base_type_c::visit(structure_element_initialization_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(structure_element_initialization_list_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* structure_element_name ASSIGN value */
|
||||
void *search_base_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
void *search_base_type_c::visit(structure_element_initialization_c *symbol) {ERROR; return NULL;} /* should never get called... */
|
||||
|
||||
/* string_type_name ':' elementary_string_type_name string_type_declaration_size string_type_declaration_init */
|
||||
/*
|
||||
@@ -370,7 +368,7 @@ SYM_REF4(string_type_declaration_c, string_type_name,
|
||||
string_type_declaration_size,
|
||||
string_type_declaration_init) // may be == NULL!
|
||||
*/
|
||||
void *search_base_type_c::visit(string_type_declaration_c *symbol) {return (void *)symbol;}
|
||||
void *search_base_type_c::visit(string_type_declaration_c *symbol) {return (void *)symbol;}
|
||||
|
||||
|
||||
/* function_block_type_name ASSIGN structure_initialization */
|
||||
@@ -384,15 +382,13 @@ void *search_base_type_c::visit(fb_spec_init_c *symbol) {
|
||||
|
||||
/* ref_spec: REF_TO (non_generic_type_name | function_block_type_name) */
|
||||
// SYM_REF1(ref_spec_c, type_name)
|
||||
void *search_base_type_c::visit(ref_spec_c *symbol) {return (void *)symbol;}
|
||||
void *search_base_type_c::visit(ref_spec_c *symbol) {return (void *)symbol;}
|
||||
|
||||
/* For the moment, we do not support initialising reference data types */
|
||||
/* ref_spec_init: ref_spec [ ASSIGN ref_initialization ]; */
|
||||
/* NOTE: ref_initialization may be NULL!! */
|
||||
// SYM_REF2(ref_spec_init_c, ref_spec, ref_initialization)
|
||||
void *search_base_type_c::visit(ref_spec_init_c *symbol) {
|
||||
return symbol->ref_spec->accept(*this);
|
||||
}
|
||||
void *search_base_type_c::visit(ref_spec_init_c *symbol) {return symbol->ref_spec->accept(*this);}
|
||||
|
||||
/* ref_type_decl: identifier ':' ref_spec_init */
|
||||
// SYM_REF2(ref_type_decl_c, ref_type_name, ref_spec_init)
|
||||
@@ -408,9 +404,7 @@ void *search_base_type_c::visit(ref_type_decl_c *symbol) {
|
||||
/*****************************/
|
||||
/* FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations function_block_body END_FUNCTION_BLOCK */
|
||||
// SYM_REF3(function_block_declaration_c, fblock_name, var_declarations, fblock_body)
|
||||
void *search_base_type_c::visit(function_block_declaration_c *symbol) {
|
||||
return (void *)symbol;
|
||||
}
|
||||
void *search_base_type_c::visit(function_block_declaration_c *symbol) {return (void *)symbol;}
|
||||
|
||||
|
||||
|
||||
|
||||
Executable → Regular
+1
@@ -141,6 +141,7 @@ class search_base_type_c: public null_visitor_c {
|
||||
void *visit(lword_type_name_c *symbol);
|
||||
void *visit(string_type_name_c *symbol);
|
||||
void *visit(wstring_type_name_c *symbol);
|
||||
void *visit(void_type_name_c *symbol); /* A non standard datatype! */
|
||||
|
||||
/******************************************************/
|
||||
/* Extensions to the base standard as defined in */
|
||||
|
||||
Executable → Regular
+1
-1
@@ -95,7 +95,7 @@ void *search_fb_instance_decl_c::visit(fb_name_decl_c *symbol) {
|
||||
void *search_fb_instance_decl_c::visit(fb_name_list_c *symbol) {
|
||||
list_c *list = symbol;
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
if (compare_identifiers(list->elements[i], search_name) == 0)
|
||||
if (compare_identifiers(list->get_element(i), search_name) == 0)
|
||||
/* by now, current_fb_declaration should be != NULL */
|
||||
return current_fb_type_name;
|
||||
}
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
@@ -313,7 +313,7 @@ void *search_var_instance_decl_c::visit(var1_init_decl_c *symbol) {
|
||||
void *search_var_instance_decl_c::visit(var1_list_c *symbol) {
|
||||
list_c *list = symbol;
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
if (compare_identifiers(list->elements[i], search_name) == 0)
|
||||
if (compare_identifiers(list->get_element(i), search_name) == 0)
|
||||
/* by now, current_type_decl should be != NULL */
|
||||
return current_type_decl;
|
||||
}
|
||||
@@ -335,7 +335,7 @@ void *search_var_instance_decl_c::visit(fb_name_decl_c *symbol) {
|
||||
void *search_var_instance_decl_c::visit(fb_name_list_c *symbol) {
|
||||
list_c *list = symbol;
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
if (compare_identifiers(list->elements[i], search_name) == 0)
|
||||
if (compare_identifiers(list->get_element(i), search_name) == 0)
|
||||
/* by now, current_fb_declaration should be != NULL */
|
||||
return current_type_decl;
|
||||
}
|
||||
@@ -409,7 +409,7 @@ void *search_var_instance_decl_c::visit(global_var_spec_c *symbol) {
|
||||
void *search_var_instance_decl_c::visit(global_var_list_c *symbol) {
|
||||
list_c *list = symbol;
|
||||
for(int i = 0; i < list->n; i++) {
|
||||
if (compare_identifiers(list->elements[i], search_name) == 0)
|
||||
if (compare_identifiers(list->get_element(i), search_name) == 0)
|
||||
/* by now, current_type_decl should be != NULL */
|
||||
return current_type_decl;
|
||||
}
|
||||
|
||||
Executable → Regular
+1
-1
@@ -244,7 +244,7 @@ void *search_varfb_instance_type_c::visit(structure_element_declaration_list_c *
|
||||
|
||||
/* now search the structure declaration */
|
||||
for(int i = 0; i < symbol->n; i++) {
|
||||
symbol->elements[i]->accept(*this);
|
||||
symbol->get_element(i)->accept(*this);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
@@ -224,7 +224,7 @@ void *type_initial_value_c::visit(enumerated_value_list_c *symbol) {
|
||||
/* stage1_2 never creates an enumerated_value_list_c with no entries. If this occurs, then something must have changed! */
|
||||
if (symbol->n <= 0) ERROR;
|
||||
/* if no initial value explicitly given, then use the lowest value of the subrange */
|
||||
return (void *)symbol->elements[0];
|
||||
return (void *)symbol->get_element(0);
|
||||
}
|
||||
/* enumerated_type_name '#' identifier */
|
||||
// SYM_REF2(enumerated_value_c, type, value)
|
||||
|
||||
Executable → Regular
@@ -28,8 +28,7 @@ AC_PROG_RANLIB
|
||||
AC_PROG_AWK
|
||||
|
||||
# Check bison version, we need a version great or equal than 2.4 to build matiec.
|
||||
version_bison="$(bison --version | sed q | cut -d' ' -f4)"
|
||||
version_bison=${version_bison:0:3}
|
||||
version_bison="$(bison --version | sed q | cut -d' ' -f4 | cut -d'.' -f1,2 )"
|
||||
|
||||
AS_IF([awk -v ver="$version_bison" 'BEGIN { if (ver < 2.4) exit 1; }'],
|
||||
[have_bison_correct=yes], [have_bison_correct=no])
|
||||
@@ -42,6 +41,10 @@ if test "x${have_bison_correct}" = xno; then
|
||||
(exit 1); exit 1;
|
||||
fi
|
||||
|
||||
if test "x$LEX" == "x:"; then
|
||||
AC_MSG_ERROR("flex/lex is missing")
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([float.h limits.h stdint.h stdlib.h string.h strings.h sys/timeb.h unistd.h])
|
||||
|
||||
|
||||
Executable → Regular
+4
-1
@@ -122,6 +122,7 @@ static void printusage(const char *cmd) {
|
||||
printf(" as well as REF_TO in ARRAYs and STRUCTs (a non-standard extension!)\n");
|
||||
printf(" -a : allow use of non-literals in array size limits (a non-standard extension!)\n");
|
||||
printf(" -i : allow POUs with no in out and inout parameters (a non-standard extension!)\n");
|
||||
printf(" -b : allow functions returning VOID (a non-standard extension!)\n");
|
||||
printf(" -e : disable generation of implicit EN and ENO parameters.\n");
|
||||
printf(" -c : create conversion functions for enumerated data types\n");
|
||||
printf(" -O : options for output (code generation) stage. Available options for %s are...\n", cmd);
|
||||
@@ -145,6 +146,7 @@ int main(int argc, char **argv) {
|
||||
int path_len;
|
||||
|
||||
/* Default values for the command line options... */
|
||||
runtime_options.allow_void_datatype = false; /* disable: allow declaration of functions returning VOID */
|
||||
runtime_options.allow_missing_var_in = false; /* disable: allow definition and invocation of POUs with no input, output and in_out parameters! */
|
||||
runtime_options.disable_implicit_en_eno = false; /* disable: do not generate EN and ENO parameters */
|
||||
runtime_options.pre_parsing = false; /* disable: allow use of forward references (run pre-parsing phase before the definitive parsing phase that builds the AST) */
|
||||
@@ -163,7 +165,7 @@ int main(int argc, char **argv) {
|
||||
/******************************************/
|
||||
/* Parse command line options... */
|
||||
/******************************************/
|
||||
while ((optres = getopt(argc, argv, ":nehvfplsrRaicI:T:O:")) != -1) {
|
||||
while ((optres = getopt(argc, argv, ":nehvfplsrRabicI:T:O:")) != -1) {
|
||||
switch(optres) {
|
||||
case 'h':
|
||||
printusage(argv[0]);
|
||||
@@ -179,6 +181,7 @@ int main(int argc, char **argv) {
|
||||
runtime_options.ref_nonstand_extensions = true; break;
|
||||
case 'r': runtime_options.ref_standard_extensions = true; break;
|
||||
case 'a': runtime_options.nonliteral_in_array_size = true; break;
|
||||
case 'b': runtime_options.allow_void_datatype = true; break;
|
||||
case 'i': runtime_options.allow_missing_var_in = true; break;
|
||||
case 'c': runtime_options.conversion_functions = true; break;
|
||||
case 'n': runtime_options.nested_comments = true; break;
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
typedef struct {
|
||||
/* options specific to stage1_2 */
|
||||
bool allow_void_datatype; /* Allow declaration of functions returning VOID */
|
||||
bool allow_missing_var_in; /* Allow definition and invocation of POUs with no input, output and in_out parameters! */
|
||||
bool disable_implicit_en_eno; /* Disable the generation of implicit EN and ENO parameters on functions and Function Blocks */
|
||||
bool pre_parsing; /* Support forward references (Run a pre-parsing phase before the defintive parsing phase that builds the AST) */
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
include ../common.mk
|
||||
|
||||
## Flags for yacc syntax parser generator (bison)
|
||||
AM_YFLAGS = -d
|
||||
AM_LFLAGS = -o$(LEX_OUTPUT_ROOT).c
|
||||
## Flags for lex lexer generator (flex)
|
||||
AM_LFLAGS = --warn -o$(LEX_OUTPUT_ROOT).c
|
||||
|
||||
# Make sure this header file is generated first (by bison), as it is included
|
||||
# by other C++ code that will also be compiled.
|
||||
|
||||
@@ -119,7 +119,7 @@ void *create_enumtype_conversion_functions_c::visit(enumerated_value_list_c *sym
|
||||
currentTokenList.clear();
|
||||
list = (list_c *)symbol;
|
||||
for (int i = 0; i < list->n; i++) {
|
||||
list->elements[i]->accept(*this);
|
||||
list->get_element(i)->accept(*this);
|
||||
currentTokenList.push_back(currentToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ void yyerror (const char *error_msg);
|
||||
#define FOR_EACH_ELEMENT(elem, list, code) { \
|
||||
symbol_c *elem; \
|
||||
for(int i = 0; i < list->n; i++) { \
|
||||
elem = list->elements[i]; \
|
||||
elem = list->get_element(i); \
|
||||
code; \
|
||||
} \
|
||||
}
|
||||
@@ -373,6 +373,32 @@ typedef struct YYLTYPE {
|
||||
%type <leaf> prev_declared_derived_function_block_name
|
||||
%type <leaf> prev_declared_program_type_name
|
||||
|
||||
/* Tokens used to help resolve a reduce/reduce conflict */
|
||||
/* The mentioned conflict only arises due to a non-standard feature added to matiec.
|
||||
* Namely, the permission to call functions returning VOID as an ST statement.
|
||||
* e.g.: FUNCTION foo: VOID
|
||||
* VAR_INPUT i: INT; END_VAR;
|
||||
* ...
|
||||
* END_FUNCTION
|
||||
*
|
||||
* FUNCTION BAR: BOOL
|
||||
* VAR b: bool; END_VAR
|
||||
* foo(i:=42); <--- Calling foo outside an expression. Function invocation is considered an ST statement!!
|
||||
* END_FUNCTION
|
||||
*
|
||||
* The above function invocation may also be reduced to a formal IL function invocation, so we get a
|
||||
* reduce/reduce conflict to st_statement_list/instruction_list (or something equivalent).
|
||||
*
|
||||
* We solve this by having flex determine if it is ST or IL invocation (ST ends with a ';' !!).
|
||||
* At the start of a function/FB/program body, flex will tell bison whether to expect ST or IL code!
|
||||
* This is why we need the following two tokens!
|
||||
*
|
||||
* NOTE: flex was already determing whther it was parsing ST or IL code as it can only send
|
||||
* EOL tokens when parsing IL. However, did this silently without telling bison about this.
|
||||
* Now, it does
|
||||
*/
|
||||
%token start_ST_body_token
|
||||
%token start_IL_body_token
|
||||
|
||||
|
||||
|
||||
@@ -650,6 +676,9 @@ typedef struct YYLTYPE {
|
||||
%token TIME_OF_DAY
|
||||
%token TOD
|
||||
|
||||
/* A non-standard extension! */
|
||||
%token VOID
|
||||
|
||||
/******************************************************/
|
||||
/* Symbols defined in */
|
||||
/* "Safety Software Technical Specification, */
|
||||
@@ -1425,6 +1454,7 @@ typedef struct YYLTYPE {
|
||||
%type <leaf> while_statement
|
||||
%type <leaf> repeat_statement
|
||||
%type <leaf> exit_statement
|
||||
%type <leaf> continue_statement
|
||||
/* Integrated directly into for_statement */
|
||||
// %type <leaf> for_list
|
||||
|
||||
@@ -1444,6 +1474,7 @@ typedef struct YYLTYPE {
|
||||
%token END_REPEAT
|
||||
|
||||
%token EXIT
|
||||
%token CONTINUE
|
||||
|
||||
|
||||
%%
|
||||
@@ -3184,15 +3215,15 @@ structure_element_declaration_list:
|
||||
|
||||
structure_element_declaration:
|
||||
structure_element_name ':' simple_spec_init
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$));}
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$)); $$->token = $1->token;}
|
||||
| structure_element_name ':' subrange_spec_init
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$));}
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$)); $$->token = $1->token;}
|
||||
| structure_element_name ':' enumerated_spec_init
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$));}
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$)); $$->token = $1->token;}
|
||||
| structure_element_name ':' array_spec_init
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$));}
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$)); $$->token = $1->token;}
|
||||
| structure_element_name ':' initialized_structure
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$));}
|
||||
{$$ = new structure_element_declaration_c($1, $3, locloc(@$)); $$->token = $1->token;}
|
||||
| structure_element_name ':' ref_spec_init /* non standard extension: Allow use of struct elements storing REF_TO datatypes (either using REF_TO or a previosuly declared ref type) */
|
||||
{ $$ = new structure_element_declaration_c($1, $3, locloc(@$));
|
||||
if (!allow_ref_to_in_derived_datatypes) {
|
||||
@@ -3506,7 +3537,7 @@ variable:
|
||||
symbolic_variable
|
||||
| prev_declared_direct_variable
|
||||
| eno_identifier
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
;
|
||||
|
||||
|
||||
@@ -3515,15 +3546,15 @@ symbolic_variable:
|
||||
* prev_declared_variable_name | prev_declared_fb_name | prev_declared_global_var_name
|
||||
*/
|
||||
prev_declared_fb_name
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
| prev_declared_global_var_name
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
| prev_declared_variable_name
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
| multi_element_variable
|
||||
/*
|
||||
| identifier
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
*/
|
||||
| symbolic_variable '^'
|
||||
/* Dereferencing operator defined in IEC 61131-3 v3. However, implemented here differently then how it is defined in the standard! See following note for explanation! */
|
||||
@@ -3565,7 +3596,7 @@ symbolic_variable:
|
||||
any_symbolic_variable:
|
||||
// variable_name -> replaced by any_identifier
|
||||
any_identifier
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$));}
|
||||
{$$ = new symbolic_variable_c($1, locloc(@$)); $$->token = $1->token;}
|
||||
| any_multi_element_variable
|
||||
;
|
||||
|
||||
@@ -5008,6 +5039,14 @@ function_declaration:
|
||||
direct_variable_symtable.pop();
|
||||
library_element_symtable.insert($1, prev_declared_derived_function_name_token);
|
||||
}
|
||||
/* | FUNCTION derived_function_name ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION */
|
||||
| function_name_declaration ':' VOID io_OR_function_var_declarations_list function_body END_FUNCTION
|
||||
{$$ = new function_declaration_c($1, new void_type_name_c(locloc(@3)), $4, $5, locloc(@$));
|
||||
if (!runtime_options.disable_implicit_en_eno) add_en_eno_param_decl_c::add_to($$); /* add EN and ENO declarations, if not already there */
|
||||
variable_name_symtable.pop();
|
||||
direct_variable_symtable.pop();
|
||||
library_element_symtable.insert($1, prev_declared_derived_function_name_token);
|
||||
}
|
||||
/* ERROR_CHECK_BEGIN */
|
||||
| function_name_declaration elementary_type_name io_OR_function_var_declarations_list function_body END_FUNCTION
|
||||
{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing after function name in function declaration."); yynerrs++;}
|
||||
@@ -5172,8 +5211,8 @@ var2_init_decl_list:
|
||||
|
||||
|
||||
function_body:
|
||||
statement_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */
|
||||
| instruction_list {$$ = $1;} /* if we leave it for the default action we get a type clash! */
|
||||
start_ST_body_token statement_list {$$ = $2;}
|
||||
| start_IL_body_token instruction_list {$$ = $2;}
|
||||
/*
|
||||
| ladder_diagram
|
||||
| function_block_diagram
|
||||
@@ -5246,7 +5285,7 @@ function_block_declaration:
|
||||
{$$ = NULL; print_err_msg(locl(@2), locf(@3), "no variable(s) declared and body defined in function block declaration."); yynerrs++;}
|
||||
*/
|
||||
| FUNCTION_BLOCK derived_function_block_name io_OR_other_var_declarations_list function_block_body END_OF_INPUT
|
||||
{$$ = NULL; print_err_msg(locf(@1), locl(@2), "no variable(s) declared and body defined in function block declaration."); yynerrs++;}
|
||||
{$$ = NULL; print_err_msg(locf(@1), locl(@2), "expecting END_FUNCTION_BLOCK before end of file."); yynerrs++;}
|
||||
| FUNCTION_BLOCK error END_FUNCTION_BLOCK
|
||||
{$$ = NULL; print_err_msg(locf(@2), locl(@2), "unknown error in function block declaration."); yyerrok;}
|
||||
/* ERROR_CHECK_END */
|
||||
@@ -5355,9 +5394,21 @@ non_retentive_var_decls:
|
||||
|
||||
|
||||
function_block_body:
|
||||
statement_list {$$ = $1;}
|
||||
| instruction_list {$$ = $1;}
|
||||
| sequential_function_chart {$$ = $1;}
|
||||
/* NOTE: start_ST_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in ST
|
||||
* start_IL_body_token is a dummy token generated by flex when it determines it is starting to parse a POU body in IL
|
||||
* These tokens help remove a reduce/reduce conflict in bison, between a formal function invocation in IL, and a
|
||||
* function invocation used as a statement (a non-standard extension added to matiec)
|
||||
* e.g: FUNCTION_BLOCK foo
|
||||
* VAR ... END_VAR
|
||||
* func_returning_void(in1 := 3
|
||||
* ); --> only the presence or absence of ';' will determine whether this is a IL or ST
|
||||
* function invocation. (In standard ST this would be ilegal, in matiec we allow it
|
||||
* when activated by a command line option)
|
||||
* END_FUNCTION
|
||||
*/
|
||||
start_ST_body_token statement_list {$$ = $2;}
|
||||
| start_IL_body_token instruction_list {$$ = $2;}
|
||||
| sequential_function_chart {$$ = $1;}
|
||||
/*
|
||||
| ladder_diagram
|
||||
| function_block_diagram
|
||||
@@ -5797,17 +5848,17 @@ transition_priority:
|
||||
|
||||
|
||||
transition_condition:
|
||||
':' eol_list simple_instr_list
|
||||
{$$ = new transition_condition_c($3, NULL, locloc(@$));}
|
||||
start_IL_body_token ':' eol_list simple_instr_list
|
||||
{$$ = new transition_condition_c($4, NULL, locloc(@$));}
|
||||
| ASSIGN expression ';'
|
||||
{$$ = new transition_condition_c(NULL, $2, locloc(@$));}
|
||||
/* ERROR_CHECK_BEGIN */
|
||||
| eol_list simple_instr_list
|
||||
{$$ = NULL; print_err_msg(locl(@1), locf(@2), "':' missing before IL condition in transition declaration."); yynerrs++;}
|
||||
| ':' eol_list error
|
||||
| start_IL_body_token eol_list simple_instr_list
|
||||
{$$ = NULL; print_err_msg(locl(@2), locf(@3), "':' missing before IL condition in transition declaration."); yynerrs++;}
|
||||
| start_IL_body_token ':' eol_list error
|
||||
{$$ = NULL;
|
||||
if (is_current_syntax_token()) {print_err_msg(locl(@2), locf(@3), "no instructions defined in IL condition of transition declaration.");}
|
||||
else {print_err_msg(locf(@3), locl(@3), "invalid instructions in IL condition of transition declaration."); yyclearin;}
|
||||
if (is_current_syntax_token()) {print_err_msg(locl(@3), locf(@4), "no instructions defined in IL condition of transition declaration.");}
|
||||
else {print_err_msg(locf(@4), locl(@4), "invalid instructions in IL condition of transition declaration."); yyclearin;}
|
||||
yyerrok;
|
||||
}
|
||||
| ASSIGN ';'
|
||||
@@ -7856,6 +7907,15 @@ statement:
|
||||
| subprogram_control_statement
|
||||
| selection_statement
|
||||
| iteration_statement
|
||||
| function_invocation
|
||||
{ /* This is a non-standard extension (calling a function outside an ST expression!) */
|
||||
/* Only allow this if command line option has been selected... */
|
||||
$$ = $1;
|
||||
if (!runtime_options.allow_void_datatype) {
|
||||
print_err_msg(locf(@1), locl(@1), "Function invocation in ST code is not allowed outside an expression. To allow this non-standard syntax, activate the apropriate command line option.");
|
||||
yynerrs++;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
@@ -8248,6 +8308,7 @@ iteration_statement:
|
||||
| while_statement
|
||||
| repeat_statement
|
||||
| exit_statement
|
||||
| continue_statement
|
||||
;
|
||||
|
||||
|
||||
@@ -8330,7 +8391,7 @@ for_statement:
|
||||
*/
|
||||
control_variable:
|
||||
prev_declared_variable_name
|
||||
{$$ = new symbolic_variable_c($1,locloc(@$));};
|
||||
{$$ = new symbolic_variable_c($1,locloc(@$)); $$->token = $1->token;};
|
||||
// control_variable: identifier {$$ = $1;};
|
||||
|
||||
/* Integrated directly into for_statement */
|
||||
@@ -8391,7 +8452,9 @@ exit_statement:
|
||||
EXIT {$$ = new exit_statement_c(locloc(@$));}
|
||||
;
|
||||
|
||||
|
||||
continue_statement:
|
||||
CONTINUE {$$ = new continue_statement_c(locloc(@$));}
|
||||
;
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Executable → Regular
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user