OpenCores
URL https://opencores.org/ocsvn/zipcpu/zipcpu/trunk

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [zpp.l] - Rev 13

Go to most recent revision | Compare with Previous | Blame | View Log

/*******************************************************************************
**
** Filename:    zpp.l
**
** Project:     Zip CPU -- a small, lightweight, RISC CPU core
**
** Purpose:     The preprocessor for the Zip Assembler.
**
**      This routine strips comments, handles #define's, #ifdef's, and
**      #include statements in a C fashion.
**
**      #define macro's are also defined in the language and therefore
**      supposed to be supported, but the support isn't there yet.
**
** Creator:     Dan Gisselquist, Ph.D.
**              Gisselquist Tecnology, LLC
**
********************************************************************************
**
** Copyright (C) 2015, Gisselquist Technology, LLC
**
** This program is free software (firmware): 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 3 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 MERCHANTIBILITY 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.  (It's in the $(ROOT)/doc directory, run make with no
** target there if the PDF file isn't present.)  If not, see
** <http://www.gnu.org/licenses/> for a copy.
**
** License:     GPL, v3, as defined and found on www.gnu.org,
**              http://www.gnu.org/licenses/gpl.html
**
**
*******************************************************************************/

%{
// #include <FlexLexer.h>
#include <string>
#include <ctype.h>
#include <stdio.h>
#include <list>

using namespace std;

extern "C" int yylex();
// #include "zprepr.tab.h"
int     ndef = 0;
void    stb_define(const char *str);
void    stb_args(const char *str);
void    stb_macro(const char *value);
void    stb_addmacro(const char *value);
bool    stb_isdefined(const char *str);
const char      *stb_getdefn(const char *str);
%}
%x DEF DFA DFV INDEF IFDEFV INNOTDEF NODEF NVRDEF COMMENT
%x INDEF_EOL INNOTDEF_EOL
%option noyywrap
%option stack
ID [_:A-Za-z][_:A-Za-z0-9]*

%%
<COMMENT>"*/"           { yy_pop_state(); }
<COMMENT>[^*]+          { /* Ignore comments */ }
<COMMENT>"*"+[^/]       { /* Ignore comments */ }
<INITIAL,INDEF>^"#include"[ \t]+\"[^\"]+\"      {
                char *ptr = &yytext[9], *start, *end, *str;
                while(isspace(*ptr))
                        ptr++;
                start = ptr;
                ptr++;
                while((*ptr)&&(*ptr != '\"'))
                        ptr++;
                *ptr = '\0';
                yypush_buffer_state(yy_create_buffer(
                                        fopen(start, "r"),
                                        YY_BUF_SIZE));
                // push_file_state(yylineno); // and filename ...
                fprintf(yyout, "#line 0 \"%s\"\n", start);
        }
<INITIAL,INDEF>^"#define"[ \t]+ { yy_push_state(DEF); }
 /* <*>^"#line"[ \t]+(0-9)+[ \t]+["][^"]*["][ \t]*\n    { } */
