aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp74
-rw-r--r--src/parser/parse_tree.cpp5
-rw-r--r--src/parser/parser.l218
-rw-r--r--src/parser/parser.y12
-rw-r--r--src/parser/parser_state.h10
5 files changed, 209 insertions, 110 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 015648c..96af216 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,6 +16,7 @@
#include <specs.h>
#include "optical_output_port.h"
#include "parser/parse_tree.h"
+#include "parser/parser_state.h"
class OpticalOutputPort;
@@ -26,54 +27,10 @@ using namespace literals;
#include "../build/parser/parser.tab.h"
#include "../build/parser/parser.yy.h"
extern int yydebug;
-int yywrap(yyscan_t scanner);
-extern "C" int yy_delete_buffer(yyscan_t scanner);
-
-static deque<YY_BUFFER_STATE> netlist_buf_fifo;
-
-FILE* open_netlist_file(const string &filename, yyscan_t &scanner)
-{
- // Check whether the file exists
- FILE *f;
- if (filename == "-"s) {
- cerr << "Error: stdin not supported." << endl;
- exit(1);
- } else if (!(f = fopen(filename.c_str(), "r"))) {
- cerr << "Error: File not found \"" << filename << "\"" << endl;
- exit(1);
- }
-
- string header = "\n**** START of " + filename + " ****\n";
- netlist_buf_fifo.push_back(yy_scan_string(header.c_str(), scanner));
-
- YY_BUFFER_STATE buf = yy_create_buffer(f, YY_BUF_SIZE, scanner);
- netlist_buf_fifo.push_back(buf);
-
- string footer = "\n**** END of " + filename + " ****\n";
- netlist_buf_fifo.push_back(yy_scan_string(footer.c_str(), scanner));
-
- return f;
-}
-
-int yywrap(yyscan_t scanner)
-{
- static YY_BUFFER_STATE *last_buffer = NULL;
-
- if (netlist_buf_fifo.empty())
- return 1;
- else
- {
- YY_BUFFER_STATE buf = netlist_buf_fifo.front();
- netlist_buf_fifo.pop_front();
- yy_switch_to_buffer(buf, scanner);
- if ( last_buffer )
- {
- yy_delete_buffer( *last_buffer, scanner);
- last_buffer = &buf;
- }
- return 0;
- }
-}
+extern int yy_load_next_buf(yyscan_t scanner);
+extern void yy_add_content_from_string(const string &str, const string &desc, yyscan_t &scanner);
+extern void yy_add_content_from_file(const string &filename, yyscan_t &scanner);
+//extern "C" int yy_delete_buffer(yyscan_t scanner);
int do_list_tests()
{
@@ -121,9 +78,10 @@ int do_circuit(const string &filename, bool is_dry_run = false, const string& js
cout << "╚═══════════════════╝" << endl;
yyscan_t scanner;
+ ParserState *parser_state = new ParserState;
YY_BUFFER_STATE buf;
- yylex_init(&scanner);
+ yylex_init_extra(parser_state, &scanner);
buf = yy_create_buffer(f, YY_BUF_SIZE, scanner);
yy_switch_to_buffer(buf, scanner);
@@ -132,6 +90,7 @@ int do_circuit(const string &filename, bool is_dry_run = false, const string& js
//yy_delete_buffer(buf, scanner);
yylex_destroy(scanner);
+ delete parser_state;
// Close the file
if (f)
@@ -184,23 +143,19 @@ int do_circuit(const string &filename, bool is_dry_run = false, const string& js
int build_circuit(ParseTree &pt, const vector<string> &filenames, string footer="")
{
yyscan_t scanner;
- yylex_init(&scanner);
+ yylex_init_extra(new ParserState(), &scanner);
- vector<FILE*> files;
for(const auto &fname: filenames)
- {
- FILE * f = open_netlist_file(fname, scanner);
- files.push_back(f);
- }
+ yy_add_content_from_file(fname, scanner);
// add footer
- netlist_buf_fifo.push_back(yy_scan_string(footer.c_str(), scanner));
+ yy_add_content_from_string(footer, "footer autogenerated from command line arguments", scanner);
// Set up first file
- int res = yywrap(scanner);
+ int res = yy_load_next_buf(scanner);
if(res != 0)
{
- cerr << "Expected yywrap to return 0" << endl;
+ cerr << "Expected yy_load_next_buf to return 0" << endl;
exit(1);
}
@@ -213,9 +168,6 @@ int build_circuit(ParseTree &pt, const vector<string> &filenames, string footer=
//yy_delete_buffer(buf, scanner);
yylex_destroy(scanner);
- for (auto &f: files)
- fclose(f);
-
// Return if unsuccessful
if (parsing_result != 0) {
return parsing_result;
diff --git a/src/parser/parse_tree.cpp b/src/parser/parse_tree.cpp
index 76c67b0..bbafeb8 100644
--- a/src/parser/parse_tree.cpp
+++ b/src/parser/parse_tree.cpp
@@ -1,6 +1,7 @@
#include "parse_tree.h"
#include "parse_directive.h"
#include "parse_element.h"
+#include "parser_state.h"
#include "specs.h"
#include <sstream>
@@ -310,9 +311,10 @@ ParseTree::ParseTree(const string &name, const ParseSubcircuit &subcircuit, cons
}
yyscan_t scanner;
+ ParserState *parser_state = new ParserState;
YY_BUFFER_STATE buf;
- yylex_init(&scanner);
+ yylex_init_extra(parser_state, &scanner);
buf = yy_scan_string(subcircuit.netlist.c_str(), scanner);
yy_switch_to_buffer(buf, scanner);
@@ -320,6 +322,7 @@ ParseTree::ParseTree(const string &name, const ParseSubcircuit &subcircuit, cons
//yy_delete_buffer(buf, scanner);
yylex_destroy(scanner);
+ delete parser_state;
// Return if unsuccessful
if (parsing_result != 0) {
diff --git a/src/parser/parser.l b/src/parser/parser.l
index 3edda2f..3519d0d 100644
--- a/src/parser/parser.l
+++ b/src/parser/parser.l
@@ -12,39 +12,54 @@ BIN_OPERATOR [,=\*/\+\-\^]
PAR_OPERATOR [\{\}\(\)\[\]<>]
OPERATOR {BIN_OPERATOR}|{PAR_OPERATOR}|{BIDIR_SPECIFIER}
-
WS [  \t]
WS_BREAK (?:[^{WS}])
/* EOL_DOS \r\n */
/* EOL_UNIX \n */
-/* EOL_OLD_MAC \n */
+/* EOL_OLD_MAC \r */
EOL_PORTABLE \r?\n
EOL {EOL_PORTABLE}
%option warn
%option yylineno
-/*%option noyywrap*/
+%option noyywrap
%option caseless
%option reentrant
%option bison-bridge
%option stack
+%option extra-type="void *"
%{
#include <string>
#include <sstream> // for conversions of numbers from str
#include <cstring> // for strcpy
#include <vector>
+#include <deque>
#include "parse_tree.h"
+#include "parser_state.h"
#include "parser.tab.h"
using std::string;
using std::vector;
+using std::deque;
+
+typedef struct {
+ enum type {
+ NETLIST_FILE,
+ STRING
+ } type;
+ string description;
+ YY_BUFFER_STATE buf;
+ FILE *fp = nullptr;
+} netlist_content_t;
+
+deque<netlist_content_t> netlist_content_fifo;
#define YY_NO_INPUT
#define YY_NO_UNPUT
-#define YY_EXTRA_TYPE void*
+#define YY_EXTRA_TYPE void *
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size, yyscan_t scanner);
void yypush_buffer_state ( YY_BUFFER_STATE buffer, yyscan_t scanner);
@@ -54,12 +69,120 @@ int yyget_column ( yyscan_t scanner );
void yyset_extra ( YY_EXTRA_TYPE user_defined, yyscan_t scanner );
YY_EXTRA_TYPE yyget_extra ( yyscan_t scanner );
+string yyget_filename ( yyscan_t scanner );
+string yyget_current_line ( yyscan_t scanner );
+
+string yyget_filename ( yyscan_t scanner )
+{
+ const ParserState *yy_extra = (ParserState *)yyget_extra(scanner);
+ return yy_extra->current_filename;
+}
+
+void yyset_filename (string fname, yyscan_t scanner)
+{
+ ParserState *yy_extra = (ParserState *)yyget_extra(scanner);
+ yy_extra->current_filename = fname;
+}
+
+string yyget_current_line ( yyscan_t scanner )
+{
+ const ParserState *yy_extra = (ParserState *)yyget_extra(scanner);
+ return yy_extra->current_line;
+}
+
+void yyset_current_line (string line_content, yyscan_t scanner)
+{
+ ParserState *yy_extra = (ParserState *)yyget_extra(scanner);
+ yy_extra->current_line = line_content;
+}
+
+int yy_load_next_buf(yyscan_t scanner)
+{
+ static FILE *last_file = nullptr;
+
+ if ( last_file )
+ {
+ fclose(last_file);
+ }
+
+ if (netlist_content_fifo.empty())
+ {
+ yyset_filename("-"s, scanner);
+ return 1;
+ }
+ else
+ {
+ auto netlist_content = netlist_content_fifo.front();
+ netlist_content_fifo.pop_front();
+
+ string filename = netlist_content.description;
+ if (netlist_content.type == netlist_content_t::STRING)
+ filename = "[autogenerated - " + filename + "]";
+ yyset_filename(filename, scanner);
+ yy_switch_to_buffer(netlist_content.buf, scanner);
+
+ last_file = netlist_content.fp;
+ return 0;
+ }
+}
+
+void yy_add_content_from_string(const string &str, const string &desc, yyscan_t &scanner)
+{
+ // Allocate memory for the string (c-style)
+ // necessary as flex will delete the buffer
+ char* cstr = new char[str.size() + 1];
+
+ // Copy the contents of the std::string to the new memory
+ std::strcpy(cstr, str.c_str());
+
+ netlist_content_t netlist_content;
+
+ netlist_content.type = netlist_content_t::STRING;
+ netlist_content.description = desc;
+ netlist_content.buf = yy_scan_string(cstr, scanner);
+ netlist_content.fp = nullptr;
+ netlist_content_fifo.push_back(netlist_content);
+}
+
+void yy_add_content_from_file(const string &filename, yyscan_t &scanner)
+{
+ // Check whether the file exists
+ FILE *f;
+ if (filename == "-"s) {
+ cerr << "Error: stdin not supported." << endl;
+ exit(1);
+ } else if (!(f = fopen(filename.c_str(), "r"))) {
+ cerr << "Error: File not found \"" << filename << "\"" << endl;
+ exit(1);
+ }
+
+ netlist_content_t netlist_content;
+
+ {
+ stringstream ss;
+ ss << endl << "*** START of " << filename << " ***" << endl;
+ yy_add_content_from_string(ss.str(), "header for " + filename, scanner);
+ }
+
+ netlist_content.type = netlist_content_t::NETLIST_FILE;
+ netlist_content.description = filename;
+ netlist_content.buf = yy_create_buffer(f, YY_BUF_SIZE, scanner);
+ netlist_content.fp = f;
+ netlist_content_fifo.push_back(netlist_content);
+
+ {
+ stringstream ss;
+ ss << endl << "*** END of " << filename << " ***" << endl;
+ yy_add_content_from_string(ss.str(), "footer for " + filename, scanner);
+ }
+}
+
int yylerror(yyscan_t scanner, const char *p)
{
- cerr << "error (line " << yyget_lineno(scanner) << "): " << p << endl;
- string * str = (string *)yyget_extra(scanner);
- if (str)
- cerr << "\twhile parsing line: " << *str << endl;
+ cerr << "Parsing error (" << yyget_filename(scanner) << ":" << yyget_lineno(scanner) << "): " << p << endl;
+ string str = yyget_current_line(scanner);
+ if (!str.empty())
+ cerr << "-- while parsing line: \"" << str << "\"" << endl;
return 3;
}
@@ -77,6 +200,30 @@ static T from_string(const string &str)
return ret;
}
+string convert_special_char(char c)
+{
+ stringstream ss;
+ switch (c)
+ {
+ case '\r':
+ ss << "\\r";
+ break;
+ case '\n':
+ ss << "\\n";
+ break;
+ case '\t':
+ ss << "\\t";
+ break;
+ case '\b':
+ ss << "\\b";
+ break;
+ default:
+ ss << c;
+ break;
+ }
+ return ss.str();
+}
+
%}
/*** States ***/
@@ -93,14 +240,9 @@ static T from_string(const string &str)
%% /*** Rules section ***/
-^.*{EOL} {
- // print the netlist as it is read
- // note: doesnt handle included files
- if(false)
- cout << yytext; REJECT;
+<INITIAL,SUBCKT_DEFINITION>^\.include {
+ yy_push_state(INCLUDE, yyscanner);
}
-
-^\.include {yy_push_state(INCLUDE, yyscanner);}
<INCLUDE>{WS}* /* eat the whitespace */
<INCLUDE>[^ ;\t\n\r]+ { /* got the include file name */
yyin = fopen( yytext, "r" );
@@ -326,7 +468,7 @@ static T from_string(const string &str)
}
<INITIAL>^\.ENDS {
- cerr << "Unexpeced '.ENDS' directive" << endl;
+ cerr << "unexpected '.ENDS' directive" << endl;
exit(1);
}
@@ -363,12 +505,10 @@ static T from_string(const string &str)
{WS} ;
-^.*/{EOL} {
- string * str = (string *)yyget_extra(yyscanner);
- if (!str)
- str = new string;
- *str = yytext;
- yyset_extra((void *)str, yyscanner);
+<*>^.*/{EOL} {
+ yyset_current_line(yytext, yyscanner);
+ if (false)
+ cout << yytext << endl;
REJECT;
}
@@ -387,41 +527,29 @@ static T from_string(const string &str)
{EOL} { return '\n'; }
-<INITIAL,INCLUDE><<EOF>> {
+
+<INITIAL><<EOF>> {
yypop_buffer_state(yyscanner);
if ( !YY_CURRENT_BUFFER )
{
- yyterminate();
+ if ( ! yy_load_next_buf(yyscanner) )
+ return '\n';
+ else
+ yyterminate();
}
return '\n';
}
-<SUBCKT_DECLARATION,IN_DQUOTES><<EOF>> {
- exit(yylerror(yyscanner, "Unexpected end of file."));
+<SUBCKT_DECLARATION,IN_DQUOTES,INCLUDE><<EOF>> {
+ exit(yylerror(yyscanner, "unexpected end of file."));
}
<*>. {
stringstream msg;
- msg << "Unexpected character: \"";
- switch (yytext[0])
- {
- case '\r':
- msg << "\\r";
- break;
- case '\n':
- msg << "\\n";
- break;
- case '\t':
- msg << "\\t";
- break;
- case '\b':
- msg << "\\b";
- break;
- default:
- msg << yytext[0];
- break;
- }
+ char c = yytext[0];
+ msg << "unexpected character: \"";
+ msg << convert_special_char(c);
msg << "\"";
exit(yylerror(yyscanner, msg.str().c_str()));
}
diff --git a/src/parser/parser.y b/src/parser/parser.y
index 36be00f..855277e 100644
--- a/src/parser/parser.y
+++ b/src/parser/parser.y
@@ -10,6 +10,9 @@
//extern int yylineno;
//extern char *yytext;
+
+ string yyget_filename ( yyscan_t scanner );
+ string yyget_current_line ( yyscan_t scanner );
}
%{
@@ -954,8 +957,11 @@ int yyerror(yyscan_t scanner, ParseTree *pt, const char *err)
}
}
string token_escaped = ss.str();
- printf("-- Error in the netlist (line %u): %s\n", yyget_lineno(scanner), err);
- printf("-- \"%s\"\n", token_escaped.c_str());
- //cerr << err << endl;
+
+ cerr << "Parsing error (" << yyget_filename(scanner) << ":" << yyget_lineno(scanner) << "): " << err << endl;
+ cerr << "-- offending token: \"" << token_escaped.c_str() << "\"" << endl;
+ string str = yyget_current_line(scanner);
+ if (!str.empty())
+ cerr << "-- while parsing line: \"" << str << "\"" << endl;
exit(1);
}
diff --git a/src/parser/parser_state.h b/src/parser/parser_state.h
new file mode 100644
index 0000000..359d67f
--- /dev/null
+++ b/src/parser/parser_state.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <string>
+
+using std::string;
+
+struct ParserState {
+ string current_filename;
+ string current_line;
+};