From 3b3b77291a21ed23a2763c79335501beebb10746 Mon Sep 17 00:00:00 2001 From: Niels Moseley Date: Sun, 24 Mar 2019 22:54:18 +0100 Subject: Updated the liberty parser to accept [A:B] ranges (AST has not been updated). Liberty parser now also accepts key : value pair lines that do not end in ';'. --- passes/techmap/libparse.cc | 87 ++++++++++++++++++++++++++++++++++++++++++---- passes/techmap/libparse.h | 10 +++++- 2 files changed, 90 insertions(+), 7 deletions(-) (limited to 'passes') diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 3927a657b..878ca3160 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -24,6 +24,7 @@ #include #include #include +#include #ifndef FILTERLIB #include "kernel/log.h" @@ -86,15 +87,17 @@ int LibertyParser::lexer(std::string &str) { int c; + // eat whitespace do { c = f.get(); } while (c == ' ' || c == '\t' || c == '\r'); - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') { + // search for identifiers, numbers, plus or minus. + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') { str = c; while (1) { c = f.get(); - if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.' || c == '[' || c == ']') + if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') str += c; else break; @@ -111,6 +114,8 @@ int LibertyParser::lexer(std::string &str) } } + // if it wasn't an identifer, number of array range, + // maybe it's a string? if (c == '"') { str = ""; while (1) { @@ -125,9 +130,10 @@ int LibertyParser::lexer(std::string &str) return 'v'; } + // if it wasn't a string, perhaps it's a comment or a forward slash? if (c == '/') { c = f.get(); - if (c == '*') { + if (c == '*') { // start of '/*' block comment int last_c = 0; while (c > 0 && (last_c != '*' || c != '/')) { last_c = c; @@ -136,7 +142,7 @@ int LibertyParser::lexer(std::string &str) line++; } return lexer(str); - } else if (c == '/') { + } else if (c == '/') { // start of '//' line comment while (c > 0 && c != '\n') c = f.get(); line++; @@ -144,9 +150,10 @@ int LibertyParser::lexer(std::string &str) } f.unget(); // fprintf(stderr, "LEX: char >>/<<\n"); - return '/'; + return '/'; // a single '/' charater. } + // check for a backslash if (c == '\\') { c = f.get(); if (c == '\r') @@ -157,11 +164,15 @@ int LibertyParser::lexer(std::string &str) return '\\'; } + // check for a new line if (c == '\n') { line++; return 'n'; } + // anything else, such as ';' will get passed + // through as literal items. + // if (c >= 32 && c < 255) // fprintf(stderr, "LEX: char >>%c<<\n", c); // else @@ -210,7 +221,12 @@ LibertyAst *LibertyParser::parse() ast->value += str; tok = lexer(str); } - if (tok == ';') + + // In a liberty file, all key : value pairs should end in ';' + // However, there are some liberty files in the wild that + // just have a newline. We'll be kind and accept a newline + // instead of the ';' too.. + if ((tok == ';') || (tok == 'n')) break; else error(); @@ -225,6 +241,48 @@ LibertyAst *LibertyParser::parse() continue; if (tok == ')') break; + + // FIXME: the AST needs to be extended to store + // these vector ranges. + if (tok == '[') + { + // parse vector range [A] or [A:B] + std::string arg; + tok = lexer(arg); + if (tok != 'v') + { + // expected a vector array index + error("Expected a number."); + } + else + { + // fixme: check for number A + } + tok = lexer(arg); + // optionally check for : in case of [A:B] + // if it isn't we just expect ']' + // as we have [A] + if (tok == ':') + { + tok = lexer(arg); + if (tok != 'v') + { + // expected a vector array index + error("Expected a number."); + } + else + { + // fixme: check for number B + tok = lexer(arg); + } + } + // expect a closing bracket of array range + if (tok != ']') + { + error("Expected ']' on array range."); + } + continue; + } if (tok != 'v') error(); ast->args.push_back(arg); @@ -255,6 +313,14 @@ void LibertyParser::error() log_error("Syntax error in liberty file on line %d.\n", line); } +void LibertyParser::error(const std::string &str) +{ + std::stringstream ss; + ss << "Syntax error in liberty file on line " << line << ".\n"; + ss << " " << str << "\n"; + log_error("%s", ss.str().c_str()); +} + #else void LibertyParser::error() @@ -263,6 +329,15 @@ void LibertyParser::error() exit(1); } +void LibertyParser::error(const std::string &str) +{ + std::stringstream ss; + ss << "Syntax error in liberty file on line " << line << ".\n"; + ss << " " << str << "\n"; + printf("%s", ss.str().c_str()); + exit(1); +} + /**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/ #define CHECK_NV(result, check) \ diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index cf6325570..c9ebd06c5 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -46,9 +46,17 @@ namespace Yosys LibertyAst *ast; LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {} ~LibertyParser() { if (ast) delete ast; } + + /* lexer return values: + 'v': identifier, string, array range [...] -> str holds the token string + 'n': newline + anything else is a single character. + */ int lexer(std::string &str); - LibertyAst *parse(); + + LibertyAst *parse(); void error(); + void error(const std::string &str); }; } -- cgit v1.2.3 From 9d9cc8a3140cdbc2d976a5b06b5a057845da739a Mon Sep 17 00:00:00 2001 From: Niels Moseley Date: Mon, 25 Mar 2019 12:15:10 +0100 Subject: EOL is now accepted as ';' replacement on lines that look like: feature_xyz(option) --- passes/techmap/libparse.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'passes') diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 878ca3160..9dc3e96ab 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -202,12 +202,11 @@ LibertyAst *LibertyParser::parse() { tok = lexer(str); - if (tok == ';') + // allow both ';' and new lines to + // terminate a statement. + if ((tok == ';') || (tok == 'n')) break; - if (tok == 'n') - continue; - if (tok == ':' && ast->value.empty()) { tok = lexer(ast->value); if (tok != 'v') -- cgit v1.2.3 From 1f7f54e68eb201976ddd42cb906492bf9e611030 Mon Sep 17 00:00:00 2001 From: Niels Moseley Date: Mon, 25 Mar 2019 14:12:04 +0100 Subject: spaces -> tabs --- passes/techmap/libparse.cc | 156 ++++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 78 deletions(-) (limited to 'passes') diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 9dc3e96ab..8eadd8735 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -87,12 +87,12 @@ int LibertyParser::lexer(std::string &str) { int c; - // eat whitespace + // eat whitespace do { c = f.get(); } while (c == ' ' || c == '\t' || c == '\r'); - // search for identifiers, numbers, plus or minus. + // search for identifiers, numbers, plus or minus. if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') { str = c; while (1) { @@ -114,8 +114,8 @@ int LibertyParser::lexer(std::string &str) } } - // if it wasn't an identifer, number of array range, - // maybe it's a string? + // if it wasn't an identifer, number of array range, + // maybe it's a string? if (c == '"') { str = ""; while (1) { @@ -130,7 +130,7 @@ int LibertyParser::lexer(std::string &str) return 'v'; } - // if it wasn't a string, perhaps it's a comment or a forward slash? + // if it wasn't a string, perhaps it's a comment or a forward slash? if (c == '/') { c = f.get(); if (c == '*') { // start of '/*' block comment @@ -153,7 +153,7 @@ int LibertyParser::lexer(std::string &str) return '/'; // a single '/' charater. } - // check for a backslash + // check for a backslash if (c == '\\') { c = f.get(); if (c == '\r') @@ -164,14 +164,14 @@ int LibertyParser::lexer(std::string &str) return '\\'; } - // check for a new line + // check for a new line if (c == '\n') { line++; return 'n'; } - // anything else, such as ';' will get passed - // through as literal items. + // anything else, such as ';' will get passed + // through as literal items. // if (c >= 32 && c < 255) // fprintf(stderr, "LEX: char >>%c<<\n", c); @@ -202,8 +202,8 @@ LibertyAst *LibertyParser::parse() { tok = lexer(str); - // allow both ';' and new lines to - // terminate a statement. + // allow both ';' and new lines to + // terminate a statement. if ((tok == ';') || (tok == 'n')) break; @@ -220,11 +220,11 @@ LibertyAst *LibertyParser::parse() ast->value += str; tok = lexer(str); } - - // In a liberty file, all key : value pairs should end in ';' - // However, there are some liberty files in the wild that - // just have a newline. We'll be kind and accept a newline - // instead of the ';' too.. + + // In a liberty file, all key : value pairs should end in ';' + // However, there are some liberty files in the wild that + // just have a newline. We'll be kind and accept a newline + // instead of the ';' too.. if ((tok == ';') || (tok == 'n')) break; else @@ -240,48 +240,48 @@ LibertyAst *LibertyParser::parse() continue; if (tok == ')') break; - - // FIXME: the AST needs to be extended to store - // these vector ranges. - if (tok == '[') - { - // parse vector range [A] or [A:B] - std::string arg; - tok = lexer(arg); - if (tok != 'v') - { - // expected a vector array index - error("Expected a number."); - } - else - { - // fixme: check for number A - } - tok = lexer(arg); - // optionally check for : in case of [A:B] - // if it isn't we just expect ']' - // as we have [A] - if (tok == ':') - { - tok = lexer(arg); - if (tok != 'v') - { - // expected a vector array index - error("Expected a number."); - } - else - { - // fixme: check for number B - tok = lexer(arg); - } - } - // expect a closing bracket of array range - if (tok != ']') - { - error("Expected ']' on array range."); - } - continue; - } + + // FIXME: the AST needs to be extended to store + // these vector ranges. + if (tok == '[') + { + // parse vector range [A] or [A:B] + std::string arg; + tok = lexer(arg); + if (tok != 'v') + { + // expected a vector array index + error("Expected a number."); + } + else + { + // fixme: check for number A + } + tok = lexer(arg); + // optionally check for : in case of [A:B] + // if it isn't we just expect ']' + // as we have [A] + if (tok == ':') + { + tok = lexer(arg); + if (tok != 'v') + { + // expected a vector array index + error("Expected a number."); + } + else + { + // fixme: check for number B + tok = lexer(arg); + } + } + // expect a closing bracket of array range + if (tok != ']') + { + error("Expected ']' on array range."); + } + continue; + } if (tok != 'v') error(); ast->args.push_back(arg); @@ -314,10 +314,10 @@ void LibertyParser::error() void LibertyParser::error(const std::string &str) { - std::stringstream ss; - ss << "Syntax error in liberty file on line " << line << ".\n"; - ss << " " << str << "\n"; - log_error("%s", ss.str().c_str()); + std::stringstream ss; + ss << "Syntax error in liberty file on line " << line << ".\n"; + ss << " " << str << "\n"; + log_error("%s", ss.str().c_str()); } #else @@ -330,32 +330,32 @@ void LibertyParser::error() void LibertyParser::error(const std::string &str) { - std::stringstream ss; - ss << "Syntax error in liberty file on line " << line << ".\n"; - ss << " " << str << "\n"; - printf("%s", ss.str().c_str()); - exit(1); + std::stringstream ss; + ss << "Syntax error in liberty file on line " << line << ".\n"; + ss << " " << str << "\n"; + printf("%s", ss.str().c_str()); + exit(1); } /**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/ #define CHECK_NV(result, check) \ do { \ - auto _R = (result); \ - if (!(_R check)) { \ - fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \ - #result, (long int)_R, #check, __FILE__, __LINE__); \ - abort(); \ - } \ + auto _R = (result); \ + if (!(_R check)) { \ + fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \ + #result, (long int)_R, #check, __FILE__, __LINE__); \ + abort(); \ + } \ } while(0) #define CHECK_COND(result) \ do { \ - if (!(result)) { \ - fprintf(stderr, "Error from '%s' in %s:%d.\n", \ - #result, __FILE__, __LINE__); \ - abort(); \ - } \ + if (!(result)) { \ + fprintf(stderr, "Error from '%s' in %s:%d.\n", \ + #result, __FILE__, __LINE__); \ + abort(); \ + } \ } while(0) /**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/ -- cgit v1.2.3