<DEF>[_A-Za-z][_:A-Za-z0-9]*/[^(]       {
                stb_define(yytext);
                BEGIN DFV;
        }
<DEF>{ID}/[(]   { fprintf(stderr, "DEF::Found MACRO\n");
                stb_define(yytext);
                BEGIN DFA; }
<DFA>([^)]+)                            {
                /* Process arguments */
                stb_args(yytext);
                BEGIN DFV;
        }
<DFV>[ \t]+     { /* Ignore initial spaces */ }
<DFV>[.]*$      {/* Parse to end of line, get value for our define */
                // printf("End of define, value = \'%s\'\n", yytext);
                stb_macro(yytext);
                yy_pop_state();
        }
<INITIAL,INDEF>^[ \t]+.[dD][aA][tT][aA]?        { fprintf(yyout, "\tWORD"); }
<INITIAL,INDEF>^"#defcont"[ \t]+        { yy_push_state(DFV); }
<INITIAL,INDEF>^"#ifdef"[ \t]*  { ndef = 0; yy_push_state(IFDEFV); }
<INITIAL,INDEF>^"#ifndef"[ \t]* { ndef = 1; yy_push_state(IFDEFV); }
<IFDEFV>{ID}    {
                bool    known = stb_isdefined(yytext);
                if ( ((known)&&(ndef==0)) || ((!known)&&(ndef!=0)) ) {
                        BEGIN INDEF_EOL;
                } else {
                        BEGIN INNOTDEF_EOL;
                }
        }
        /* Not yet: <INITIAL,INDEF>^"#if"[ \t]*         { yy_push_state(IFDEFE); }
        /* Not yet: <INITIAL,INDEF>^"#if"[ \t]*         { yy_push_state(IFDEFE); }
        /* Not yet: <IFDEFE><expr> { yy_push_state(IFDEFE); } */
        /* <INNOTDEF>^"#elsif"[ \t]*    { yy_pop_state(); yy_push_state(IFDEFE); } */
<INDEF_EOL>[ \t]*$              { BEGIN INDEF; }
<INDEF_EOL>(;|"//").*$          { BEGIN INDEF; }
<INNOTDEF_EOL>[ \t]*$           { BEGIN INNOTDEF; }
<INNOTDEF_EOL>(;|"//").*$       { BEGIN INNOTDEF; }
<INDEF_EOL>[^ \t\n].*$          { BEGIN INDEF; fprintf(stderr, "WARNING! Unexpected characters on IFDEF line, \'%s\'\n", yytext); }
<INNOTDEF_EOL>[^ \t\n].*$       { BEGIN INNOTDEF; fprintf(stderr, "WARNING! Unexpected characters on IFNDEF line, %s\n", yytext); }
<INDEF,NVRDEF>^"#else"[ \t]*((;|"//").*)?$      { BEGIN NODEF; }
<INNOTDEF>^"#else"[ \t]*((;|"//").*)?$          { BEGIN INDEF; }
<INNOTDEF>(.*)                  { }
<INDEF>^"#elsif"[ \t]*          { BEGIN NVRDEF; }
<NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*((;|"//").*)?$     { yy_pop_state(); }
<NODEF,INDEF,INNOTDEF>^"#endif"[ \t]*"/*"       { BEGIN COMMENT; }
<*>^"#endif"[ \t]*              { fprintf(stderr, "ERR: Unknown endif!!\n");}
        /* Not yet: ^"#struct"[ \t]*    {}      */
        /* Not yet: ^"#endstruct"[ \t]* {}      */
        /* Not yet: ^"#seg"[ \t]*       {}      */
<NODEF,NVRDEF>.*                { /* Ignore everything in these states*/ }
<INITIAL,INDEF>{ID}/[^(]        { 
                if (stb_isdefined(yytext))
                        fprintf(yyout, "%s", stb_getdefn(yytext));
                else
                        fprintf(yyout, "%s", yytext);
        }
<*>^[ \t]*"//".*$       { /* Ignore comment only lines */ }
<*>^[ \t]*";".*$        { /* Ignore comment only lines */ }
<*>"//".*               { /* Ignore trailing comments */ }
<*>";".*                { /* Ignore trailing comments */ }
<*>"/*"                 { yy_push_state(COMMENT); }
<*>[ \t]+               { ECHO; }
<INITIAL,INDEF>[.]*     { ECHO; }
<*>\n                   { ECHO; }
        /* <*>.                 { printf("Unmatched \'%c\'\n", yytext[0]); } */
        /* <<EOF>>                      { printf("EOF!\n"); } */

%%

class   SYMTABLE_ENTRY {
private:
        std::string     &trim(std::string &s) {
                std::string::iterator   ptr = s.end();

                while((ptr >= s.begin())&&(isspace(*ptr)))
                        *ptr-- = '\0';

                return s;
        }

public:
        std::string     m_name, m_value, m_args;
        SYMTABLE_ENTRY(const char *str) : m_name(str) {
                trim(m_name);
        }
        SYMTABLE_ENTRY &operator+=(const char *str) {
                const char      *start = str;

                while(isspace(*start))
                        start++;
                if (m_value.length()!=0)
                        m_value += " ";

                std::string     trimd(start);
                trim(trimd);
                m_value += trimd;

                /*
                printf("ENTRY::SYMBOL \'%s\' NOW = \'%s\'\n",
                        m_name.c_str(), m_value.c_str());
                */
                return *this;
        }
        SYMTABLE_ENTRY &setargs(const char *str) {
                m_args += str;
                return *this;
        }

        std::string     getdefn(void) {
                return m_value;
        }
};

class   SYMBOL_TABLE {
private:
        typedef SYMTABLE_ENTRY  *TBLV;
        typedef std::list<TBLV> TBLT;

        TBLT    m_tbl;
        TBLT::iterator  lookup(const char *str) {
                TBLT::iterator  i = m_tbl.begin();
                for(; (i!= m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0); i++)
                        ;
                if ((i != m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())==0))
                        return i;
                return m_tbl.end();
        }

public:
        SYMBOL_TABLE(void) {}

        void define(const char *str) {
                SYMTABLE_ENTRY  *v = new SYMTABLE_ENTRY(str);
                TBLT::iterator  i = m_tbl.begin();
                for(; (i!= m_tbl.end())&&(strcmp(str, (*i)->m_name.c_str())>0); i++)
                        ;
                m_tbl.insert(i, v);

                // printf("SYMS::Defining SYMBOL: \'%s\'\n", str);
        }

        bool defined(const char *str) {
                TBLT::iterator  i = lookup(str);
                if (i==m_tbl.end())
                        return false;
                else
                        return true;
        }


        void    undefine(const char *str) {
                TBLT::iterator  i = lookup(str);
                if (i == m_tbl.end())
                        return;
                TBLV    v = (*i);
                m_tbl.erase(i);
                delete  v;
        }

        void    addmacro(const char *name, const char *str) {
                TBLT::iterator i = lookup(name);
                if (i == m_tbl.end()) {
                        fprintf(stderr, "INTERNAL ERR, %s NOT DEFINED!\n", name);
                } *(*i) += str;
        }
                                
        void    addargs(const char *name, const char *str) {
                TBLT::iterator i = lookup(name);
                if (i == m_tbl.end()) {
                        fprintf(stderr, "INTERNAL ERR, %s NOT DEFINED!\n", name);
                } (*i)->setargs(str);
        }
        const   char *getdefn(const char *name) {
                TBLT::iterator i = lookup(name);
                if (i == m_tbl.end()) {
                        fprintf(stderr, "INTERNAL ERR, %s NOT DEFINED!\n", name);
                        return NULL;
                } (*i)->getdefn().c_str();
        }
                                
};

SYMTABLE_ENTRY  *last = NULL;
SYMBOL_TABLE    syms;
std::string     last_define;

void    stb_define(const char *str) {
        if (syms.defined(str)) {
                fprintf(stderr, "WARNING!  Symbol \'%s\' is already defined!\n", str);
                syms.undefine(str);
        }

        syms.define(str);
        last_define = str;
}

void    stb_args(const char *args) {
        syms.addargs(last_define.c_str(), args);
}

void    stb_macro(const char *value) {
        syms.addmacro(last_define.c_str(), value);
}

void    stb_addmacro(const char *value) {
        syms.addmacro(last_define.c_str(),value);
}

bool    stb_isdefined(const char *str) {
        return syms.defined(str);
}

const char *stb_getdefn(const char *str) {
        return syms.getdefn(str);
}

int main(int argc, char **argv) {
        yylex();
}

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.