etisserant@0: /* msousa@261: * matiec - a compiler for the programming languages defined in IEC 61131-3 msousa@261: * Copyright (C) 2003-2011 Mario de Sousa (msousa@fe.up.pt) Edouard@279: * Copyright (C) 2007-2011 Laurent Bessard and Edouard Tisserant msousa@261: * msousa@261: * This program is free software: you can redistribute it and/or modify msousa@261: * it under the terms of the GNU General Public License as published by msousa@261: * the Free Software Foundation, either version 3 of the License, or msousa@261: * (at your option) any later version. msousa@261: * msousa@261: * This program is distributed in the hope that it will be useful, msousa@261: * but WITHOUT ANY WARRANTY; without even the implied warranty of msousa@261: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the msousa@261: * GNU General Public License for more details. msousa@261: * msousa@261: * You should have received a copy of the GNU General Public License msousa@261: * along with this program. If not, see . msousa@261: * etisserant@0: * etisserant@0: * This code is made available on the understanding that it will not be etisserant@0: * used in safety-critical situations without a full and competent review. etisserant@0: */ etisserant@0: etisserant@0: /* msousa@261: * An IEC 61131-3 compiler. etisserant@0: * etisserant@0: * Based on the etisserant@0: * FINAL DRAFT - IEC 61131-3, 2nd Ed. (2001-12-10) etisserant@0: * etisserant@0: */ etisserant@0: etisserant@0: /* etisserant@0: **************************************************************** etisserant@0: **************************************************************** etisserant@0: **************************************************************** etisserant@0: ********* ********* etisserant@0: ********* ********* etisserant@0: ********* O V E R A L L A R C H I T E C T U R E ********* etisserant@0: ********* ********* etisserant@0: ********* ********* etisserant@0: **************************************************************** etisserant@0: **************************************************************** etisserant@0: **************************************************************** etisserant@0: etisserant@0: The compiler works in 4(+1) stages: etisserant@0: Stage 1 - Lexical analyser - implemented with flex (iec.flex) etisserant@0: Stage 2 - Syntax parser - implemented with bison (iec.y) etisserant@0: Stage 3 - Semantics analyser - not yet implemented etisserant@0: Stage 4 - Code generator - implemented in C++ etisserant@0: Stage 4+1 - Binary code generator - gcc, javac, etc... etisserant@0: etisserant@0: etisserant@0: Data structures passed between stages, in global variables: etisserant@0: 1->2 : tokens (int), and token values (char *) etisserant@0: 2->1 : symbol tables (defined in symtable.hh) etisserant@0: 2->3 : abstract syntax tree (tree of C++ classes, in absyntax.hh file) etisserant@0: 3->4 : Same as 2->3 etisserant@0: 4->4+1 : file with program in c, java, etc... etisserant@0: etisserant@0: etisserant@0: The compiler works in several passes: etisserant@0: Pass 1: executes stages 1 and 2 simultaneously etisserant@0: Pass 2: executes stage 3 etisserant@0: Pass 3: executes stage 4 etisserant@0: Pass 4: executes stage 4+1 etisserant@0: */ etisserant@0: etisserant@0: etisserant@0: etisserant@0: //#include // printf() greg@186: #include etisserant@139: #include etisserant@0: #include // EXIT_FAILURE etisserant@0: #include "absyntax/absyntax.hh" // symbol_c type etisserant@0: etisserant@0: /* A macro for printing out internal parser errors... */ etisserant@0: #include // required for std::cerr etisserant@0: #define ERROR error_exit(__FILE__,__LINE__) etisserant@0: void error_exit(const char *file_name, int line_no) { etisserant@0: std::cerr << "\nInternal program error in file " << file_name etisserant@0: << " at line " << line_no << "\n\n\n"; etisserant@0: exit(EXIT_FAILURE); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: mario@177: mario@177: #include "stage1_2/stage1_2.hh" mario@181: #include "absyntax_utils/absyntax_utils.hh" mario@177: ccb@202: int stage3(symbol_c *tree_root); lbessard@46: int stage4(symbol_c *tree_root, const char *builddir); etisserant@0: etisserant@0: etisserant@0: static void printusage(const char *cmd) { mario@177: printf("syntax: %s [-h] [-f] [-s] [-I ] [-T ] \n", cmd); mario@177: printf(" h : show this help message\n"); lbessard@136: printf(" f : full token location on error messages\n"); mario@177: /******************************************************/ mario@177: /* whether we are suporting safe extensions */ mario@177: /* as defined in PLCopen - Technical Committee 5 */ mario@177: /* Safety Software Technical Specification, */ mario@177: /* Part 1: Concepts and Function Blocks, */ mario@177: /* Version 1.0 – Official Release */ mario@177: /******************************************************/ mario@177: printf(" s : allow use of safe extensions\n"); msousa@261: printf("\n"); msousa@261: printf("%s - Copyright (C) 2003-2011 \n" msousa@261: "This program comes with ABSOLUTELY NO WARRANTY!\n" msousa@261: "This is free software licensed under GPL v3, and you are welcome to redistribute it under the conditions specified by this license.\n", cmd); etisserant@0: } etisserant@0: etisserant@0: etisserant@0: etisserant@0: int main(int argc, char **argv) { etisserant@0: symbol_c *tree_root; lbessard@46: char * builddir = NULL; mario@177: stage1_2_options_t stage1_2_options = {false, false, NULL}; mario@177: int optres, errflg = 0; mario@177: /* mario@177: extern char *optarg; mario@177: extern int optind, optopt; mario@177: */ lbessard@46: mario@181: /******************************************/ mario@181: /* Parse command line options... */ mario@181: /******************************************/ mario@177: while ((optres = getopt(argc, argv, ":hfsI:T:")) != -1) { mario@177: switch(optres) { mario@177: case 'h': mario@177: printusage(argv[0]); mario@177: return 0; mario@177: break; mario@177: case 'f': mario@177: stage1_2_options.full_token_loc = true; mario@177: break; mario@177: case 's': mario@177: stage1_2_options.safe_extensions = true; mario@177: break; mario@177: case 'I': mario@177: stage1_2_options.includedir = optarg; mario@177: break; lbessard@179: case 'T': lbessard@179: builddir = optarg; lbessard@179: break; mario@177: case ':': /* -I or -T without operand */ mario@177: fprintf(stderr, "Option -%c requires an operand\n", optopt); mario@177: errflg++; mario@177: break; mario@177: case '?': mario@181: fprintf(stderr, "Unrecognized option: -%c\n", optopt); mario@181: errflg++; mario@181: break; mario@177: default: mario@181: fprintf(stderr, "Unknown error while parsing command line options."); mario@177: errflg++; mario@177: break; mario@177: } etisserant@0: } etisserant@0: mario@177: if (optind == argc) { mario@177: fprintf(stderr, "Missing input file\n"); mario@177: errflg++; lbessard@136: } lbessard@136: mario@177: if (optind > argc) { mario@177: fprintf(stderr, "Too many input files\n"); mario@177: errflg++; mario@177: } mario@177: mario@177: if (errflg) { lbessard@136: printusage(argv[0]); lbessard@136: return EXIT_FAILURE; lbessard@136: } lbessard@136: lbessard@136: mario@181: /***************************/ mario@181: /* Run the compiler... */ mario@181: /***************************/ etisserant@0: /* 1st Pass */ mario@177: if (stage1_2(argv[optind], &tree_root, stage1_2_options) < 0) etisserant@0: return EXIT_FAILURE; etisserant@0: etisserant@0: /* 2nd Pass */ msousa@315: /* basically loads some symbol tables to speed up look ups later on */ msousa@315: absyntax_utils_init(tree_root); msousa@315: /* moved to bison, although it could perfectly well still be here instead of in bison code. */ msousa@315: //add_en_eno_param_decl_c::add_to(tree_root); msousa@315: msousa@315: /* Only very simple (not yet complete) data type checking currently implemented... */ etisserant@0: if (stage3(tree_root) < 0) etisserant@0: return EXIT_FAILURE; ccb@202: etisserant@0: etisserant@0: /* 3rd Pass */ lbessard@46: if (stage4(tree_root, builddir) < 0) etisserant@0: return EXIT_FAILURE; etisserant@0: etisserant@0: /* 4th Pass */ msousa@315: /* Call gcc, g++, or whatever... */ etisserant@0: /* Currently implemented in the Makefile! */ etisserant@0: etisserant@0: return 0; etisserant@0: } etisserant@0: etisserant@0: