diff --git a/tests/VHDL_TreeWidget/VHDL_TreeWidget.pro b/tests/VHDL_TreeWidget/VHDL_TreeWidget.pro new file mode 100644 --- /dev/null +++ b/tests/VHDL_TreeWidget/VHDL_TreeWidget.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-08-23T00:04:05 +# +#------------------------------------------------- + +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = VHDL_TreeWidget + +DESTDIR = ../../bin + +TEMPLATE = app + +INCLUDEPATH += \ + $$DESTDIR/../vhdlparser \ + ../../vhdlparser + + +LIBS += -lfl -L${DESTDIR} -lvhdlparser + +SOURCES += main.cpp\ + mainwindow.cpp + +HEADERS += mainwindow.h + +FORMS += mainwindow.ui diff --git a/tests/VHDL_TreeWidget/main.cpp b/tests/VHDL_TreeWidget/main.cpp new file mode 100644 --- /dev/null +++ b/tests/VHDL_TreeWidget/main.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/tests/VHDL_TreeWidget/mainwindow.cpp b/tests/VHDL_TreeWidget/mainwindow.cpp new file mode 100644 --- /dev/null +++ b/tests/VHDL_TreeWidget/mainwindow.cpp @@ -0,0 +1,111 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + connect(this->ui->actionOpen,SIGNAL(triggered()),this,SLOT(openFile())); + connect(this->ui->actionScan_Folder,SIGNAL(triggered()),this,SLOT(openFolder())); + this->file = new VHDL_Tools::VHDL_File; + this->rootNode = NULL; +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::openFile() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open VHDL file"), NULL, tr("VHDL Files (*.vhd)")); + if(fileName!="") + { + parseFile(fileName,true); + this->rootNode=file->getParseTree(); + updateTree(rootNode); + } +} + +void MainWindow::openFolder() +{ + QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), + NULL, + QFileDialog::ShowDirsOnly + | QFileDialog::DontResolveSymlinks); + if(dir!="") + { + this->rootNode=new VHDL_Tools::VHDL_AST_Node(dir,VHDL_Tools::virtualGroup); + parseDirectory(dir); + updateTree(this->rootNode); + } +} + + +void MainWindow::updateTree(VHDL_Tools::VHDL_AST_Node *rootNode) +{ + this->ui->VHDLtreeWidget->clear(); + if(rootNode) + { + QTreeWidgetItem* item = new QTreeWidgetItem(QStringList()<a_value); + for(int i=0;ichilds.count();i++) + { + printNode(rootNode->childs.at(i),item); + } + this->ui->VHDLtreeWidget->addTopLevelItem(item); + } +} + +void MainWindow::printNode(VHDL_Tools::VHDL_AST_Node *rootNode, QTreeWidgetItem *parent) +{ + if(rootNode) + { + QTreeWidgetItem* item = new QTreeWidgetItem(parent,QStringList()<a_value); + for(int i=0;ichilds.count();i++) + { + printNode(rootNode->childs.at(i),item); + } + } +} + +void MainWindow::parseFile(const QString &fileName, bool trashPreviousTree) +{ + if(fileName!="") + this->file->parseFile(fileName,trashPreviousTree); +} + +void MainWindow::parseDirectory(const QString &dirName) +{ + QDir dir(dirName); + dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + QFileInfoList list = dir.entryInfoList(); + for (int i = 0; i < list.size(); ++i) + { + if(list.at(i).isDir()) + { + parseDirectory(list.at(i).fileName()); + } + else + { + if(list.at(i).isFile() && (!list.at(i).completeSuffix().compare("vhd"))) + { + parseFile(list.at(i).absoluteFilePath(),false); + VHDL_Tools::VHDL_AST_Node* parseTree = file->getParseTree(); + this->rootNode->childs.append(parseTree); + parseTree->parent = this->rootNode; + } + } + } +} + + + + + + + diff --git a/tests/VHDL_TreeWidget/mainwindow.h b/tests/VHDL_TreeWidget/mainwindow.h new file mode 100644 --- /dev/null +++ b/tests/VHDL_TreeWidget/mainwindow.h @@ -0,0 +1,33 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +private slots: + void openFile(); + void openFolder(); +private: + void updateTree(VHDL_Tools::VHDL_AST_Node* rootNode); + void printNode(VHDL_Tools::VHDL_AST_Node* rootNode,QTreeWidgetItem* parent); + void parseFile(const QString& fileName, bool trashPreviousTree=false); + void parseDirectory(const QString& dirName); + VHDL_Tools::VHDL_AST_Node* rootNode; + Ui::MainWindow *ui; + VHDL_Tools::VHDL_File* file; +}; + +#endif // MAINWINDOW_H diff --git a/tests/VHDL_TreeWidget/mainwindow.ui b/tests/VHDL_TreeWidget/mainwindow.ui new file mode 100644 --- /dev/null +++ b/tests/VHDL_TreeWidget/mainwindow.ui @@ -0,0 +1,70 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + + 1 + + + + + + + + + + 0 + 0 + 400 + 27 + + + + + File + + + + + + + + + TopToolBarArea + + + false + + + + + + Open + + + + + Scan Folder + + + + + + + diff --git a/tests/basic_VHDL_parser/basic_VHDL_parser.pro b/tests/basic_VHDL_parser/basic_VHDL_parser.pro --- a/tests/basic_VHDL_parser/basic_VHDL_parser.pro +++ b/tests/basic_VHDL_parser/basic_VHDL_parser.pro @@ -18,10 +18,6 @@ TEMPLATE = app INCLUDEPATH += \ $$DESTDIR/../vhdlparser \ ../../vhdlparser -# ../../../vhdlparser \ -# /opt/build-vhdl_tools-Qt_5_2_1_Syst_me-Debug/vhdlparser - -message($$DESTDIR) LIBS += -lfl -L${DESTDIR} -lvhdlparser @@ -29,4 +25,5 @@ LIBS += -lfl -L${DESTDIR} -lvhdlparser SOURCES += main.cpp OTHER_FILES += \ - test1.vhd + test1.vhd\ + test2.vhd diff --git a/tests/basic_VHDL_parser/test1.vhd b/tests/basic_VHDL_parser/test1.vhd --- a/tests/basic_VHDL_parser/test1.vhd +++ b/tests/basic_VHDL_parser/test1.vhd @@ -1,3 +1,32 @@ +package test is + component ramb4_s16 + port ( + do : out std_logic_vector (15 downto 0) + ); + end component; + + component ramb4_s16 + port ( + do : out std_logic_vector (15 downto 0) + ); + end component; + +end package; + +package test is + component cmp1 + port ( + do : out std_logic_vector (15 downto 0) + ); + end component; + + component cmp2 + port ( + do : out std_logic_vector (15 downto 0) + ); + end component; + +end package; ------------------------------------------------------------------------------ -- This file is a part of the GRLIB VHDL IP LIBRARY diff --git a/tests/basic_VHDL_parser/test2.vhd b/tests/basic_VHDL_parser/test2.vhd new file mode 100644 --- /dev/null +++ b/tests/basic_VHDL_parser/test2.vhd @@ -0,0 +1,261 @@ +LIBRARY IEEE; +USE IEEE.numeric_std.ALL; +USE IEEE.std_logic_1164.ALL; +LIBRARY grlib; +USE grlib.amba.ALL; +USE grlib.stdlib.ALL; +LIBRARY techmap; +USE techmap.gencomp.ALL; +LIBRARY gaisler; +USE gaisler.memctrl.ALL; +USE gaisler.leon3.ALL; +USE gaisler.uart.ALL; +USE gaisler.misc.ALL; +USE gaisler.spacewire.ALL; -- PLE +LIBRARY esa; +USE esa.memoryctrl.ALL; + +LIBRARY staging; +USE staging.SOC_LPP_JCP.ALL; + +ENTITY MINI_LFR_top IS + + PORT ( + clk_50 : IN STD_LOGIC; + clk_49 : IN STD_LOGIC; + reset : IN STD_LOGIC; + --BPs + BP0 : IN STD_LOGIC; + BP1 : IN STD_LOGIC; + --LEDs + LED0 : OUT STD_LOGIC; + LED1 : OUT STD_LOGIC; + LED2 : OUT STD_LOGIC; + --UARTs + TXD1 : IN STD_LOGIC; + RXD1 : OUT STD_LOGIC; + nCTS1 : OUT STD_LOGIC; + nRTS1 : IN STD_LOGIC; + + TXD2 : IN STD_LOGIC; + RXD2 : OUT STD_LOGIC; + nCTS2 : OUT STD_LOGIC; + nDTR2 : IN STD_LOGIC; + nRTS2 : IN STD_LOGIC; + nDCD2 : OUT STD_LOGIC; + + --EXT CONNECTOR + IO0 : INOUT STD_LOGIC; + IO1 : INOUT STD_LOGIC; + IO2 : INOUT STD_LOGIC; + IO3 : INOUT STD_LOGIC; + IO4 : INOUT STD_LOGIC; + IO5 : INOUT STD_LOGIC; + IO6 : INOUT STD_LOGIC; + IO7 : INOUT STD_LOGIC; + IO8 : INOUT STD_LOGIC; + IO9 : INOUT STD_LOGIC; + IO10 : INOUT STD_LOGIC; + IO11 : INOUT STD_LOGIC; + + --SPACE WIRE + SPW_EN : OUT STD_LOGIC; -- 0 => off + SPW_NOM_DIN : IN STD_LOGIC; -- NOMINAL LINK + SPW_NOM_SIN : IN STD_LOGIC; + SPW_NOM_DOUT : OUT STD_LOGIC; + SPW_NOM_SOUT : OUT STD_LOGIC; + SPW_RED_DIN : IN STD_LOGIC; -- REDUNDANT LINK + SPW_RED_SIN : IN STD_LOGIC; + SPW_RED_DOUT : OUT STD_LOGIC; + SPW_RED_SOUT : OUT STD_LOGIC; + -- MINI LFR ADC INPUTS + ADC_nCS : OUT STD_LOGIC; + ADC_CLK : OUT STD_LOGIC; + ADC_SDO : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + + -- SRAM + SRAM_nWE : OUT STD_LOGIC; + SRAM_CE : OUT STD_LOGIC; + SRAM_nOE : OUT STD_LOGIC; + SRAM_nBE : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); + SRAM_A : OUT STD_LOGIC_VECTOR(19 DOWNTO 0); + SRAM_DQ : INOUT STD_LOGIC_VECTOR(31 DOWNTO 0) + ); + +END MINI_LFR_top; + + +ARCHITECTURE beh OF MINI_LFR_top IS + +type DURATION is range -1E18 to 1E18 + units + fs; + ps = 1000 fs; + ns = 1000 ps; + us = 1000 ns; + ms = 1000 us; + sec = 1000 ms; + min = 60 sec; + end units; + + SIGNAL clk_50_s : STD_LOGIC := '0'; + SIGNAL clk_25 : STD_LOGIC := '0'; + ----------------------------------------------------------------------------- + SIGNAL coarse_time : STD_LOGIC_VECTOR(31 DOWNTO 0); + SIGNAL fine_time : STD_LOGIC_VECTOR(15 DOWNTO 0); + -- + SIGNAL errorn : STD_LOGIC; + -- UART AHB --------------------------------------------------------------- + SIGNAL ahbrxd : STD_ULOGIC; -- DSU rx data + SIGNAL ahbtxd : STD_ULOGIC; -- DSU tx data + + -- UART APB --------------------------------------------------------------- + SIGNAL urxd1 : STD_ULOGIC; -- UART1 rx data + SIGNAL utxd1 : STD_ULOGIC; -- UART1 tx data + -- + SIGNAL I00_s : STD_LOGIC; + -- + CONSTANT NB_APB_SLAVE : INTEGER := 1; + CONSTANT NB_AHB_SLAVE : INTEGER := 1; + CONSTANT NB_AHB_MASTER : INTEGER := 1; + + SIGNAL apbi_ext : apb_slv_in_type; + SIGNAL apbo_ext : soc_apb_slv_out_vector(NB_APB_SLAVE-1+5 DOWNTO 5):= (OTHERS => apb_none); + SIGNAL ahbi_s_ext : ahb_slv_in_type; + SIGNAL ahbo_s_ext : soc_ahb_slv_out_vector(NB_AHB_SLAVE-1+3 DOWNTO 3):= (OTHERS => ahbs_none); + SIGNAL ahbi_m_ext : AHB_Mst_In_Type; + SIGNAL ahbo_m_ext : soc_ahb_mst_out_vector(NB_AHB_MASTER-1+1 DOWNTO 1):= (OTHERS => ahbm_none); + +BEGIN -- beh + + ----------------------------------------------------------------------------- + -- CLK + ----------------------------------------------------------------------------- + + PROCESS(clk_50) + BEGIN + IF clk_50'EVENT AND clk_50 = '1' THEN + clk_50_s <= NOT clk_50_s; + END IF; + END PROCESS; + + PROCESS(clk_50_s) + BEGIN + IF clk_50_s'EVENT AND clk_50_s = '1' THEN + clk_25 <= NOT clk_25; + END IF; + END PROCESS; + + ----------------------------------------------------------------------------- + + PROCESS (clk_25, reset) + BEGIN -- PROCESS + IF reset = '0' THEN -- asynchronous reset (active low) + LED0 <= '0'; + LED1 <= '0'; + LED2 <= '0'; + IO1 <= '0'; + IO2 <= '1'; + IO3 <= '0'; + IO4 <= '0'; + IO5 <= '0'; + IO6 <= '0'; + IO7 <= '0'; + IO8 <= '0'; + IO9 <= '0'; + IO10 <= '0'; + IO11 <= '0'; + ELSIF clk_25'event AND clk_25 = '1' THEN -- rising clock edge + LED0 <= '0'; + LED1 <= '1'; + LED2 <= BP0; + IO1 <= '1'; + IO2 <= SPW_NOM_DIN OR SPW_NOM_SIN OR SPW_RED_DIN OR SPW_RED_SIN; + IO3 <= ADC_SDO(0); + IO4 <= ADC_SDO(1); + IO5 <= ADC_SDO(2); + IO6 <= ADC_SDO(3); + IO7 <= ADC_SDO(4); + IO8 <= ADC_SDO(5); + IO9 <= ADC_SDO(6); + IO10 <= ADC_SDO(7); + IO11 <= BP1 OR nDTR2 OR nRTS2 OR nRTS1; + END IF; + END PROCESS; + + PROCESS (clk_49, reset) + BEGIN -- PROCESS + IF reset = '0' THEN -- asynchronous reset (active low) + I00_s <= '0'; + ELSIF clk_49'event AND clk_49 = '1' THEN -- rising clock edge + I00_s <= NOT I00_s; + END IF; + END PROCESS; + IO0 <= I00_s; + + --UARTs + nCTS1 <= '1'; + nCTS2 <= '1'; + nDCD2 <= '1'; + + --EXT CONNECTOR + + --SPACE WIRE + SPW_EN <= '0'; -- 0 => off + + SPW_NOM_DOUT <= '0'; + SPW_NOM_SOUT <= '0'; + SPW_RED_DOUT <= '0'; + SPW_RED_SOUT <= '0'; + + ADC_nCS <= '0'; + ADC_CLK <= '0'; + + + leon3_soc_1: leon3_soc_LPP_JCP + GENERIC MAP ( + fabtech => apa3e, + memtech => apa3e, + padtech => inferred, + clktech => inferred, + disas => 0, + dbguart => 0, + pclow => 2, + clk_freq => 25000, + NB_CPU => 1, + ENABLE_FPU => 0, + FPU_NETLIST => 0, + ENABLE_DSU => 1, + ENABLE_AHB_UART => 1, + ENABLE_APB_UART => 1, + ENABLE_IRQMP => 1, + ENABLE_GPT => 1, + NB_AHB_MASTER => NB_AHB_MASTER, + NB_AHB_SLAVE => NB_AHB_SLAVE, + NB_APB_SLAVE => NB_APB_SLAVE) + PORT MAP ( + clk => clk_25, + rstn => reset, + errorn => errorn, + ahbrxd => TXD1, + ahbtxd => RXD1, + urxd1 => TXD2, + utxd1 => RXD2, + address => SRAM_A, + data => SRAM_DQ, + nSRAM_BE0 => SRAM_nBE(0), + nSRAM_BE1 => SRAM_nBE(1), + nSRAM_BE2 => SRAM_nBE(2), + nSRAM_BE3 => SRAM_nBE(3), + nSRAM_WE => SRAM_nWE, + nSRAM_CE => SRAM_CE, + nSRAM_OE => SRAM_nOE, + + apbi_ext => apbi_ext, + apbo_ext => apbo_ext, + ahbi_s_ext => ahbi_s_ext, + ahbo_s_ext => ahbo_s_ext, + ahbi_m_ext => ahbi_m_ext, + ahbo_m_ext => ahbo_m_ext); + +END beh; diff --git a/vhdl_tools.pro b/vhdl_tools.pro --- a/vhdl_tools.pro +++ b/vhdl_tools.pro @@ -16,7 +16,8 @@ CONFIG += ordered release SUBDIRS += \ vhdlparser \ - tests/basic_VHDL_parser + tests/basic_VHDL_parser \ + tests/VHDL_TreeWidget diff --git a/vhdlparser/scanner/Flex_Bison_FIles/vhdl.l b/vhdlparser/scanner/Flex_Bison_FIles/vhdl.l --- a/vhdlparser/scanner/Flex_Bison_FIles/vhdl.l +++ b/vhdlparser/scanner/Flex_Bison_FIles/vhdl.l @@ -13,8 +13,13 @@ /* msvc2010 requires that we exclude this header file. */ #define YY_NO_UNISTD_H + +/* handle locations */ +int yycolumn = 1; + +#define YY_USER_ACTION yycolumn += yyleng; + %} - %option debug %option nodefault %option yyclass="vhdl_Scanner" @@ -27,12 +32,14 @@ /*-----------------------------------------------------------*/ /*Separators*/ -[ \t\n]+ { } //skip new lines, blanc spaces and tabulations +[ \t]+ { } //skip new lines, blanc spaces and tabulations /*-----------------------------------------------------------*/ - +\n {yycolumn=1;} /*comment*/ ---.* {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::comment));} +--.* { + //this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::comment,yylineno, yycolumn-yyleng)); +} /*-----------------------------------------------------------*/ /*Reserved words*/ @@ -43,45 +50,31 @@ after | alias | all | and | -architecture | array | assert | attribute | begin | -block | body | buffer | bus | -case | -component | -configuration | -constant | disconnect | downto | else | elsif | -end | -entity | exit | file | -for | function | -generate | -generic | +generate | /* don't parse generate as block! just look for "if" or "for" */ group | guarded | -if | impure | in | inertial | inout | is | label | -library | linkage | literal | -loop | -map | mod | nand | new | @@ -95,14 +88,9 @@ open | or | others | out | -package | -port | postponed | -procedure | -process | pure | range | -record | register | reject | rem | @@ -113,89 +101,100 @@ ror | select | severity | shared | -signal | sla | sll | sra | srl | -subtype | then | to | transport | -type | unaffected | -units | until | -use | -variable | wait | when | while | with | xnor | xor | -(true|false) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::keyword));} +(true|false) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::keyword,yylineno, yycolumn-yyleng));} + +port {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::port,yylineno, yycolumn-yyleng));} + +generic {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::generic,yylineno, yycolumn-yyleng));} + +map {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::map,yylineno, yycolumn-yyleng));} + +architecture | +block | +case | +configuration | +component | +for | +if | +loop | +package | +procedure | +process | +protected | +record { + this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::block,yylineno, yycolumn-yyleng)); + } + +entity {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::entity,yylineno, yycolumn-yyleng));} - /* delimiter*/ -\. | \| | \[ | \] | -\:= | \>\= | -\<\= | -\/\= | -\= | -\> | -\< | -\& | -\‘ | -\=\> | -\: | -\<\> | -\; | -\, | -\( | -\) | -\* | -\+ | -\- | -\/ | -\*\* {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::separator)); } +units { + this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::units,yylineno, yycolumn-yyleng)); + } + +constant | +library | +signal | +subtype | +type | +use | +variable {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::clause,yylineno, yycolumn-yyleng));} + + + +end {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::endKw,yylineno, yycolumn-yyleng));} /*-----------------------------------------------------------*/ /*identifier (may be a reserved word)*/ -[a-z][a-z0-9\_]+[a-z] | +[a-z][a-z0-9\_\.]+[a-z0-9]+ | [a-z]+ | -\\.*\\ {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::identifier));} +\\.*\\ {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::identifier,yylineno, yycolumn-yyleng));} /*-----------------------------------------------------------*/ /*abstract literal (integer or floating point type)*/ /*Numerical literals*/ -(\+|\-)?([0-9\_]+)|(\+|\-)?([0-9\_]+E[0-9\_]+)|((2|3|4|5|6|7|8|9|10|11|12|13|14|15|16)\#[0-9\_]\#) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +(\+|\-)?([0-9\_]+)|(\+|\-)?([0-9\_]+E[0-9\_]+)|((2|3|4|5|6|7|8|9|10|11|12|13|14|15|16)\#[0-9\_]\#) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -(\+|\-)?[0-9\_]+\.[0-9\_]+|[0-9\_]+\.[0-9\_]+E[0-9\_]+ {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +(\+|\-)?[0-9\_]+\.[0-9\_]+|[0-9\_]+\.[0-9\_]+E[0-9\_]+ {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -\'(0|1)\' {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +\'(0|1)\' {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -\'.\' {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +\'.\' {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -(\+|\-)?([0-9\_]+)(fs|ps|ns|us|ms|sec|min|hr) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +(\+|\-)?([0-9\_]+)(fs|ps|ns|us|ms|sec|min|hr) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} /*Bit string literals*/ -\"[0-1\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +\"[0-1\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} /*String literals*/ -\".*\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +\".*\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -x\"[0-9A-F\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +x\"[0-9A-F\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} -o\"[0-7\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +o\"[0-7\_]+\" {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} /*The NULL literal*/ -\[NULL\] {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal));} +\[NULL\] {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::literal,yylineno, yycolumn-yyleng));} /*-----------------------------------------------------------*/ @@ -208,10 +207,39 @@ o\"[0-7\_]+\" {this->appendNode(new VHDL /* bit string literal (a sequence of extended digits * surrounded by ”, e.g.: ”011”)*/ /*-----------------------------------------------------------*/ + /* delimiter*/ +\. | \| | \[ | \] | +\:= | \>\= | +\<\= | +\/\= | +\= | +\> | +\< | +\& | +\‘ | +\' | +\=\> | +\<\> | +\, | +\* | +\+ | +\- | +\/ | +\*\* {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::separator,yylineno, yycolumn-yyleng)); } +\: {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::colon,yylineno, yycolumn-yyleng)); } +\( {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::leftParen,yylineno, yycolumn-yyleng));} + +\) {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::rightParen,yylineno, yycolumn-yyleng));} + + +\; {this->appendNode(new VHDL_Tools::VHDL_AST_Node(YYText(),VHDL_Tools::semicolon,yylineno, yycolumn-yyleng)); } + +. printf("bad input character '%s' at line %d column %d\n ", yytext, yylineno,yycolumn-yyleng); + %% diff --git a/vhdlparser/scanner/vhdl_ast_node.cpp b/vhdlparser/scanner/vhdl_ast_node.cpp new file mode 100644 --- /dev/null +++ b/vhdlparser/scanner/vhdl_ast_node.cpp @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the VHDL Tools Software +-- Copyright (C) 2014, Plasma Physics Laboratory - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@member.fsf.org +----------------------------------------------------------------------------*/ +#include "vhdl_ast_node.h" + + + +VHDL_Tools::VHDL_AST_Node::VHDL_AST_Node(const QString &value, VHDL_Tools::VHDL_AST_Node_type type, int line, int column) + :a_value(value),type(type),line(line),column(column) +{ + +} + +void VHDL_Tools::VHDL_AST_Node::move(VHDL_Tools::VHDL_AST_Node *parentNode) +{ + if(parentNode!=NULL) + { + this->parent->childs.removeOne(this); + parentNode->childs.append(this); + this->parent=parentNode; + } +} diff --git a/vhdlparser/scanner/vhdl_ast_node.h b/vhdlparser/scanner/vhdl_ast_node.h new file mode 100644 --- /dev/null +++ b/vhdlparser/scanner/vhdl_ast_node.h @@ -0,0 +1,78 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the VHDL Tools Software +-- Copyright (C) 2014, Plasma Physics Laboratory - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@member.fsf.org +----------------------------------------------------------------------------*/ +#ifndef VHDL_AST_NODE_H +#define VHDL_AST_NODE_H +#include +#include + +namespace VHDL_Tools{ + +#define closedByEnd 0x100 +#define closedBySemicolon 0x200 +#define closedByRightParen 0x300 + +#define IS_CLOSED_BY_END(type) (((type)&0xF00)==closedByEnd) +#define IS_CLOSED_BY_SEMICOLON(type) (((type)&0xF00)==closedBySemicolon) +#define IS_CLOSED_BY_RIGHTPAREN(type) (((type)&0xF00)==closedByRightParen) + +#define IS_CLOSED_BY(openType,type) ((type)==ExpectedCloseTypeLookUp[((openType)&0xF00)>>8]) + +enum VHDL_AST_Node_type { + none=0, + separator=1, + keyword=2, + leftParen=3|closedByRightParen, + rightParen=4, + block=5|closedByEnd, + units=6|closedByEnd, + entity=7|closedByEnd, + clause=8|closedBySemicolon, + semicolon=9, + colon=10, + generic=11, + port=12, + map=13, + endKw=14, + virtualGroup=15, + identifier=16, + literal=17, + rootNode=18, + comment=19 +}; + +const VHDL_AST_Node_type ExpectedCloseTypeLookUp[]={none,endKw,semicolon,rightParen,none,none,none,none,none,none,none,none,none,none,none,none}; + +class VHDL_AST_Node +{ +public: + VHDL_AST_Node(const QString& value,VHDL_Tools::VHDL_AST_Node_type type,int line=0, int column=0); + QString a_value; + VHDL_Tools::VHDL_AST_Node_type type; + int line; + int column; + VHDL_Tools::VHDL_AST_Node* parent; + QList childs; + void move(VHDL_Tools::VHDL_AST_Node* parentNode); +}; +} + +#endif // VHDL_AST_NODE_H diff --git a/vhdlparser/scanner/vhdl_fragment.cpp b/vhdlparser/scanner/vhdl_fragment.cpp new file mode 100644 --- /dev/null +++ b/vhdlparser/scanner/vhdl_fragment.cpp @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the VHDL Tools Software +-- Copyright (C) 2014, Plasma Physics Laboratory - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@member.fsf.org +----------------------------------------------------------------------------*/ +#include "vhdl_fragment.h" + +VHDL_Tools::VHDL_Fragment::VHDL_Fragment() +{ +} diff --git a/vhdlparser/scanner/vhdl_fragment.h b/vhdlparser/scanner/vhdl_fragment.h new file mode 100644 --- /dev/null +++ b/vhdlparser/scanner/vhdl_fragment.h @@ -0,0 +1,131 @@ +/*------------------------------------------------------------------------------ +-- This file is a part of the VHDL Tools Software +-- Copyright (C) 2014, Plasma Physics Laboratory - CNRS +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------------*/ +/*-- Author : Alexis Jeandet +-- Mail : alexis.jeandet@member.fsf.org +----------------------------------------------------------------------------*/ +#ifndef VHDL_FRAGMENT_H +#define VHDL_FRAGMENT_H +#include "vhdl_ast_node.h" +namespace VHDL_Tools { +class VHDL_Fragment +{ +public: + VHDL_Fragment(); + virtual void pushNode(VHDL_Tools::VHDL_AST_Node* node)=0; + VHDL_Tools::VHDL_AST_Node* node; +}; + +class VHDL_packaget: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_packaget() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_entity: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_entity() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_architecture: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_architecture() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_component: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_component() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_Library: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_Library() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_useClose: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_useClose() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_generic: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_generic() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_port: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_port() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_type: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_type() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_subtype: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_subtype() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_constant: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_constant() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +class VHDL_signal: public VHDL_Tools::VHDL_Fragment +{ +public: + VHDL_signal() {} + void pushNode(VHDL_Tools::VHDL_AST_Node* node); + QString name; +}; + +} +#endif // VHDL_FRAGMENT_H diff --git a/vhdlparser/scanner/vhdl_scanner.cpp b/vhdlparser/scanner/vhdl_scanner.cpp --- a/vhdlparser/scanner/vhdl_scanner.cpp +++ b/vhdlparser/scanner/vhdl_scanner.cpp @@ -22,25 +22,50 @@ #include "vhdl_scanner.h" #include -VHDL_Tools::vhdl_Scanner::vhdl_Scanner(std::istream *in) +VHDL_Tools::vhdl_Scanner::vhdl_Scanner(std::istream *in, const QString &fileName) : yyFlexLexer(in) { - this->rootNode = new VHDL_Tools::VHDL_AST_Node("rootNode",VHDL_Tools::rootNode); + this->rootNode = new VHDL_Tools::VHDL_AST_Node(fileName,VHDL_Tools::rootNode); + this->currentNode = rootNode; + this->rootNode->parent = this->rootNode; } +VHDL_Tools::vhdl_Scanner::~vhdl_Scanner() +{ + deleteNode(rootNode); +} + + int VHDL_Tools::vhdl_Scanner::scan() { return( yylex() ); } -void VHDL_Tools::vhdl_Scanner::stackData(QString data) +int VHDL_Tools::vhdl_Scanner::newFile(std::istream *in, const QString &fileName,bool trashPreviousTree) { - qDebug()<rootNode = new VHDL_Tools::VHDL_AST_Node(fileName,VHDL_Tools::rootNode); + this->currentNode = rootNode; + this->rootNode->parent = this->rootNode; + return 1; } + void VHDL_Tools::vhdl_Scanner::appendNode(VHDL_Tools::VHDL_AST_Node *node) { - this->rootNode->childs.append(node); + this->currentNode->childs.append(node); + node->parent = this->currentNode; + this->currentNode = node; } - +void VHDL_Tools::vhdl_Scanner::deleteNode(VHDL_Tools::VHDL_AST_Node *node) +{ + for(int i=0;ichilds.count();i++) + { + deleteNode(node->childs.at(i)); + } + node->parent->childs.removeAll(node); + delete node; +} diff --git a/vhdlparser/scanner/vhdl_scanner.h b/vhdlparser/scanner/vhdl_scanner.h --- a/vhdlparser/scanner/vhdl_scanner.h +++ b/vhdlparser/scanner/vhdl_scanner.h @@ -29,35 +29,39 @@ #include #include #include +#include +#include "vhdl_ast_node.h" +#include "vhdl_fragment.h" #undef YY_DECL #define YY_DECL int VHDL_Tools::vhdl_Scanner::yylex() namespace VHDL_Tools{ -enum VHDL_AST_Node_type {separator,keyword,identifier,literal,rootNode,comment}; -class VHDL_AST_Node +class vhdl_Scanner_block_stack { public: - VHDL_AST_Node(const QString& value,VHDL_Tools::VHDL_AST_Node_type type):value(value),type(type) {} - QString value; - VHDL_Tools::VHDL_AST_Node_type type; - VHDL_Tools::VHDL_AST_Node* parent; - QList childs; + vhdl_Scanner_block_stack(bool waitForSemicolon,bool waitForParen, int delta) + :waitForSemicolon(waitForSemicolon),waitForParen(waitForParen),stackDelta(delta){} + bool waitForSemicolon; + bool waitForParen; + int stackDelta; }; class vhdl_Scanner : public yyFlexLexer { public: - vhdl_Scanner(std::istream *in); + vhdl_Scanner(std::istream *in,const QString& fileName); + ~vhdl_Scanner(); int scan(); - + int newFile(std::istream *in, const QString& fileName, bool trashPreviousTree=false); + VHDL_Tools::VHDL_AST_Node* getScanTree(){return rootNode;} private: /* hide this one from public view */ int yylex(); - void stackData(QString data); void appendNode(VHDL_Tools::VHDL_AST_Node* node); - VHDL_Tools::VHDL_AST_Node* rootNode; + void deleteNode(VHDL_Tools::VHDL_AST_Node* node); + VHDL_Tools::VHDL_AST_Node* rootNode,*currentNode; }; } diff --git a/vhdlparser/vhdl_file.cpp b/vhdlparser/vhdl_file.cpp --- a/vhdlparser/vhdl_file.cpp +++ b/vhdlparser/vhdl_file.cpp @@ -1,30 +1,169 @@ #include "vhdl_file.h" - +#include VHDL_Tools::VHDL_File::VHDL_File() { this->scanner = NULL; } +#define walkForward( node , code ) \ + if((node)->childs.count())\ +{\ + (node) = (node)->childs.first();\ + }\ + else\ +{\ + return (code);\ + }\ -bool VHDL_Tools::VHDL_File::parseFile(const QString &file) + +#define skipTokens(node,TokenType) while ((node)->type==(TokenType)){walkForward((node),-1);} + +bool VHDL_Tools::VHDL_File::parseFile(const QString &file, bool trashPreviousTree) { std::ifstream in_file( file.toStdString().c_str() ); if( ! in_file.good() ) return false; - if(scanner) - delete(scanner); - try - { - scanner = new VHDL_Tools::vhdl_Scanner( &in_file ); - } - catch( std::bad_alloc &ba ) + // if(scanner) + // delete(scanner); + // try + // { + // scanner = new VHDL_Tools::vhdl_Scanner( &in_file ,file); + // } + // catch( std::bad_alloc &ba ) + // { + // std::cerr << "Failed to allocate scanner: (" << + // ba.what() << ")\n"; + // return false; + // } + if(scanner==NULL) { - std::cerr << "Failed to allocate scanner: (" << - ba.what() << ")\n"; - return false; + try + { + scanner = new VHDL_Tools::vhdl_Scanner( &in_file ,file); + } + catch( std::bad_alloc &ba ) + { + std::cerr << "Failed to allocate scanner: (" << + ba.what() << ")\n"; + return false; + } } + scanner->newFile(&in_file,file,trashPreviousTree); while (scanner->scan()!=0); - //parse(file.toStdString().c_str()); - + makeParseTree(scanner->getScanTree()); return false; } + +VHDL_Tools::VHDL_AST_Node *VHDL_Tools::VHDL_File::getParseTree() +{ + return rootNode; +} + +int VHDL_Tools::VHDL_File::makeParseTree(VHDL_AST_Node *rootNode) +{ + this->rootNode = rootNode; + VHDL_AST_Node *currentNode=rootNode; + QStack openBlocks; + openBlocks.push(rootNode); + while (currentNode) + { + switch (currentNode->type) + { + case block: + openBlocks.push(currentNode); + walkForward(currentNode,-1); + break; + case entity: + //Declaration or instanciation? + if(!((currentNode->parent->type == colon) && (currentNode->parent->parent->type==identifier))) + { + openBlocks.push(currentNode); + } + walkForward(currentNode,-1); + break; + case units: + if(openBlocks.top()->type==clause) + { + openBlocks.top()->type=units; + walkForward(currentNode,-1); + } + break; + case port: + currentNode->type = static_cast(currentNode->type | closedBySemicolon); + openBlocks.push(currentNode); + break; + case generic: + if(!(currentNode->childs.first()->type==map)) + { + currentNode->type = static_cast(currentNode->type | closedBySemicolon); + openBlocks.push(currentNode); + } + walkForward(currentNode,-1); + break; + case clause: + openBlocks.push(currentNode); + walkForward(currentNode,-1); + break; + case endKw: + closeAndMatchBlock(¤tNode,&openBlocks,QList()<parent->type==port)||(openBlocks.top()->parent->type==generic)) + closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); + else + closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); + break; + case semicolon: + if(IS_CLOSED_BY_SEMICOLON(openBlocks.top()->type)) + { + closeAndMatchBlock(¤tNode,&openBlocks,QList(),false); + } + else + { + walkForward(currentNode,0); + } + break; + default: + walkForward(currentNode,0); + break; + } + } + return 0; +} + +int VHDL_Tools::VHDL_File::closeAndMatchBlock(VHDL_Tools::VHDL_AST_Node **currentNode, QStack *openBlocksContext, QList skipTypes, bool endWithSemicolon) +{ + VHDL_AST_Node* startNode = openBlocksContext->pop(); + + if( IS_CLOSED_BY(startNode->type,(*currentNode)->type)) + { + walkForward((*currentNode),-1); + for(int i=0;itype==semicolon)) + { + walkForward((*currentNode),-1); + (*currentNode)->move(startNode->parent); + + } + else + { + (*currentNode)->move(startNode->parent); + } + } + else + { + // TODO improve message ! + qDebug() << "Got unexpected close token! @ line:" << (*currentNode)->line << " column:"<< (*currentNode)->column; + } + return 0; +} + + + diff --git a/vhdlparser/vhdl_file.h b/vhdlparser/vhdl_file.h --- a/vhdlparser/vhdl_file.h +++ b/vhdlparser/vhdl_file.h @@ -10,10 +10,13 @@ class VHDL_File public: VHDL_File(); - bool parseFile(const QString& file); - + bool parseFile(const QString& file, bool trashPreviousTree=false); + VHDL_Tools::VHDL_AST_Node* getParseTree(); private: VHDL_Tools::vhdl_Scanner *scanner; + int makeParseTree(VHDL_Tools::VHDL_AST_Node* rootNode); + int closeAndMatchBlock(VHDL_Tools::VHDL_AST_Node** currentNode,QStack* openBlocksContext,QListskipTypes,bool endWithSemicolon=false); + VHDL_Tools::VHDL_AST_Node* rootNode; }; } diff --git a/vhdlparser/vhdlparser.pro b/vhdlparser/vhdlparser.pro --- a/vhdlparser/vhdlparser.pro +++ b/vhdlparser/vhdlparser.pro @@ -23,11 +23,15 @@ INCLUDEPATH += \ SOURCES += vhdl_file.cpp \ - scanner/vhdl_scanner.cpp + scanner/vhdl_scanner.cpp \ + scanner/vhdl_fragment.cpp \ + scanner/vhdl_ast_node.cpp HEADERS += vhdl_file.h\ libvhdlparser_global.h \ - scanner/vhdl_scanner.h + scanner/vhdl_scanner.h \ + scanner/vhdl_fragment.h \ + scanner/vhdl_ast_node.h unix { target.path = /usr/lib