add liberty parser; update db

This commit is contained in:
bunchgrape 2025-05-02 14:18:01 +08:00
parent 5a4e5cf8f2
commit 77e4a23383
235 changed files with 56902 additions and 10 deletions

View File

@ -3,6 +3,7 @@
#include "DatabaseClass.h"
#include "Geometry.h"
#include "Pin.h"
#include "common/lib/Liberty.h"
using namespace db;

View File

@ -4,6 +4,10 @@
#include <vector>
#include "Geometry.h"
namespace gt {
class LibertyCell;
}
namespace db {
using std::string;
@ -87,6 +91,8 @@ public:
bool operator==(const CellType& r) const;
bool operator!=(const CellType& r) const { return !(*this == r); }
gt::LibertyCell* liberty_cell = nullptr;
};
class Cell {
@ -116,6 +122,7 @@ public:
const std::string& name() const { return _name; }
Pin* pin(const std::string& name) const;
Pin* pin(unsigned i) const { return _pins[i]; }
std::vector<Pin*> pins() { return _pins; }
CellType* ctype() const { return _type; }
void ctype(CellType* t);
int lx() const;

View File

@ -15,6 +15,7 @@
#include "Site.h"
#include "SiteMap.h"
#include "Via.h"
#include "common/lib/Liberty.h"
using namespace db;
@ -63,21 +64,62 @@ void Database::load() {
if (setting.LefFile != "") {
setting.Format = "lefdef";
readLEF(setting.LefFile);
lef_read = true;
} else if ((setting.LefCell != "") && (setting.LefTech != "")) {
setting.Format = "lefdef";
readLEF(setting.LefTech);
readLEF(setting.LefCell);
lef_read = true;
} else if (setting.LefFiles.size() > 0) {
setting.Format = "lefdef";
for (auto lef : setting.LefFiles) {
readLEF(lef);
}
lef_read = true;
}
if (setting.CellLib != "") {
auto lib = std::make_shared<gt::CellLib>();
if (lef_read) {
lib->rawdb = this;
}
lib->read(setting.CellLib);
lib->finish_read();
cell_libs_[gt::MIN] = lib;
cell_libs_[gt::MAX] = cell_libs_[gt::MIN];
liberty_read = true;
} else if (setting.CellLib_MIN != "" && setting.CellLib_MAX != "") {
auto lib_min = std::make_shared<gt::CellLib>();
auto lib_max = std::make_shared<gt::CellLib>();
if (lef_read) {
lib_min->rawdb = this;
lib_max->rawdb = this;
}
lib_min->read(setting.CellLib_MIN);
lib_max->read(setting.CellLib_MAX);
lib_min->finish_read();
lib_max->finish_read();
cell_libs_[gt::MIN] = lib_min;
cell_libs_[gt::MAX] = lib_max;
liberty_read = true;
} else if (setting.LibFiles.size() > 0) {
auto lib = std::make_shared<gt::CellLib>();
if (lef_read) lib->rawdb = this;
for (auto libfile : setting.LibFiles) {
lib->read(libfile);
}
lib->finish_read();
cell_libs_[gt::MIN] = lib;
cell_libs_[gt::MAX] = cell_libs_[gt::MIN];
liberty_read = true;
}
if (setting.DefFile != "") {
setting.Format = "lefdef";
readDEF(setting.DefFile);
readDEFPG(setting.DefFile);
def_read = true;
}
if (setting.Size != "") {
@ -690,9 +732,11 @@ void Database::SetupRowSegments() {
}
void Database::setup() {
if (def_read) {
SetupLayers();
SetupCellLibrary();
SetupFloorplan();
}
SetupCellLibrary();
SetupRegions();
if (!setting.liteMode) {
SetupSiteMap();

View File

@ -2,6 +2,8 @@
#include "DatabaseClass.h"
#include "Setting.h"
#include "common/lib/Helper.h"
std::string validate_token(std::string& name);
namespace db {
@ -39,11 +41,17 @@ public:
robin_hood::unordered_map<string, IOPin*> name_iopins;
robin_hood::unordered_map<string, ViaType*> name_viatypes;
robin_hood::unordered_map<string, Layer*> name_layers;
bool lef_read = false;
bool def_read = false;
bool liberty_read = false;
bool verilog_read = false;
string module_name = "";
VerilogParser* verilog_parser = nullptr;
array<std::shared_ptr<gt::CellLib>, 2> cell_libs_;
vector<Layer> layers;
vector<Site*> lefsites;
vector<ViaType*> viatypes;

View File

@ -4,6 +4,7 @@
#include <set>
#include <string>
#include <vector>
#include <array>
#include "common/utils/utils.h"
@ -14,6 +15,7 @@ namespace db {
using std::string;
using std::vector;
using std::array;
class Database;
class Rectangle;
@ -44,3 +46,9 @@ class GCellGrid;
class BsRouteInfo;
class VerilogParser;
} // namespace db
namespace gt {
class CellLib;
class LibertyCell;
class LibertyPort;
}

View File

@ -11,7 +11,13 @@ void Setting::reset() {
LefCell = "";
LefTech = "";
LefFiles.clear();
LibFiles.clear();
Constraints = "";
CellLib = "";
CellLib_MIN = "";
CellLib_MAX = "";
Verilog = "";
OutputFile = "";

View File

@ -29,11 +29,16 @@ public:
std::string LefCell = "";
std::string LefTech = "";
std::vector<std::string> LefFiles;
std::vector<std::string> LibFiles;
std::string Constraints = "";
std::string Verilog = "";
std::string Size = "";
std::string CellLib = "";
std::string CellLib_MIN = "";
std::string CellLib_MAX = "";
std::string OutputFile = "";
void reset();

View File

@ -0,0 +1,61 @@
#pragma once
#include <map>
#include <string>
#include <string_view>
namespace gt {
using std::initializer_list;
using std::map;
using std::pair;
using std::string;
using std::string_view;
template <class ENUM>
class EnumNameMap {
public:
EnumNameMap(initializer_list<pair<const ENUM, string>> enum_names);
const string find(ENUM key) const;
ENUM find(string name, ENUM unknown_key) const;
void find(string name, ENUM &key, bool &exists) const;
private:
map<ENUM, string> enum_map_;
map<string, ENUM> name_map_;
};
template <class ENUM>
EnumNameMap<ENUM>::EnumNameMap(initializer_list<pair<const ENUM, string>> enum_names) : enum_map_(enum_names) {
for (const auto &[key, name] : enum_map_) name_map_[name] = key;
}
template <class ENUM>
const string EnumNameMap<ENUM>::find(ENUM key) const {
auto find_iter = enum_map_.find(key);
if (find_iter != enum_map_.end())
return find_iter->second;
else
return nullptr;
}
template <class ENUM>
void EnumNameMap<ENUM>::find(string name, ENUM &key, bool &exists) const {
auto find_iter = name_map_.find(name);
if (find_iter != name_map_.end()) {
key = find_iter->second;
exists = true;
} else
exists = false;
}
template <class ENUM>
ENUM EnumNameMap<ENUM>::find(string name, ENUM unknown_key) const {
auto find_iter = name_map_.find(name);
if (find_iter != name_map_.end())
return find_iter->second;
else
return unknown_key;
}
} // namespace gt

86
cpp_to_py/common/lib/Helper.h Executable file
View File

@ -0,0 +1,86 @@
#pragma once
#include <dirent.h>
#include <sys/wait.h>
#include <unistd.h>
#include <algorithm>
#include <atomic>
#include <cassert>
#include <chrono>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <forward_list>
#include <fstream>
#include <functional>
#include <future>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <ratio>
#include <regex>
#include <set>
#include <shared_mutex>
#include <sstream>
#include <stack>
#include <string_view>
#include <thread>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>
#if defined(__has_include) && __has_include(<filesystem>)
#include <filesystem>
#else
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
};
#endif
#include "common/common.h"
#include "units.hpp"
namespace gt {
using namespace std::chrono_literals;
using namespace std::literals::string_literals;
enum Split {
MIN = 0,
MAX = 1
};
enum Tran {
RISE = 0,
FALL = 1
};
constexpr int MAX_SPLIT = 2;
constexpr int MAX_TRAN = 2;
constexpr std::initializer_list<Split> SPLIT = {MIN, MAX};
constexpr std::initializer_list<Tran> TRAN = {RISE, FALL};
constexpr std::initializer_list<std::pair<Split, Tran>> SPLIT_TRAN = {{MIN, RISE}, {MIN, FALL}, {MAX, RISE}, {MAX, FALL}};
#define for_each_el(el) for (auto el : SPLIT)
#define for_each_el_rf_if(el, rf, c) \
for (auto [el, rf] : SPLIT_TRAN) \
if (c)
}; // namespace gt

View File

@ -0,0 +1,117 @@
#include "Liberty.h"
namespace gt {
void CellLib::uncomment(std::vector<char>& buffer) {
auto fsize = buffer.size() > 0 ? buffer.size() - 1 : 0;
for (size_t i = 0; i < fsize; ++i) {
// Block comment
if (buffer[i] == '/' && buffer[i + 1] == '*') {
buffer[i] = buffer[i + 1] = ' ';
for (i = i + 2; i < fsize; buffer[i++] = ' ') {
if (buffer[i] == '*' && buffer[i + 1] == '/') {
buffer[i] = buffer[i + 1] = ' ';
i = i + 1;
break;
}
}
}
// Line comment
if (buffer[i] == '/' && buffer[i + 1] == '/') {
buffer[i] = buffer[i + 1] = ' ';
for (i = i + 2; i < fsize; ++i) {
if (buffer[i] == '\n' || buffer[i] == '\r') {
break;
} else
buffer[i] = ' ';
}
}
// Pond comment
if (buffer[i] == '#') {
buffer[i] = ' ';
for (i = i + 1; i < fsize; ++i) {
if (buffer[i] == '\n' || buffer[i] == '\r') {
break;
} else
buffer[i] = ' ';
}
}
}
}
void CellLib::tokenize(const std::vector<char>& buf, std::vector<std::string_view>& tokens) {
static std::string_view dels = "(),:;/#[]{}*\"\\";
const char* beg = buf.data();
const char* end = buf.data() + buf.size();
const char* token{nullptr};
size_t len{0};
tokens.clear();
for (const char* itr = beg; itr != end && *itr != 0; ++itr) {
if (std::isspace(*itr) || (dels.find(*itr) != std::string_view::npos)) {
if (len > 0) { // Add the current token.
tokens.push_back({token, len});
token = nullptr;
len = 0;
}
if (*itr == '(' || *itr == ')' || *itr == '{' || *itr == '}') {
tokens.push_back({itr, 1});
}
} else {
if (len == 0) {
token = itr;
}
++len;
}
}
if (len > 0) {
tokens.push_back({token, len});
}
}
LibertyCell* CellLib::get_cell(const std::string& name) {
if (auto itr = lib_cells_.find(name); itr == lib_cells_.end()) {
return nullptr;
} else {
return itr->second;
}
}
int LibertyCell::get_port(const std::string& name) {
if (auto itr = ports_map_.find(name); itr == ports_map_.end()) {
return -1;
} else {
return itr->second;
}
}
EnumNameMap<DelayModel> delay_model_name_map = {{DelayModel::generic_cmos, "generic_cmos"},
{DelayModel::table_lookup, "table_lookup"},
{DelayModel::cmos2, "cmos2"},
{DelayModel::piecewise_cmos, "piecewise_cmos"},
{DelayModel::dcm, "dcm"},
{DelayModel::polynomial, "polynomial"},
{DelayModel::unknown, "unknown"}};
DelayModel findDelayModel(const std::string model_name) {
return delay_model_name_map.find(model_name, DelayModel::unknown);
}
EnumNameMap<CellPortDirection> port_direction_name_map = {{CellPortDirection::input, "input"},
{CellPortDirection::output, "output"},
{CellPortDirection::inout, "inout"},
{CellPortDirection::internal, "internal"},
{CellPortDirection::unknown, "unknown"}};
CellPortDirection findPortDirection(const std::string dir_name) {
return port_direction_name_map.find(dir_name, CellPortDirection::unknown);
}
} // namespace gt

View File

@ -0,0 +1,155 @@
#pragma once
#include <optional>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
#include "EnumNameMap.h"
#include "Helper.h"
#include "tokenizer.h"
#include "unit.h"
using std::optional;
using std::string;
using std::unordered_map;
using std::variant;
using std::vector;
namespace db {
class Database;
class CellType;
}; // namespace db
namespace gt {
class CellLib;
class LibertyCell;
class LibertyPort;
class TimingArc;
struct LutTemplate;
class Lut;
enum class DelayModel { generic_cmos, table_lookup, cmos2, piecewise_cmos, dcm, polynomial, unknown };
enum class CellPortDirection { input, output, inout, internal, unknown };
DelayModel findDelayModel(const std::string model_name);
CellPortDirection findPortDirection(const std::string dir_name);
class CellLib {
public:
~CellLib() { logger.info("Destruct celllib"); }
CellLib() = default;
CellLib(db::Database *rawdb_) : rawdb(rawdb_) {}
db::Database *rawdb = nullptr;
db::CellType *cell_type_ = nullptr;
using token_iterator = std::vector<std::string_view>::iterator;
DelayModel delay_model;
string name;
optional<second_t> time_unit_;
optional<watt_t> power_unit_;
optional<ohm_t> resistance_unit_;
optional<farad_t> capacitance_unit_;
optional<ampere_t> current_unit_;
optional<volt_t> voltage_unit_;
unordered_map<string, optional<float>> default_values = {
{"default_cell_leakage_power", optional<float>{}},
{"default_inout_pin_cap", optional<float>{}},
{"default_input_pin_cap", optional<float>{}},
{"default_output_pin_cap", optional<float>{}},
{"default_fanout_load", optional<float>{}},
{"default_max_fanout", optional<float>{}},
{"default_max_transition", optional<float>{}},
{"voltage", optional<float>{}},
};
unordered_map<string, float> scale_factors = {
{"time", 1.0},
{"resistance", 1.0},
{"power", 1.0},
{"capacitance", 1.0},
{"current", 1.0},
{"voltage", 1.0},
};
unordered_map<string, LutTemplate *> lut_templates_;
unordered_map<string, LibertyCell *> lib_cells_;
LutTemplate *get_lut_template(const string &);
LibertyCell *get_cell(const std::string &name);
void read(const string &file);
void finish_read();
void finish_port_read(LibertyPort *liberty_port);
public:
LibertyCell *extractLibertyCell(token_iterator &, const token_iterator);
LibertyPort *extractLibertyPort(token_iterator &, const token_iterator, LibertyCell *);
TimingArc *extractTimingArc(token_iterator &, const token_iterator, LibertyPort *);
std::optional<float> extract_operating_conditions(token_iterator &itr, const token_iterator end);
LutTemplate *extract_lut_template(token_iterator &, const token_iterator);
Lut *extract_lut(token_iterator &, const token_iterator);
void apply_default_values();
void uncomment(std::vector<char> &);
void tokenize(const std::vector<char> &, std::vector<std::string_view> &);
};
class LibertyCell {
public:
LibertyCell() = default;
string name;
db:: CellType *cell_type_ = nullptr;
vector<LibertyPort *> ports_;
// map<string, LibertyPort *> ports_map_;
map<string, int> ports_map_;
vector<float> leakage_powers_;
optional<float> leakage_power_;
optional<float> area_;
bool is_seq_ = false;
int num_bits_ = 0;
public:
int get_port(const std::string &name);
};
class LibertyPort {
public:
LibertyPort() = default;
public:
string name;
LibertyCell *cell_;
CellPortDirection direction_;
optional<float> port_capacitance_[3];
bool is_clock_ = false;
bool is_bundle_ = false;
vector<LibertyPort *> member_ports_;
vector<TimingArc *> timing_arcs_;
map<string, TimingArc *> timing_arcs_map_;
vector<TimingArc *> timing_arcs_non_cond_non_bundle_;
// optional<float> capacitance;
// optional<float> fall_capacitance;
// optional<float> rise_capacitance;
optional<float> fanout_load;
optional<float> max_fanout;
optional<float> min_fanout;
optional<float> max_capacitance;
optional<float> min_capacitance;
optional<float> max_transition;
optional<float> min_transition;
};
}; // namespace gt

View File

@ -0,0 +1,561 @@
#include <zlib.h>
#include <iostream>
#include "Liberty.h"
#include "Timing.h"
#include "common/db/Cell.h"
#include "common/db/Database.h"
#include "Lut.h"
using std::ifstream;
namespace gt {
LutTemplate* CellLib::get_lut_template(const std::string& name) {
if (auto itr = lut_templates_.find(name); itr == lut_templates_.end()) {
return nullptr;
} else {
return itr->second;
}
}
std::optional<float> CellLib::extract_operating_conditions(token_iterator& itr, const token_iterator end) {
std::optional<float> voltage;
std::string operating_condition_name;
if (itr = on_next_parentheses(itr, end, [&](auto& name) mutable { operating_condition_name = name; }); itr == end) {
logger.info("can't find lut template name");
}
// Extract the lut template group
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("can't find lut template group brace '{'");
}
int stack = 1;
while (stack && ++itr != end) {
// variable 1
if (*itr == "voltage") { // Read the variable.
if (++itr == end) {
logger.info("volate error in operating_conditions template %s", operating_condition_name);
}
voltage = std::strtof(std::string(*itr).c_str(), nullptr);
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
if (stack != 0 || *itr != "}") {
logger.info("can't find operating_conditions template group brace '}'");
}
return voltage;
}
LutTemplate* CellLib::extract_lut_template(token_iterator& itr, const token_iterator end) {
LutTemplate* lt = new LutTemplate();
if (itr = on_next_parentheses(itr, end, [&](auto& name) mutable { lt->name = name; }); itr == end) {
logger.info("can't find lut template name");
}
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("can't find lut template group brace '{'");
}
int stack = 1;
while (stack && ++itr != end) {
if (*itr == "variable_1") {
if (++itr == end) {
logger.info("variable_1 error in lut template %s", lt->name.c_str());
}
if (auto vitr = lut_vars.find(*itr); vitr != lut_vars.end()) {
lt->variable1 = vitr->second;
} else {
logger.warning(
"unexpected lut template variable %.*s", static_cast<int>((*itr).length()), (*itr).data());
}
} else if (*itr == "variable_2") {
if (++itr == end) {
logger.info("variable_2 error in lut template %s", lt->name.c_str());
}
if (auto vitr = lut_vars.find(*itr); vitr != lut_vars.end()) {
lt->variable2 = vitr->second;
} else {
logger.warning(
"unexpected lut template variable %.*s", static_cast<int>((*itr).length()), (*itr).data());
}
} else if (*itr == "index_1") {
itr = on_next_parentheses(
itr, end, [&](auto& str) { lt->indices1.push_back(std::strtof(str.data(), nullptr)); });
} else if (*itr == "index_2") {
itr = on_next_parentheses(
itr, end, [&](auto& str) { lt->indices2.push_back(std::strtof(str.data(), nullptr)); });
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
if (stack != 0 || *itr != "}") {
logger.info("can't find lut template brace '}'");
}
lut_templates_[lt->name] = lt;
return lt;
}
Lut* CellLib::extract_lut(token_iterator& itr, const token_iterator end) {
Lut* lut = new Lut();
if (itr = on_next_parentheses(itr, end, [&](auto& name) mutable { lut->name = name; }); itr == end) {
logger.info("can't find lut template name");
}
lut->lut_template = get_lut_template(lut->name);
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("group brace '{' error in lut ", lut->name);
}
int stack = 1;
size_t size1 = 1;
size_t size2 = 1;
while (stack && ++itr != end) {
if (*itr == "index_1") {
itr = on_next_parentheses(
itr, end, [&](auto& v) mutable { lut->indices1.push_back(std::strtof(v.data(), nullptr)); });
if (lut->indices1.size() == 0) {
logger.info("syntax error in %s index_1", lut->name);
}
size1 = lut->indices1.size();
} else if (*itr == "index_2") {
itr = on_next_parentheses(
itr, end, [&](auto& v) mutable { lut->indices2.push_back(std::strtof(v.data(), nullptr)); });
if (lut->indices2.size() == 0) {
logger.info("syntax error in %s index_2", lut->name);
}
size2 = lut->indices2.size();
} else if (*itr == "values") {
if (lut->indices1.empty()) {
if (size1 != 1) {
logger.info("empty indices1 in non-scalar lut %s", lut->name);
}
lut->indices1.resize(size1);
}
if (lut->indices2.empty()) {
if (size2 != 1) {
logger.info("empty indices2 in non-scalar lut %s", lut->name);
}
lut->indices2.resize(size2);
}
lut->table.resize(size1 * size2);
int id{0};
itr = on_next_parentheses(
itr, end, [&](auto& v) mutable { lut->table[id++] = std::strtof(v.data(), nullptr); });
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
lut->set_ = true;
if (stack != 0 || *itr != "}") {
logger.info("can't find group brace '}' in lut ");
}
return lut;
}
TimingArc* CellLib::extractTimingArc(token_iterator& itr, const token_iterator end, LibertyPort* cell_port) {
TimingArc* timing_arc = new TimingArc();
timing_arc->liberty_port_ = cell_port;
cell_port->timing_arcs_.push_back(timing_arc);
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("can't find group brace '{' in timing");
}
int stack = 1;
while (stack && ++itr != end) {
if (*itr == "cell_fall") {
timing_arc->cell_delay_[1] = extract_lut(itr, end);
} else if (*itr == "cell_rise") {
timing_arc->cell_delay_[0] = extract_lut(itr, end);
} else if (*itr == "fall_transition") {
timing_arc->transition_[1] = extract_lut(itr, end);
} else if (*itr == "rise_transition") {
timing_arc->transition_[0] = extract_lut(itr, end);
} else if (*itr == "fall_constraint") {
timing_arc->constraint_[1] = extract_lut(itr, end);
} else if (*itr == "rise_constraint") {
timing_arc->constraint_[0] = extract_lut(itr, end);
} else if (*itr == "timing_sense") {
logger.infoif(++itr == end, "can't get the timing_sense in cellpin ");
timing_arc->timing_sense_ = findTimingSense(string(*itr));
} else if (*itr == "timing_type") {
logger.infoif(++itr == end, "can't get the timing_type in cellpin ");
timing_arc->timing_type_ = findTimingType(string(*itr));
} else if (*itr == "sdf_cond") {
logger.infoif(++itr == end, "can't get the sdf_cond in cellpin ");
timing_arc->sdf_cond_ = *itr;
timing_arc->is_cond_ = true;
} else if (*itr == "related_pin") {
logger.infoif(++itr == end, "can't get the related port ");
timing_arc->related_port_name_ = *itr;
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
if (stack != 0 || *itr != "}") {
logger.info("can't find group brace '}' in cell timing ");
}
return timing_arc;
}
LibertyPort* CellLib::extractLibertyPort(token_iterator& itr, const token_iterator end, LibertyCell* liberty_cell) {
LibertyPort* cell_port = new LibertyPort();
cell_port->cell_ = liberty_cell;
on_next_parentheses(itr, end, [&](auto& name) mutable { cell_port->name = name; });
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("can't find group brace '{' in port");
}
int stack = 1;
while (stack && ++itr != end) {
if (*itr == "direction") {
logger.infoif(++itr == end, "can't get direction in cell ", cell_port->name);
cell_port->direction_ = findPortDirection(string(*itr));
} else if (*itr == "capacitance") {
logger.infoif(++itr == end, "can't get the capacitance in cellpin");
cell_port->port_capacitance_[2] = std::strtof(itr->data(), nullptr);
} else if (*itr == "fall_capacitance") {
logger.infoif(++itr == end, "can't get fall_capacitance in cellpin");
cell_port->port_capacitance_[1] = std::strtof(itr->data(), nullptr);
} else if (*itr == "rise_capacitance") {
logger.infoif(++itr == end, "can't get rise_capacitance in cellpin");
cell_port->port_capacitance_[0] = std::strtof(itr->data(), nullptr);
} else if (*itr == "max_capacitance") {
logger.infoif(++itr == end, "can't get the max_capacitance in cellpin");
cell_port->max_capacitance = std::strtof(itr->data(), nullptr);
} else if (*itr == "min_capacitance") {
logger.infoif(++itr == end, "can't get the min_capacitance in cellpin");
cell_port->min_capacitance = std::strtof(itr->data(), nullptr);
} else if (*itr == "max_transition") {
logger.infoif(++itr == end, "can't get the max_transition in cellpin");
cell_port->max_transition = std::strtof(itr->data(), nullptr);
} else if (*itr == "min_transition") {
logger.infoif(++itr == end, "can't get the min_transition in cellpin");
cell_port->min_transition = std::strtof(itr->data(), nullptr);
} else if (*itr == "fanout_load") {
logger.infoif(++itr == end, "can't get fanout_load in cellpin");
cell_port->fanout_load = std::strtof(itr->data(), nullptr);
} else if (*itr == "max_fanout") {
logger.infoif(++itr == end, "can't get max_fanout in cellpin");
cell_port->max_fanout = std::strtof(itr->data(), nullptr);
} else if (*itr == "min_fanout") {
logger.infoif(++itr == end, "can't get min_fanout in cellpin");
cell_port->min_fanout = std::strtof(itr->data(), nullptr);
} else if (*itr == "clock") {
logger.infoif(++itr == end, "can't get the clock status in cellpin");
cell_port->is_clock_ = (*itr == "true") ? true : false;
} else if (*itr == "timing") {
TimingArc* timing_arc_ = extractTimingArc(itr, end, cell_port);
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
if (stack != 0 || *itr != "}") {
logger.info("can't find group brace '}' in cell port");
}
return cell_port;
}
LibertyCell* CellLib::extractLibertyCell(token_iterator& itr, const token_iterator end) {
LibertyCell* liberty_cell = new LibertyCell();
on_next_parentheses(itr, end, [&](auto& name) mutable { liberty_cell->name = name; });
if (itr = std::find(itr, end, "{"); itr == end) {
logger.info("can't find group brace '{' in cell %s", liberty_cell->name);
}
int stack = 1;
int stage = -1;
while (stack && ++itr != end) {
if (*itr == "cell_leakage_power") {
logger.infoif(++itr == end, "can't get the cell_leakage_power ");
liberty_cell->leakage_power_ = scale_factors["power"] * std::strtof(itr->data(), nullptr);
}
if (*itr == "leakage_power") {
itr = std::find(itr, end, "{");
int stack_1 = 1;
while (stack_1 && ++itr != end) {
if (*itr == "value") {
logger.infoif(++itr == end, "can't get value in cell %s", liberty_cell->name);
liberty_cell->leakage_powers_.push_back(std::strtof(itr->data(), nullptr));
} else if (*itr == "}")
stack_1--;
else if (*itr == "{")
stack_1++;
}
} else if (*itr == "area") {
logger.infoif(++itr == end, "can't get area in cell %s", liberty_cell->name);
liberty_cell->area_ = std::strtof(itr->data(), nullptr);
} else if (*itr == "pin") {
logger.infoif(++itr == end, "can't get port in cell %s", liberty_cell->name);
LibertyPort* cell_port_ = extractLibertyPort(itr, end, liberty_cell);
liberty_cell->ports_.push_back(cell_port_);
} else if (*itr == "bundle") {
LibertyPort* cell_port_bundle = new LibertyPort();
liberty_cell->ports_.push_back(cell_port_bundle);
cell_port_bundle->cell_ = liberty_cell;
cell_port_bundle->is_bundle_ = true;
on_next_parentheses(itr, end, [&](auto& name) mutable { cell_port_bundle->name = name; });
itr = std::find(itr, end, "{");
int stack_1 = 1;
while (stack_1 && ++itr != end) {
if (*itr == "direction") {
logger.infoif(++itr == end, "can't get direction in cell %s", liberty_cell->name);
cell_port_bundle->direction_ = findPortDirection(string(*itr));
} else if (*itr == "pin") {
LibertyPort* cell_port_ = extractLibertyPort(itr, end, liberty_cell);
cell_port_bundle->member_ports_.push_back(cell_port_);
} else if (*itr == "}")
stack_1--;
else if (*itr == "{")
stack_1++;
}
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
if (stack != 0 || *itr != "}") {
logger.info("can't find group brace '}' in cellpin ");
}
return liberty_cell;
}
void CellLib::read(const std::string& file) {
// process .gz file with zlib
std::vector<char> buffer;
if (file.substr(file.find_last_of(".") + 1) == "gz") {
logger.info("reading gzip celllib %s ...", file.c_str());
gzFile fs = gzopen(file.c_str(), "rb");
if (!fs) {
logger.error("cannot open verilog file: %s", file.c_str());
}
char buf[1024];
int len = 0;
while ((len = gzread(fs, buf, 1024)) > 0) {
buffer.insert(buffer.end(), buf, buf + len);
}
gzclose(fs);
buffer.push_back(0);
} else {
ifstream fs(file.c_str(), std::ios::ate);
if (!fs.good()) {
logger.error("cannot open liberty file: %s", file.c_str());
}
logger.info("reading celllib %s ...", file.c_str());
size_t fsize = fs.tellg();
fs.seekg(0, std::ios::beg);
buffer.resize(fsize + 1);
fs.read(buffer.data(), fsize);
buffer[fsize] = 0;
}
// get tokens
std::vector<std::string_view> tokens;
tokens.reserve(buffer.size() / sizeof(std::string));
uncomment(buffer);
tokenize(buffer, tokens);
// Set up the iterator
auto itr = tokens.begin();
auto end = tokens.end();
// Read the library name.
if (itr = std::find(itr, end, "library"); itr == end) {
logger.error("can't find keyword %s", "library");
}
if (itr = on_next_parentheses(itr, end, [&](auto& str) mutable { name = str; }); itr == end) {
logger.info("can't find library name");
}
if (itr = std::find(itr, tokens.end(), "{"); itr == tokens.end()) {
logger.info("can't find library group symbol '{'");
}
int stack = 1;
while (stack && ++itr != end) {
if (*itr == "lu_table_template") {
auto lut = extract_lut_template(itr, end);
} else if (*itr == "power_lut_template") {
auto lut = extract_lut_template(itr, end);
} else if (*itr == "delay_model") {
logger.infoif(++itr == end, "syntax error in delay_model");
delay_model = findDelayModel(string(*itr));
} else if (*itr == "default_cell_leakage_power" || *itr == "default_inout_pin_cap" ||
*itr == "default_input_pin_cap" || *itr == "default_output_pin_cap" ||
*itr == "default_fanout_load" || *itr == "default_max_fanout" || *itr == "default_max_transition") {
logger.infoif(++itr == end, "syntax error");
default_values[std::string(*itr)] = std::strtof(itr->data(), nullptr);
} else if (*itr == "operating_conditions") {
logger.infoif(++itr == end, "syntax error");
default_values["voltage"] = extract_operating_conditions(itr, end);
} else if (*itr == "time_unit") {
logger.infoif(++itr == end, "syntax error");
time_unit_ = make_time_unit(*itr);
} else if (*itr == "voltage_unit") {
logger.infoif(++itr == end, "syntax error");
voltage_unit_ = make_voltage_unit(*itr);
} else if (*itr == "current_unit") {
logger.infoif(++itr == end, "syntax error");
current_unit_ = make_current_unit(*itr);
} else if (*itr == "pulling_resistance_unit") {
logger.infoif(++itr == end, "syntax error");
resistance_unit_ = make_resistance_unit(*itr);
} else if (*itr == "capacitive_load_unit") {
string unit;
on_next_parentheses(itr, end, [&](auto& str) mutable { unit += str; });
capacitance_unit_ = make_capacitance_unit(unit);
} else if (*itr == "leakage_power_unit") {
logger.infoif(++itr == end, "syntax error");
auto current_power_unit_ = make_power_unit(*itr);
if (!power_unit_) power_unit_ = current_power_unit_;
scale_factors["power"] = *current_power_unit_ / *power_unit_;
} else if (*itr == "cell") {
LibertyCell* libterty_cell = extractLibertyCell(itr, end);
lib_cells_[libterty_cell->name] = libterty_cell;
} else if (*itr == "}") {
stack--;
} else if (*itr == "{") {
stack++;
} else {
// undefined token TODO:
}
}
}
void CellLib::finish_port_read(LibertyPort* liberty_port) {
for (TimingArc* timing_arc : liberty_port->timing_arcs_) {
if (timing_arc->related_port_name_.empty()) {
logger.warning("timing arc %s.%s.%s has no related pin",
liberty_port->cell_->name.c_str(),
liberty_port->name.c_str(),
timing_arc->timing_type_);
continue;
}
if (auto related_port = liberty_port->cell_->get_port(timing_arc->related_port_name_);
related_port == -1) {
logger.warning("timing arc %s.%s.%s has no related pin",
liberty_port->cell_->name.c_str(),
liberty_port->name.c_str(),
timing_arc->timing_type_);
} else {
timing_arc->from_port_ = liberty_port->cell_->ports_[related_port];;
}
timing_arc->to_port_ = timing_arc->liberty_port_;
}
for (TimingArc* timing_arc : liberty_port->timing_arcs_) {
timing_arc->encode_str_ = timing_arc->encode_arc();
if (liberty_port->timing_arcs_map_.find(timing_arc->encode_str_) != liberty_port->timing_arcs_map_.end()) {
TimingArc* old_timing_arc = liberty_port->timing_arcs_map_[timing_arc->encode_str_];
if (!timing_arc->is_cond_) {
liberty_port->timing_arcs_map_[timing_arc->encode_str_] = timing_arc;
}
} else
liberty_port->timing_arcs_map_[timing_arc->encode_str_] = timing_arc;
}
}
void CellLib::finish_read() {
for (auto [name, liberty_cell] : lib_cells_) {
db::CellType* lef_cell_type = rawdb->getCellType(name);
if (lef_cell_type == nullptr) {
logger.warning("cell %s not found in lef", name.c_str());
continue;
} else {
lef_cell_type->liberty_cell = liberty_cell;
liberty_cell->cell_type_ = lef_cell_type;
}
// sort port by name
std::sort(liberty_cell->ports_.begin(),
liberty_cell->ports_.end(),
[](const LibertyPort* a, const LibertyPort* b) { return a->name < b->name; });
for (int i = 0; i < liberty_cell->ports_.size(); i++) {
liberty_cell->ports_map_[liberty_cell->ports_[i]->name] = i;
}
for (auto port : liberty_cell->ports_) {
if (port->is_clock_) liberty_cell->is_seq_ = true;
if (port->is_bundle_) {
for (auto member_port : port->member_ports_) {
finish_port_read(member_port);
}
} else
finish_port_read(port);
}
for (auto port : liberty_cell->ports_) {
LibertyPort* non_bundle_port;
if (port->is_bundle_) {
non_bundle_port = port->member_ports_[0];
} else
non_bundle_port = port;
for (auto kvp : non_bundle_port->timing_arcs_map_) {
// string encode_str = kvp.first;
// std::cout << encode_str << std::endl;
TimingArc* timing_arc = kvp.second;
port->timing_arcs_non_cond_non_bundle_.push_back(timing_arc);
}
}
}
}
}; // namespace gt

32
cpp_to_py/common/lib/Lut.cpp Executable file
View File

@ -0,0 +1,32 @@
#include "Lut.h"
namespace gt {
bool is_time_lut_var(LutVar v) {
switch (v) {
case LutVar::INPUT_NET_TRANSITION:
case LutVar::CONSTRAINED_PIN_TRANSITION:
case LutVar::RELATED_PIN_TRANSITION:
case LutVar::INPUT_TRANSITION_TIME:
return true;
break;
default:
return false;
break;
}
}
bool is_capacitance_lut_var(LutVar v) {
switch (v) {
case LutVar::TOTAL_OUTPUT_NET_CAPACITANCE:
return true;
break;
default:
return false;
break;
}
}
}; // namespace gt

56
cpp_to_py/common/lib/Lut.h Executable file
View File

@ -0,0 +1,56 @@
#pragma once
#include "common/common.h"
#include "common/lib/Helper.h"
namespace gt {
enum class LutVar {
TOTAL_OUTPUT_NET_CAPACITANCE = 0,
INPUT_NET_TRANSITION = 1,
CONSTRAINED_PIN_TRANSITION = 2,
RELATED_PIN_TRANSITION = 3,
INPUT_TRANSITION_TIME = 4,
};
inline const std::unordered_map<std::string_view, LutVar> lut_vars{
{"total_output_net_capacitance", LutVar::TOTAL_OUTPUT_NET_CAPACITANCE},
{"input_net_transition", LutVar::INPUT_NET_TRANSITION},
{"constrained_pin_transition", LutVar::CONSTRAINED_PIN_TRANSITION},
{"related_pin_transition", LutVar::RELATED_PIN_TRANSITION},
{"input_transition_timing", LutVar::INPUT_TRANSITION_TIME},
{"input_transition_time", LutVar::INPUT_TRANSITION_TIME}};
bool is_time_lut_var(LutVar);
bool is_capacitance_lut_var(LutVar);
struct LutTemplate {
LutTemplate() = default;
std::string name;
std::optional<LutVar> variable1;
std::optional<LutVar> variable2;
std::vector<float> indices1;
std::vector<float> indices2;
int id = -1;
};
class Lut {
public:
Lut() = default;
std::string name;
std::vector<float> indices1;
std::vector<float> indices2;
std::vector<float> table;
const LutTemplate* lut_template{nullptr};
bool set_ = false;
};
}; // namespace gt

164
cpp_to_py/common/lib/Timing.cpp Executable file
View File

@ -0,0 +1,164 @@
#include "Timing.h"
#include "Lut.h"
#include "Liberty.h"
namespace gt {
TimingArc::TimingArc() {
for (int i = 0; i < MAX_TRAN; i++) {
cell_delay_[i] = new Lut();
transition_[i] = new Lut();
constraint_[i] = new Lut();
}
}
bool TimingArc::is_constraint() const {
switch (timing_type_) {
case TimingType::removal_rising:
case TimingType::removal_falling:
case TimingType::recovery_rising:
case TimingType::recovery_falling:
case TimingType::setup_rising:
case TimingType::setup_falling:
case TimingType::hold_rising:
case TimingType::hold_falling:
case TimingType::non_seq_setup_rising:
case TimingType::non_seq_setup_falling:
case TimingType::non_seq_hold_rising:
case TimingType::non_seq_hold_falling:
return true;
break;
default:
return false;
break;
}
}
bool TimingArc::is_min_constraint() const {
switch (timing_type_) {
case TimingType::hold_rising:
case TimingType::hold_falling:
case TimingType::non_seq_hold_rising:
case TimingType::non_seq_hold_falling:
case TimingType::removal_rising:
case TimingType::removal_falling:
return true;
break;
default:
return false;
break;
}
}
bool TimingArc::is_max_constraint() const {
switch (timing_type_) {
case TimingType::setup_rising:
case TimingType::setup_falling:
case TimingType::non_seq_setup_rising:
case TimingType::non_seq_setup_falling:
case TimingType::recovery_rising:
case TimingType::recovery_falling:
return true;
break;
default:
return false;
break;
}
}
bool TimingArc::is_falling_edge_triggered() const {
switch (timing_type_) {
case TimingType::setup_falling:
case TimingType::hold_falling:
case TimingType::removal_falling:
case TimingType::recovery_falling:
case TimingType::falling_edge:
return true;
break;
default:
return false;
break;
};
}
bool TimingArc::is_rising_edge_triggered() const {
switch (timing_type_) {
case TimingType::setup_rising:
case TimingType::hold_rising:
case TimingType::removal_rising:
case TimingType::recovery_rising:
case TimingType::rising_edge:
return true;
break;
default:
return false;
break;
};
}
// encode TimingType TimingSense from_port_name to_port_name to remove duplicate
string TimingArc::encode_arc() {
int max_type_shift = std::ceil(std::log2(static_cast<int>(TimingType::unknown)));
int encode = (static_cast<int>(timing_sense_) << max_type_shift) | static_cast<int>(timing_type_);
string encode_str = std::to_string(encode);
encode_str += "_" + from_port_->name + "_" + to_port_->name;
return encode_str;
}
EnumNameMap<TimingSense> timing_sense_name_map = {{TimingSense::non_unate, "non_unate"},
{TimingSense::positive_unate, "positive_unate"},
{TimingSense::negative_unate, "negative_unate"},
{TimingSense::unknown, "unknown"}};
TimingSense findTimingSense(const std::string sense_name) {
return timing_sense_name_map.find(sense_name, TimingSense::unknown);
}
EnumNameMap<TimingType> timing_type_name_map = {{TimingType::clear, "clear"},
{TimingType::combinational, "combinational"},
{TimingType::combinational_fall, "combinational_fall"},
{TimingType::combinational_rise, "combinational_rise"},
{TimingType::falling_edge, "falling_edge"},
{TimingType::hold_falling, "hold_falling"},
{TimingType::hold_rising, "hold_rising"},
{TimingType::min_pulse_width, "min_pulse_width"},
{TimingType::minimum_period, "minimum_period"},
{TimingType::nochange_high_high, "nochange_high_high"},
{TimingType::nochange_high_low, "nochange_high_low"},
{TimingType::nochange_low_high, "nochange_low_high"},
{TimingType::nochange_low_low, "nochange_low_low"},
{TimingType::non_seq_hold_falling, "non_seq_hold_falling"},
{TimingType::non_seq_hold_rising, "non_seq_hold_rising"},
{TimingType::non_seq_setup_falling, "non_seq_setup_falling"},
{TimingType::non_seq_setup_rising, "non_seq_setup_rising"},
{TimingType::preset, "preset"},
{TimingType::recovery_falling, "recovery_falling"},
{TimingType::recovery_rising, "recovery_rising"},
{TimingType::removal_falling, "removal_falling"},
{TimingType::removal_rising, "removal_rising"},
{TimingType::retaining_time, "retaining_time"},
{TimingType::rising_edge, "rising_edge"},
{TimingType::setup_falling, "setup_falling"},
{TimingType::setup_rising, "setup_rising"},
{TimingType::skew_falling, "skew_falling"},
{TimingType::skew_rising, "skew_rising"},
{TimingType::three_state_disable, "three_state_disable"},
{TimingType::three_state_disable_fall, "three_state_disable_fall"},
{TimingType::three_state_disable_rise, "three_state_disable_rise"},
{TimingType::three_state_enable, "three_state_enable"},
{TimingType::three_state_enable_fall, "three_state_enable_fall"},
{TimingType::three_state_enable_rise, "three_state_enable_rise"},
{TimingType::min_clock_tree_path, "min_clock_tree_path"},
{TimingType::max_clock_tree_path, "max_clock_tree_path"},
{TimingType::unknown, "unknown"}};
TimingType findTimingType(const std::string type_name) {
return timing_type_name_map.find(type_name, TimingType::unknown);
}
}; // namespace gt

95
cpp_to_py/common/lib/Timing.h Executable file
View File

@ -0,0 +1,95 @@
#pragma once
#include <string>
#include "EnumNameMap.h"
#include "Helper.h"
using std::string;
namespace gt {
class LibertyCell;
class LibertyPort;
class TimingArc;
struct LutTemplate;
class Lut;
enum class TimingSense { non_unate, positive_unate, negative_unate, unknown };
enum class TimingType {
clear,
combinational,
combinational_fall,
combinational_rise,
falling_edge,
hold_falling,
hold_rising,
min_pulse_width,
minimum_period,
nochange_high_high,
nochange_high_low,
nochange_low_high,
nochange_low_low,
non_seq_hold_falling,
non_seq_hold_rising,
non_seq_setup_falling,
non_seq_setup_rising,
preset,
recovery_falling,
recovery_rising,
removal_falling,
removal_rising,
retaining_time,
rising_edge,
setup_falling,
setup_rising,
skew_falling,
skew_rising,
three_state_disable,
three_state_disable_fall,
three_state_disable_rise,
three_state_enable,
three_state_enable_fall,
three_state_enable_rise,
min_clock_tree_path,
max_clock_tree_path,
unknown
};
TimingSense findTimingSense(const std::string sense_name);
TimingType findTimingType(const std::string type_name);
class TimingArc {
public:
TimingArc();
// TimingArc(TimingArcSet* set, LibertyPort* from, LibertyPort* to, Tran irf, Tran orf);
int id = -1;
string encode_str_;
LibertyCell* cell_;
LibertyPort* liberty_port_;
TimingType timing_type_ = TimingType::unknown;
TimingSense timing_sense_ = TimingSense::unknown;
string related_port_name_;
LibertyPort* from_port_;
LibertyPort* to_port_;
string sdf_cond_;
bool is_cond_ = false;
// TimingArcSet* timing_arc_set_;
Lut* cell_delay_[MAX_TRAN];
Lut* transition_[MAX_TRAN];
Lut* constraint_[MAX_TRAN];
string encode_arc();
bool is_constraint() const;
bool is_min_constraint() const;
bool is_max_constraint() const;
bool is_rising_edge_triggered() const;
bool is_falling_edge_triggered() const;
};
}; // namespace gt

25447
cpp_to_py/common/lib/sdc/json.hpp Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
2014-01-07 Andreas Kupries <andreask@activestate.com>
* json.tcl: Move many-* wrapper to before its usage. Bumped
version to 1.3.2. v1.3.1 is broken.
* c/json.tab.c: Worked around issues with the critcl v2
* c/json.y: application the Tcllib C code is geared towards.
* json.tcl: Bumped json version to 1.3.1, jsonc to 1.1.1,
* jsonc.tcl: and tcllibc to 0.3.13.
* tcllibc.tcl: See ticket [6efa4f571af052].
2014-01-06 Andreas Kupries <andreask@activestate.com>
See ticket [6efa4f571af052].
c: Removed json-parser files.
c/json.y: New parser.
c/json.tab.c: Generated parser code.
c/json_y.h: Header to binding.
jsonc.tcl:
json_tcl.tcl:
Reworked the Json/C code to use a bison-pased parser provided by
Mikhail. No separate data structures to convert, just direct
generation of Tcl structures. Changes compared to the original
submission:
- Use List, not Dict operations for objects, i.e. be Tcl 8.4
compatible.
- Do not generate Int/Double objects, only strings. Conversion to
actual int is lazy, when actually needed. Also ensures that
compile-time Tcl version does not restrict range of integers,
only runtime Tcl version.
- Allow all values as toplevel json, not just array and object.
- Currently no shared objects for the fixed values (null, true,
false).
Note that the RE-based json validation is still faster on even
moderatly sized strings, even when just using a stripped C lexer
not generating token values.
Bumped jsonc to version 1.1 and tcllibc to version 0.3.12.
2013-12-11 Andreas Kupries <andreask@activestate.com>
* c: [Ticket 6efa4f571a]: Integrated a critcl binding of
* json.bench: the json-c parser. Moved to a standard
* json.man: switchable setup. json2dict and manyy-json2dict
* json.tcl: are now switchable to C. Everything else kept
* json.test: to Tcl. Note especially that Tcl 'validate'
* json.testsuite: (regexp-based) was still faster than json-c.
* json_tcl.tcl: Which has no mode for pure syntax checking,
* jsonc.tcl: thus overhead with construction of irelevant data
* pkgIndex.tcl: structures. Extended testsuite. New benchmark
* test-data: suite. Version bumped to 1.3.
2013-06-19 Andreas Kupries <andreask@activestate.com>
* json.man: New command 'many-json2dict' to parse strings
* json.pcx: containing more than one JSON entity. The existing
* json.tcl: json2dict command will return only the first. Updated
* json.test: documentation. Extended testsuite. Package version
* pkgIndex.tcl: bumped to 1.2
2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.15 ========================
*
2013-02-01 Andreas Kupries <aku@hephaistos>
* json_write.tcl: While we can quote / (solidus) via \/ as per the
* json_write.man: JSON syntax there is no reason why we should.
* json_write.test: Bumped version to 1.0.2.
* pkgIndex.tcl:
2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.14 ========================
*
2011-11-10 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json.tcl: [Bug 3426178]: Fixed bug in "list2json",
* json.test: reported by <a11426@users.sourceforge.net>.
* json.man: Updated testsuite. Bumped version to 1.1.2.
* pkgIndex.tcl:
2011-08-24 Andreas Kupries <andreask@activestate.com>
* json_write.man:
* json_write.test:
* json_write.tcl: [Bug 3396787]: Fixed missing argument to call of
* pkgIndex.tcl: [info level], breaking the argument checks. Bumped
version to 1.0.1
2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.13 ========================
*
2011-01-20 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json.tcl (json::parseValue): Fixed a missing -- older 8.4 seems
* json.man: to require to handle a dash in $leadingChar. Bumped
* pkgIndex.tcl: version to 1.1.1
2009-12-10 Andreas Kupries <andreask@activestate.com>
* json.tcl: [Patch 2909962]: Accepted rewrite of the json parser
* json.man: internals by Thomas Maeder
* pkgIndex.tcl: <thomasmaeder@users.sourceforge.net>. The new
(regex-based) parser is considerably faster than the previous
implementation. Bumped version to 1.1.
2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.12 ========================
*
2009-11-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json_write.tcl: New package 'json::write', supporting the
* json_write.test: generation of text in JSON format.
* json_write.man: Package version 1.
* json_write.pcx:
* pkgIndex.tcl:
2009-11-23 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json.tcl: Bumped package to version 1.0.1 due to the bugfix made
* pkgIndex.tcl: on 2009-04-18.
2009-05-26 KATO Kanryu <kanryu6@users.sourceforge.net>
* json.test: improved to compare dicts
2009-04-18 KATO Kanryu <kanryu6@users.sourceforge.net>
* json.tcl: fixed to parse last integer
* json.test: improved to compare dicts
2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.11.1 ========================
*
2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.11 ========================
*
2008-06-14 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json.pcx: New file. Syntax definitions for the public commands
of the json package.
2007-12-05 Andreas Kupries <andreask@activestate.com>
* json.test: Brought the test results into sync with the ordered
dicts of Tcl 8.5. NOTE: This will cause the combination of Tcl
8.4 with a backported dict to fail, at least until either the
backported dict does the same ordering, or the tests are split
into variants, one for both of the two cases. This fixes [Tcllib
SF Bug 1844104], reported by Larry Virden
<lvirden@users.sourceforge.net>. Thanks.
2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.10 ========================
*
2007-03-21 Andreas Kupries <andreas_kupries@users.sourceforge.net>
* json.man: Fixed all warnings due to use of now deprecated
commands. Added a section about how to give feedback.
2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net>
*
* Released and tagged Tcllib 1.9 ========================
*
2006-08-25 Jeff Hobbs <jeffh@ActiveState.com>
* json.test: empty list test cases
* json.tcl (json::_json2dict): handle empty list case
2006-08-18 Andreas Kupries <andreask@activestate.com>
* json.man: Added some more keywords to the docs.
2006-08-17 Jeff Hobbs <jeffh@ActiveState.com>
* json.tcl, json.man, json.test, pkgIndex.tcl: json package v1.0
Parses JSON formatted text into Tcl dicts.
See http://www.json.org/ for format details.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,557 @@
/*
* JSON parser, yacc/bison based. Manual lexer.
* Mikhail.
*/
%define api.pure full
%{
/* * ** *** ***** ******** ************* ********************* */
#include <tcl.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <json_y.h>
#define TOKEN(tok) TRACE (("TOKEN %s\n", tok))
#define TOKEN1(tok) TRACE (("TOKEN %s (%s)\n", tok, Tcl_GetString(context->obj)))
#define REDUCE(rule) TRACE (("REDUCE %s\n", rule))
#define TRUE_O (Tcl_NewStringObj("true", 4))
#define FALSE_O (Tcl_NewStringObj("false", 5))
#define NULL_O (Tcl_NewStringObj("null", 4))
typedef union YYSTYPE YYSTYPE;
static void jsonerror (struct context *, const char *);
static int jsonlexp (YYSTYPE *lvalp, struct context *context);
#define yylex jsonlexp
#define yyerror jsonerror
/* * ** *** ***** ******** ************* *********************
** User declarations <EOF>
*/
%}
%union {
Tcl_Obj *obj;
struct {
Tcl_Obj *key;
Tcl_Obj *val;
} keyval;
};
%lex-param {struct context* context}
%parse-param {struct context* context}
%token STRING CONSTANT
%type <obj> tree
%type <obj> json
%type <obj> object
%type <obj> list
%type <obj> values
%type <obj> members
%type <obj> value
%type <obj> string
%type <keyval> member
%%
tree : json
{
REDUCE("TREE");
if (context->I) {
Tcl_SetObjResult(context->I, $1);
TRACE ((" RESULT (%s)\n", Tcl_GetString($1)));
}
context->result = TCL_OK;
}
;
json : value
;
object : '{' members '}'
{
$$ = $2;
}
| '{' '}'
{
$$ = Tcl_NewObj();
}
;
list : '[' values ']'
{
$$ = $2;
}
| '[' ']'
{
$$ = Tcl_NewObj();
}
;
values : value
{
$$ = Tcl_NewListObj(1, &$1);
}
| values ',' value
{
Tcl_ListObjAppendElement(NULL, $1, $3);
$$ = $1;
}
;
members : member
{
$$ = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(NULL, $$, $1.key);
Tcl_ListObjAppendElement(NULL, $$, $1.val);
}
| members ',' member
{
Tcl_ListObjAppendElement(NULL, $1, $3.key);
Tcl_ListObjAppendElement(NULL, $1, $3.val);
$$ = $1;
}
;
member : string ':' value
{
$$.key = $1;
$$.val = $3;
}
;
string : STRING
{
$$ = context->obj;
}
;
value : CONSTANT
{
$$ = context->obj;
}
| string
| object
| list
;
%%
/* * ** *** ***** ******** ************* *********************
** User definitions
*/
void
jsonparse (struct context* context)
{
yyparse (context);
}
#define HAVE(n) (context->remaining >= n)
#define DRAIN(n) context->text += n, context->remaining -= n
#define STORESTRINGSEGMENT() \
if (initialized) { \
if (context->text != bp) { \
Tcl_AppendToObj(context->obj, \
bp, context->text - bp); \
} \
} else { \
context->obj = Tcl_NewStringObj( \
bp, context->text - bp); \
initialized = 1; \
}
void
jsonskip(struct context *context)
{
while (context->remaining) {
switch (*context->text) {
case '\n':
case ' ':
case '\t':
case '\r':
DRAIN(1);
continue;
}
break;
}
}
static int
jsonlexp(YYSTYPE *lvalp, struct context *context)
{
const char *bp = NULL;
/* Question: Why not plain numbers 1,2 for the states
* but these specific hex patterns ?
*/
enum {
PLAIN = 0x0000ff00,
INSTR = 0x00ff0000
} lstate;
double d;
char *end;
const char *p;
int initialized = 0;
/*
* Do not auto-lex beyond a full json structure.
*/
if (context->result == TCL_OK) {
TOKEN ("<<eof>>");
return 0;
}
/*
* Quickly skip and ignore whitespace.
*/
while (context->remaining) {
switch (*context->text) {
case '\n':
case ' ':
case '\t':
case '\r':
DRAIN(1);
continue;
}
break;
}
/*
* Handle the token following the whitespace. Small state machine to
* handle strings and escapes in them, and bare words (various
* contants, and numbers).
*/
for (lstate = PLAIN; context->remaining > 0; DRAIN(1)) {
if (lstate == INSTR) {
if (*context->text == '"') {
/*
* End of quoted string
*/
STORESTRINGSEGMENT();
DRAIN(1);
TOKEN1 ("STRING");
return STRING;
}
if (*context->text == '\\') {
/*
* Escaped sequence. The 9 sequences specified at json.org
* are:
* \" \\ \/ \b \f \n \r \t \uXXXX
*/
char buf[TCL_UTF_MAX];
int len, consumed;
STORESTRINGSEGMENT();
/*
* Perform additional checks to restrict the set of accepted
* escape sequence to what is allowed by json.org instead of
* Tcl_UtfBackslash.
*/
if (!HAVE(1)) {
Tcl_AppendToObj(context->obj, "\\", 1);
yyerror(context,"incomplete escape at <<eof> error");
TOKEN("incomplete escape at <<eof>> error");
return -1;
}
switch (context->text[1]) {
case '"':
case '\\':
case '/':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
break;
case 'u':
if (!HAVE(5)) {
Tcl_AppendToObj(context->obj, "\\u", 2);
yyerror(context,"incomplete escape at <<eof> error");
TOKEN("incomplete escape at <<eof>> error");
return -1;
}
break;
default:
Tcl_AppendToObj(context->obj, context->text + 1, 1);
yyerror(context,"bad escape");
TOKEN("bad escape");
return -1;
}
/*
* XXX Tcl_UtfBackslash() may be more
* XXX permissive, than JSON standard.
* XXX But that may be a good thing:
* XXX "be generous in what you accept".
*/
len = Tcl_UtfBackslash(context->text,
&consumed, buf);
DRAIN(consumed - 1);
bp = context->text + 1;
Tcl_AppendToObj(context->obj, buf, len);
}
continue;
}
switch (*context->text) {
case ',':
case '{':
case ':':
case '}':
case '[':
case ']':
DRAIN(1);
TOKEN (context->text[-1]);
return context->text[-1];
case 't':
if ((context->remaining < 4) ||
strncmp("rue", context->text + 1, 3))
goto bareword;
DRAIN(4);
context->obj = TRUE_O;
TOKEN1 ("CONSTANT");
return CONSTANT;
case 'f':
if ((context->remaining < 5) ||
strncmp("alse", context->text + 1, 4))
goto bareword;
DRAIN(5);
context->obj = FALSE_O;
TOKEN1 ("CONSTANT");
return CONSTANT;
case 'n':
if ((context->remaining < 4) ||
strncmp("ull", context->text + 1, 3))
goto bareword;
DRAIN(4);
context->obj = NULL_O;
TOKEN1 ("CONSTANT");
return CONSTANT;
case '"':
bp = context->text + 1;
lstate = INSTR;
continue;
case '\\':
yyerror(context,"Escape character outside of string");
TOKEN ("escape error");
return -1;
}
/*
* We already considered the null, true, and false
* above, so it can only be a number now.
*
* NOTE: At this point we do not care about double
* versus integer, nor about the possible integer
* range. We generate a plain string Tcl_Obj and leave
* it to the user of the generated structure to
* convert to a number when actually needed. This
* defered conversion also ensures that the Tcl and
* platform we are building against does not matter
* regarding integer range, only the abilities of the
* Tcl at runtime.
*/
d = strtod(context->text, &end);
if (end == context->text)
goto bareword; /* Nothing parsed */
context->obj = Tcl_NewStringObj (context->text,
end - context->text);
context->remaining -= (end - context->text);
context->text = end;
TOKEN1 ("CONSTANT");
return CONSTANT;
}
TOKEN ("<<eof>>");
return 0;
bareword:
yyerror(context,"Bare word encountered");
TOKEN ("bare word error");
return -1;
}
#if 0
int
jsonlex(struct context *context)
{
const char *bp = NULL;
/* Question: Why not plain numbers 1,2 for the states
* but these specific hex patterns ?
*/
enum {
PLAIN = 0x0000ff00,
INSTR = 0x00ff0000
} lstate;
double d;
char *end;
const char *p;
int initialized = 0;
while (context->remaining) {
/* Iterate over the whole string and check all tokens.
* Nothing else.
*/
/*
* Quickly skip and ignore whitespace.
*/
while (context->remaining) {
switch (*context->text) {
case '\n':
case ' ':
case '\t':
case '\r':
DRAIN(1);
continue;
}
break;
}
/*
* Handle the token following the whitespace. Small state machine to
* handle strings and escapes in them, and bare words (various
* contants, and numbers).
*/
for (lstate = PLAIN; context->remaining > 0; DRAIN(1)) {
if (lstate == INSTR) {
if (*context->text == '"') {
/*
* End of quoted string
*/
DRAIN(1);
goto next_token;
}
if (*context->text == '\\') {
/*
* Escaped sequence
*/
char buf[TCL_UTF_MAX];
int len, consumed;
/*
* XXX Tcl_UtfBackslash() may be more
* XXX permissive, than JSON standard.
* XXX But that may be a good thing:
* XXX "be generous in what you accept".
*/
len = Tcl_UtfBackslash(context->text, &consumed, buf);
DRAIN(consumed - 1);
}
continue;
}
switch (*context->text) {
case ',':
case '{':
case ':':
case '}':
case '[':
case ']':
DRAIN(1);
goto next_token;
case 't':
if ((context->remaining < 4) ||
strncmp("rue", context->text + 1, 3))
return -1; /* bare word */
DRAIN(4);
goto next_token;
case 'f':
if ((context->remaining < 5) ||
strncmp("alse", context->text + 1, 4))
return -1; /* bare word */
DRAIN(5);
goto next_token;
case 'n':
if ((context->remaining < 4) ||
strncmp("ull", context->text + 1, 3))
return -1; /* bare word */
DRAIN(4);
goto next_token;
case '"':
bp = context->text + 1;
lstate = INSTR;
continue;
case '\\':
/* Escape outside string, abort. */
return -1;
}
/*
* We already considered the null, true, and false
* above, so it can only be a number now.
*
* NOTE: At this point we do not care about double
* versus integer, nor about the possible integer
* range. We generate a plain string Tcl_Obj and leave
* it to the user of the generated structure to
* convert to a number when actually needed. This
* defered conversion also ensures that the Tcl and
* platform we are building against does not matter
* regarding integer range, only the abilities of the
* Tcl at runtime.
*/
d = strtod(context->text, &end);
if (end == context->text)
return -1; /* bare word */
context->remaining -= (end - context->text);
context->text = end;
goto next_token;
}
return 0;
next_token:
continue;
}
}
#endif
static void
jsonerror(struct context *context, const char *message)
{
char *fullmessage;
char *yytext;
int yyleng;
if (context->has_error) return;
if (context->obj) {
yytext = Tcl_GetStringFromObj(context->obj, &yyleng);
fullmessage = Tcl_Alloc(strlen(message) + 63 + yyleng);
sprintf(fullmessage, "%s %d bytes before end, around ``%.*s''",
message, context->remaining, yyleng, yytext);
} else {
fullmessage = Tcl_Alloc(strlen(message) + 63);
sprintf(fullmessage, "%s %d bytes before end",
message, context->remaining);
}
TRACE ((">>> %s\n",fullmessage));
Tcl_SetResult (context->I, fullmessage, TCL_DYNAMIC);
Tcl_SetErrorCode (context->I, "JSON", "SYNTAX", NULL);
context->has_error = 1;
}

View File

@ -0,0 +1,63 @@
/*
* Data structures and declarations for yacc/bison based json parser.
* External to .y file for communication and use within the binding layer.
*/
struct context {
/*
* General state.
*/
Tcl_Interp *I; /* Tcl interpreter we are in. */
int result; /* Tcl result of the parse.
**
* NOTE: A value of TCL_OK (set when
* successfully reducing the main rule)
* causes the lexer to return <<EOF>> from
* then on, preventing parsing beyond a
* single json structure.
*/
/*
* Lexer Input.
*/
const char *text; /* Text to parse */
int remaining; /* Number of characters left to parse. */
/*
* Lexer -> Parser communication.
*/
Tcl_Obj *obj; /* Tcl value of the last returned token. */
int has_error;
};
/*
* Note: The parser function automatically sets the Tcl_Interp (See
* field "I") result to the parse result, or an error message.
*/
extern void
jsonparse (struct context *);
#if 0
extern int
jsonlex(struct context *);
#endif
extern void
jsonskip (struct context *);
/*
* Default: Tracing off.
*/
#ifndef JSON_DEBUG
#define JSON_DEBUG 0
#endif
#if JSON_DEBUG
#define TRACE(x) do { printf x ; fflush (stdout); } while (0)
#else
#define TRACE(x)
#endif

View File

@ -0,0 +1,167 @@
# -*- tcl -*-
# Tcl Benchmark File
#
# This file contains a number of benchmarks for the 'json' parser
# to allow developers to monitor package performance.
#
# (c) 2013 Andreas Kupries <andreas_kupries@users.sourceforge.net>
# We need at least version 8.4 for the package and thus the
# benchmarks.
if {![package vsatisfies [package present Tcl] 8.4]} {
bench_puts "Need Tcl 8.4+, found Tcl [package present Tcl]"
return
}
# ### ### ### ######### ######### ######### ###########################
## Setting up the environment ...
package require Tcl 8.4
package forget json
set self [file join [pwd] [file dirname [info script]]]
set mod [file dirname $self]
set index [file join [file dirname $self] tcllibc pkgIndex.tcl]
if 1 {
if {[file exists $index]} {
set ::dir [file dirname $index]
uplevel #0 [list source $index]
unset ::dir
package require tcllibc
}
}
source [file join $self json.tcl]
# ### ### ### ######### ######### ######### ###########################
## Helpers
proc cat {f} {
set c [open $f]
set d [read $c]
close $c
return $d
}
proc iota {n} {
set r {}
while {$n > 0} {
lappend r [json::string2json $n]
incr n -1
}
return $r
}
proc iota-dict {n} {
set r {}
while {$n > 0} {
lappend r f$n [json::string2json $n]
incr n -1
}
return $r
}
# ### ### ### ######### ######### ######### ###########################
## Get all the possible implementations
json::SwitchTo {}
foreach e [json::KnownImplementations] {
::json::LoadAccelerator $e
}
# ### ### ### ######### ######### ######### ###########################
## Benchmarks.
## Just the parser, on the valid inputs for the testsuite.
foreach impl [json::Implementations] {
json::SwitchTo $impl
if {$impl eq "tcl"} {
set series {0 1 10 100 1000}
} else {
set series {0 1 10 100 1000}
}
bench_puts "=== === === === === ==="
bench_puts "=== === === $impl ==="
bench_puts "=== === === === === ==="
bench_puts {=== test-data =========}
foreach f [glob -nocomplain -directory $self/tests *.json] {
set in [cat $f]
bench -desc "parse [file rootname [file tail $f]] ($impl)" -body {
json::json2dict $in
}
bench -desc "validate [file rootname [file tail $f]] ($impl)" -body {
json::validate $in
}
}
foreach f [glob -nocomplain -directory $self/tests *.bench] {
set in [cat $f]
bench -desc "parse [file rootname [file tail $f]] ($impl)" -body {
json::json2dict $in
}
bench -desc "validate [file rootname [file tail $f]] ($impl)" -body {
json::validate $in
}
}
bench_puts {=== synthetic array =========}
foreach n $series {
set in [json::list2json [iota $n]]
bench -desc "parse array-$n ($impl)" -body {
json::json2dict $in
}
bench -desc "validate array-$n ($impl)" -body {
json::validate $in
}
}
bench_puts {=== synthetic object =========}
foreach n $series {
set in [json::dict2json [iota-dict $n]]
bench -desc "parse object-$n ($impl)" -body {
json::json2dict $in
}
bench -desc "validate object-$n ($impl)" -body {
json::validate $in
}
}
bench_puts {=== synthetic string =========}
foreach n $series {
set in [json::string2json [string repeat . $n]]
bench -desc "parse string-$n ($impl)" -body {
json::json2dict $in
}
bench -desc "validate string-$n ($impl)" -body {
json::validate $in
}
}
}
# ### ### ### ######### ######### ######### ###########################
## Complete
return
# ### ### ### ######### ######### ######### ###########################
## Notes ...

View File

@ -0,0 +1,114 @@
[comment {-*- tcl -*- doctools manpage}]
[vset VERSION 1.3.4]
[manpage_begin json n [vset VERSION]]
[keywords {data exchange}]
[keywords {exchange format}]
[keywords javascript]
[keywords json]
[copyright {2006 ActiveState Software Inc.}]
[copyright {2009 Thomas Maeder, Glue Software Engineering AG}]
[moddesc {JSON}]
[titledesc {JSON parser}]
[category {CGI programming}]
[require Tcl 8.4]
[require json [opt [vset VERSION]]]
[description]
[para]
The [package json] package provides a simple Tcl-only library for parsing the
JSON [uri http://www.json.org/] data exchange format as specified in RFC 4627
[uri http://www.ietf.org/rfc/rfc4627.txt].
There is some ambiguity in parsing JSON because JSON has type information that
is not maintained by the Tcl conversion. The [package json] package returns
data as a Tcl [cmd dict]. Either the [package dict] package or Tcl 8.5 is
required for use.
[section COMMANDS]
[list_begin definitions]
[call [cmd ::json::json2dict] [arg txt]]
Parse JSON formatted text [arg txt] into a Tcl dict and return
the value.
[para] If [arg txt] contains more than one JSON entity only the
first one is returned.
[call [cmd ::json::many-json2dict] [arg txt] [opt [arg max]]]
Parse JSON formatted text [arg txt] containing multiple JSON entities
into a list of dictionaries and return that list.
[para] If [arg max] is specified exactly that many entities are extracted
from [arg txt]. By default the command will attempt to extract all, without
limits. A value of "[arg max] == 0" does not make sense and will cause the
command to throw an error.
[list_end]
[para]
[section EXAMPLES]
[para]
An example of a JSON array converted to Tcl. A JSON array is returned as a
single item with multiple elements.
[para]
[example {[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]
=>
{Country US Latitude 37.7668 precision zip State CA City {SAN FRANCISCO} Address {} Zip 94107 Longitude -122.3959} {Country US Latitude 37.371991 precision zip State CA City SUNNYVALE Address {} Zip 94085 Longitude -122.026020}
}]
[para]
An example of a JSON object converted to Tcl. A JSON object is returned as a
multi-element list (a dict).
[para]
[example {{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": "100"
},
"IDs": [116, 943, 234, 38793]
}
}
=>
Image {IDs {116 943 234 38793} Thumbnail {Width 100 Height 125 Url http://www.example.com/image/481989943} Width 800 Height 600 Title {View from 15th Floor}}
}]
[section RELATED]
To write json, instead of parsing it, see package [package json::write].
[vset CATEGORY json]
[include ../doctools2base/include/feedback.inc]
[manpage_end]

View File

@ -0,0 +1,32 @@
# -*- tcl -*- json.pcx
# Syntax of the commands provided by package json.
#
# For use by TclDevKit's static syntax checker (v4.1+).
# See http://www.activestate.com/solutions/tcl/
# See http://aspn.activestate.com/ASPN/docs/Tcl_Dev_Kit/4.0/Checker.html#pcx_api
# for the specification of the format of the code in this file.
#
package require pcx
pcx::register json
pcx::tcldep 1.0 needs tcl 8.4
pcx::tcldep 1.2 needs tcl 8.4
namespace eval ::json {}
#pcx::message FOO {... text ...} type
#pcx::scan <VERSION> <NAME> <RULE>
pcx::check 1.0 std ::json::json2dict \
{checkSimpleArgs 1 1 {
checkWord
}}
pcx::check 1.2 std ::json::many-json2dict \
{checkSimpleArgs 1 2 {
checkWord checkInt
}}
# Initialization via pcx::init.
# Use a ::json::init procedure for non-standard initialization.
pcx::complete

View File

@ -0,0 +1,285 @@
# json.tcl --
#
# JSON parser for Tcl. Management code, Tcl/C detection and selection.
#
# Copyright (c) 2013 by Andreas Kupries
# @mdgen EXCLUDE: jsonc.tcl
package require Tcl 8.4
namespace eval ::json {}
# ### ### ### ######### ######### #########
## Management of json implementations.
# ::json::LoadAccelerator --
#
# Loads a named implementation, if possible.
#
# Arguments:
# key Name of the implementation to load.
#
# Results:
# A boolean flag. True if the implementation
# was successfully loaded; and False otherwise.
proc ::json::LoadAccelerator {key} {
variable accel
set r 0
switch -exact -- $key {
critcl {
# Critcl implementation of json requires Tcl 8.4.
if {![package vsatisfies [package provide Tcl] 8.4]} {return 0}
if {[catch {package require tcllibc}]} {return 0}
# Check for the jsonc 1.1.1 API we are fixing later.
set r [llength [info commands ::json::many_json2dict_critcl]]
}
tcl {
variable selfdir
source [file join $selfdir json_tcl.tcl]
set r 1
}
default {
return -code error "invalid accelerator/impl. package $key:\
must be one of [join [KnownImplementations] {, }]"
}
}
set accel($key) $r
return $r
}
# ::json::SwitchTo --
#
# Activates a loaded named implementation.
#
# Arguments:
# key Name of the implementation to activate.
#
# Results:
# None.
proc ::json::SwitchTo {key} {
variable accel
variable loaded
variable apicmds
if {[string equal $key $loaded]} {
# No change, nothing to do.
return
} elseif {![string equal $key ""]} {
# Validate the target implementation of the switch.
if {![info exists accel($key)]} {
return -code error "Unable to activate unknown implementation \"$key\""
} elseif {![info exists accel($key)] || !$accel($key)} {
return -code error "Unable to activate missing implementation \"$key\""
}
}
# Deactivate the previous implementation, if there was any.
if {![string equal $loaded ""]} {
foreach c $apicmds {
rename ::json::${c} ::json::${c}_$loaded
}
}
# Activate the new implementation, if there is any.
if {![string equal $key ""]} {
foreach c $apicmds {
rename ::json::${c}_$key ::json::${c}
}
}
# Remember the active implementation, for deactivation by future
# switches.
set loaded $key
return
}
# ::json::Implementations --
#
# Determines which implementations are
# present, i.e. loaded.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys.
proc ::json::Implementations {} {
variable accel
set res {}
foreach n [array names accel] {
if {!$accel($n)} continue
lappend res $n
}
return $res
}
# ::json::KnownImplementations --
#
# Determines which implementations are known
# as possible implementations.
#
# Arguments:
# None.
#
# Results:
# A list of implementation keys. In the order
# of preference, most prefered first.
proc ::json::KnownImplementations {} {
return {critcl tcl}
}
proc ::json::Names {} {
return {
critcl {tcllibc based}
tcl {pure Tcl}
}
}
# ### ### ### ######### ######### #########
## Initialization: Data structures.
namespace eval ::json {
variable selfdir [file dirname [info script]]
variable accel
array set accel {tcl 0 critcl 0}
variable loaded {}
variable apicmds {
json2dict
many-json2dict
}
}
# ### ### ### ######### ######### #########
## Wrapper fix for the jsonc package to match APIs.
proc ::json::many-json2dict_critcl {args} {
eval [linsert $args 0 ::json::many_json2dict_critcl]
}
# ### ### ### ######### ######### #########
## Initialization: Choose an implementation,
## most prefered first. Loads only one of the
## possible implementations. And activates it.
namespace eval ::json {
variable e
foreach e [KnownImplementations] {
if {[LoadAccelerator $e]} {
SwitchTo $e
break
}
}
unset e
}
# ### ### ### ######### ######### #########
## Tcl implementation of validation, shared for Tcl and C implementation.
##
## The regexp based validation is consistently faster than json-c.
## Suspected reasons: Tcl REs are mainly in C as well, and json-c has
## overhead in constructing its own data structures. While irrelevant
## to validation json-c still builds them, it has no mode doing pure
## syntax checking.
namespace eval ::json {
# Regular expression for tokenizing a JSON text (cf. http://json.org/)
# tokens consisting of a single character
variable singleCharTokens { "{" "}" ":" "\\[" "\\]" "," }
variable singleCharTokenRE "\[[join $singleCharTokens {}]\]"
# quoted string tokens
variable escapableREs { "[\\\"\\\\/bfnrt]" "u[[:xdigit:]]{4}" "." }
variable escapedCharRE "\\\\(?:[join $escapableREs |])"
variable unescapedCharRE {[^\\\"]}
variable stringRE "\"(?:$escapedCharRE|$unescapedCharRE)*\""
# as above, for validation
variable escapableREsv { "[\\\"\\\\/bfnrt]" "u[[:xdigit:]]{4}" }
variable escapedCharREv "\\\\(?:[join $escapableREsv |])"
variable stringREv "\"(?:$escapedCharREv|$unescapedCharRE)*\""
# (unquoted) words
variable wordTokens { "true" "false" "null" }
variable wordTokenRE [join $wordTokens "|"]
# number tokens
# negative lookahead (?!0)[[:digit:]]+ might be more elegant, but
# would slow down tokenizing by a factor of up to 3!
variable positiveRE {[1-9][[:digit:]]*}
variable cardinalRE "-?(?:$positiveRE|0)"
variable fractionRE {[.][[:digit:]]+}
variable exponentialRE {[eE][+-]?[[:digit:]]+}
variable numberREa "${cardinalRE}(?:$fractionRE)?(?:$exponentialRE)?"
variable numberREb "${fractionRE}(?:$exponentialRE)?"
variable numberREc "${cardinalRE}\[.\](?:$exponentialRE)?"
variable numberRE "$numberREa|$numberREb|$numberREc"
variable numberRE "$numberREa|$numberREb|$numberREc"
# JSON token, and validation
variable tokenRE "$singleCharTokenRE|$stringRE|$wordTokenRE|$numberRE"
variable tokenREv "$singleCharTokenRE|$stringREv|$wordTokenRE|$numberRE"
# 0..n white space characters
set whiteSpaceRE {[[:space:]]*}
# Regular expression for validating a JSON text
variable validJsonRE "^(?:${whiteSpaceRE}(?:$tokenREv))*${whiteSpaceRE}$"
}
# Validate JSON text
# @param jsonText JSON text
# @return 1 iff $jsonText conforms to the JSON grammar
# (@see http://json.org/)
proc ::json::validate {jsonText} {
variable validJsonRE
return [regexp -- $validJsonRE $jsonText]
}
# ### ### ### ######### ######### #########
## These three procedures shared between Tcl and Critcl implementations.
## See also package "json::write".
proc ::json::dict2json {dictVal} {
# XXX: Currently this API isn't symmetrical, as to create proper
# XXX: JSON text requires type knowledge of the input data
set json ""
set prefix ""
foreach {key val} $dictVal {
# key must always be a string, val may be a number, string or
# bare word (true|false|null)
if {0 && ![string is double -strict $val]
&& ![regexp {^(?:true|false|null)$} $val]} {
set val "\"$val\""
}
append json "$prefix\"$key\": $val" \n
set prefix ,
}
return "\{${json}\}"
}
proc ::json::list2json {listVal} {
return "\[[join $listVal ,]\]"
}
proc ::json::string2json {str} {
return "\"$str\""
}
# ### ### ### ######### ######### #########
## Ready
package provide json 1.3.4

View File

@ -0,0 +1,94 @@
# json.test - Copyright (C) 2006 ActiveState Software Inc.
#
# Tests for the Tcllib json package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
# RCS: @(#) $Id: json.test,v 1.8 2011/11/10 21:05:58 andreas_kupries Exp $
# -------------------------------------------------------------------------
source [file join \
[file dirname [file dirname [file join [pwd] [info script]]]] \
devtools testutilities.tcl]
testsNeedTcl [expr {[catch {package require dict}] ? "8.5" : "8.4"}]
testsNeedTcltest 2.0
support {
useLocalFile tests/support.tcl
}
testing {
useAccel [useTcllibC] json/json.tcl json
TestAccelInit json
}
# -------------------------------------------------------------------------
# Tests
# -------------------------------------------------------------------------
TestAccelDo json impl {
switch -exact -- $impl {
critcl {
set MY myjson
proc tmWrong {m loarg n {xarg {}}} {
return [tcltest::wrongNumArgs "myjson $m" $loarg $n]
}
proc tmTooMany {m loarg {xarg {}}} {
return [tcltest::tooManyArgs "myjson $m" $loarg]
}
proc tmTake {tcl c} { return $c }
}
tcl {
set MY ::myjson
if {[package vsatisfies [package provide Tcl] 8.5]} {
proc tmWrong {m loarg n {xarg {}}} {
if {$xarg == {}} {set xarg $loarg}
if {$xarg != {}} {set xarg " $xarg"}
incr n
return [tcltest::wrongNumArgs "I $m" "name$xarg" $n]
}
proc tmTooMany {m loarg {xarg {}}} {
if {$xarg == {}} {set xarg $loarg}
if {$xarg != {}} {set xarg " $xarg"}
return [tcltest::tooManyArgs "I $m" "name$xarg"]
}
} else {
proc tmWrong {m loarg n {xarg {}}} {
if {$xarg == {}} {set xarg $loarg}
if {$xarg != {}} {set xarg " $xarg"}
incr n
return [tcltest::wrongNumArgs "::struct::json::I::$m" "name$xarg" $n]
}
proc tmTooMany {m loarg {xarg {}}} {
if {$xarg == {}} {set xarg $loarg}
if {$xarg != {}} {set xarg " $xarg"}
return [tcltest::tooManyArgs "::struct::json::I::$m" "name$xarg"]
}
}
proc tmTake {tcl c} { return $tcl }
}
}
source [localPath json.testsuite]
}
# -------------------------------------------------------------------------
catch {unset JSON}
catch {unset TCL}
catch {unset DICTSORT}
testsuiteCleanup
# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

View File

@ -0,0 +1,102 @@
# -*- tcl -*-
# -------------------------------------------------------------------------
# Tests
# -------------------------------------------------------------------------
set i 0
foreach name [lsort -dict [array names JSON]] {
test json-${impl}-1.[incr i] "test JSON $name" -body {
transform [json::json2dict $JSON($name)] $name
} -result [resultfor $name]
}
set i 0
foreach name [lsort -dict [array names JSON]] {
test json-${impl}-7.[incr i] "validate JSON $name" -body {
json::validate $JSON($name)
} -result 1
}
set i 0
foreach name [lsort -dict [array names FAIL]] {
test json-${impl}-8.[incr i] "test FAIL $name" -body {
json::json2dict $FAIL($name)
} -returnCodes error -result $ERR(${name}-${impl})
}
set i 0
foreach name [lsort -dict [array names FAIL]] {
test json-${impl}-9.[incr i] "validate FAIL $name" -body {
json::validate $FAIL($name)
} -result 0
}
# -------------------------------------------------------------------------
# More Tests - list2json, string2json
# TODO: dict2json
# -------------------------------------------------------------------------
test json-${impl}-2.0 {list2json} -body {
json::list2json {{"a"} {"b"} {"c"}}
} -result {["a","b","c"]}
test json-${impl}-2.1 {string2json} -body {
json::string2json a
} -result {"a"}
# -------------------------------------------------------------------------
# many-json2dict
# -------------------------------------------------------------------------
test json-${impl}-3.0 {many-json2dict, wrong args, not enough} -body {
json::many-json2dict
} -returnCodes error -match glob -result {wrong # args: should be "*json::many[-_]json2dict* jsonText ?max?"}
test json-${impl}-3.1 {many-json2dict, wrong args, too many} -body {
json::many-json2dict J M X
} -returnCodes error -match glob -result {wrong # args: should be "*json::many[-_]json2dict* jsonText ?max?"}
test json-${impl}-3.2 {many-json2dict, bad limit, zero} -body {
json::many-json2dict {[]} 0
} -returnCodes error -result {Bad limit 0 of json entities to extract.}
set i 0
foreach first [lsort -dict [array names JSON]] {
foreach second [lsort -dict [array names JSON]] {
set input $JSON($first)
append input " " $JSON($second)
set output {}
lappend output [resultfor $first]
lappend output [resultfor $second]
test json-${impl}-4.[incr i] "many-json2dict: $first/$second, all" -body {
transform* [json::many-json2dict $input] $first $second
} -result $output
}
}
set i 0
foreach first [lsort -dict [array names JSON]] {
foreach second [lsort -dict [array names JSON]] {
set input $JSON($first)
append input " " $JSON($second)
set output {}
lappend output [resultfor $first]
test json-${impl}-5.[incr i] "many-json2dict: $first/$second, first only" -body {
transform* [json::many-json2dict $input 1] $first
} -result $output
}
}
set i 0
foreach first [lsort -dict [array names JSON]] {
set input $JSON($first)
test json-${impl}-6.[incr i] "many-json2dict, bad limit, 3 over 1" -body {
json::many-json2dict $input 3
} -returnCodes error -result {Bad limit 3 of json entities to extract, found only 1.}
}
# -------------------------------------------------------------------------

View File

@ -0,0 +1,291 @@
#
# JSON parser for Tcl.
#
# See http://www.json.org/ && http://www.ietf.org/rfc/rfc4627.txt
#
# Total rework of the code published with version number 1.0 by
# Thomas Maeder, Glue Software Engineering AG
#
# $Id: json.tcl,v 1.7 2011/11/10 21:05:58 andreas_kupries Exp $
#
if {![package vsatisfies [package provide Tcl] 8.5]} {
package require dict
}
# Parse JSON text into a dict
# @param jsonText JSON text
# @return dict (or list) containing the object represented by $jsonText
proc ::json::json2dict_tcl {jsonText} {
variable tokenRE
set tokens [regexp -all -inline -- $tokenRE $jsonText]
set nrTokens [llength $tokens]
set tokenCursor 0
#puts I:($jsonText)
#puts T:\t[join $tokens \nT:\t]
return [parseValue $tokens $nrTokens tokenCursor]
}
# Parse multiple JSON entities in a string into a list of dictionaries
# @param jsonText JSON text to parse
# @param max Max number of entities to extract.
# @return list of (dict (or list) containing the objects) represented by $jsonText
proc ::json::many-json2dict_tcl {jsonText {max -1}} {
variable tokenRE
if {$max == 0} {
return -code error -errorCode {JSON BAD-LIMIT ZERO} \
"Bad limit 0 of json entities to extract."
}
set tokens [regexp -all -inline -- $tokenRE $jsonText]
set nrTokens [llength $tokens]
set tokenCursor 0
set result {}
set found 0
set n $max
while {$n != 0} {
if {$tokenCursor >= $nrTokens} break
lappend result [parseValue $tokens $nrTokens tokenCursor]
incr found
if {$n > 0} {incr n -1}
}
if {$n > 0} {
return -code error -errorCode {JSON BAD-LIMIT TOO LARGE} \
"Bad limit $max of json entities to extract, found only $found."
}
return $result
}
# Throw an exception signaling an unexpected token
proc ::json::unexpected {tokenCursor token expected} {
return -code error -errorcode [list JSON UNEXPECTED $tokenCursor $expected] \
"unexpected token \"$token\" at position $tokenCursor; expecting $expected"
}
# Get rid of the quotes surrounding a string token and substitute the
# real characters for escape sequences within it
# @param token
# @return unquoted unescaped value of the string contained in $token
proc ::json::unquoteUnescapeString {tokenCursor token} {
variable stringREv
set unquoted [string range $token 1 end-1]
if {![regexp $stringREv $token]} {
unexpected $tokenCursor $token STRING
}
set res [subst -nocommands -novariables $unquoted]
return $res
}
# Parse an object member
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @param objectDictName name (in caller's context) of dict
# representing the JSON object of which to
# parse the next member
proc ::json::parseObjectMember {tokens nrTokens tokenCursorName objectDictName} {
upvar $tokenCursorName tokenCursor
upvar $objectDictName objectDict
set token [lindex $tokens $tokenCursor]
set tc $tokenCursor
incr tokenCursor
set leadingChar [string index $token 0]
if {$leadingChar eq "\""} {
set memberName [unquoteUnescapeString $tc $token]
if {$tokenCursor == $nrTokens} {
unexpected $tokenCursor "END" "\":\""
} else {
set token [lindex $tokens $tokenCursor]
incr tokenCursor
if {$token eq ":"} {
set memberValue [parseValue $tokens $nrTokens tokenCursor]
dict set objectDict $memberName $memberValue
} else {
unexpected $tokenCursor $token "\":\""
}
}
} else {
unexpected $tokenCursor $token "STRING"
}
}
# Parse the members of an object
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @param objectDictName name (in caller's context) of dict
# representing the JSON object of which to
# parse the next member
proc ::json::parseObjectMembers {tokens nrTokens tokenCursorName objectDictName} {
upvar $tokenCursorName tokenCursor
upvar $objectDictName objectDict
while true {
parseObjectMember $tokens $nrTokens tokenCursor objectDict
set token [lindex $tokens $tokenCursor]
incr tokenCursor
switch -exact $token {
"," {
# continue
}
"\}" {
break
}
default {
unexpected $tokenCursor $token "\",\"|\"\}\""
}
}
}
}
# Parse an object
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @return parsed object (Tcl dict)
proc ::json::parseObject {tokens nrTokens tokenCursorName} {
upvar $tokenCursorName tokenCursor
if {$tokenCursor == $nrTokens} {
unexpected $tokenCursor "END" "OBJECT"
} else {
set result [dict create]
set token [lindex $tokens $tokenCursor]
if {$token eq "\}"} {
# empty object
incr tokenCursor
} else {
parseObjectMembers $tokens $nrTokens tokenCursor result
}
return $result
}
}
# Parse the elements of an array
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @param resultName name (in caller's context) of the list
# representing the JSON array
proc ::json::parseArrayElements {tokens nrTokens tokenCursorName resultName} {
upvar $tokenCursorName tokenCursor
upvar $resultName result
while true {
lappend result [parseValue $tokens $nrTokens tokenCursor]
if {$tokenCursor == $nrTokens} {
unexpected $tokenCursor "END" "\",\"|\"\]\""
} else {
set token [lindex $tokens $tokenCursor]
incr tokenCursor
switch -exact $token {
"," {
# continue
}
"\]" {
break
}
default {
unexpected $tokenCursor $token "\",\"|\"\]\""
}
}
}
}
}
# Parse an array
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @return parsed array (Tcl list)
proc ::json::parseArray {tokens nrTokens tokenCursorName} {
upvar $tokenCursorName tokenCursor
if {$tokenCursor == $nrTokens} {
unexpected $tokenCursor "END" "ARRAY"
} else {
set result {}
set token [lindex $tokens $tokenCursor]
set leadingChar [string index $token 0]
if {$leadingChar eq "\]"} {
# empty array
incr tokenCursor
} else {
parseArrayElements $tokens $nrTokens tokenCursor result
}
return $result
}
}
# Parse a value
# @param tokens list of tokens
# @param nrTokens length of $tokens
# @param tokenCursorName name (in caller's context) of variable
# holding current position in $tokens
# @return parsed value (dict, list, string, number)
proc ::json::parseValue {tokens nrTokens tokenCursorName} {
upvar $tokenCursorName tokenCursor
if {$tokenCursor == $nrTokens} {
unexpected $tokenCursor "END" "VALUE"
} else {
set token [lindex $tokens $tokenCursor]
set tc $tokenCursor
incr tokenCursor
set leadingChar [string index $token 0]
switch -exact -- $leadingChar {
"\{" {
return [parseObject $tokens $nrTokens tokenCursor]
}
"\[" {
return [parseArray $tokens $nrTokens tokenCursor]
}
"\"" {
# quoted string
return [unquoteUnescapeString $tc $token]
}
"t" -
"f" -
"n" {
# bare word: true, false, null (return as is)
return $token
}
default {
# number?
if {[string is double -strict $token]} {
return $token
} else {
unexpected $tokenCursor $token "VALUE"
}
}
}
}
}

View File

@ -0,0 +1,92 @@
[comment {-*- tcl -*- doctools manpage}]
[vset PACKAGE_VERSION 1.0.3]
[manpage_begin json::write n [vset PACKAGE_VERSION]]
[keywords {data exchange}]
[keywords {exchange format}]
[keywords javascript]
[keywords json]
[copyright {2009-2013 Andreas Kupries <andreas_kupries@sourceforge.net>}]
[moddesc {JSON}]
[titledesc {JSON generation}]
[category {CGI programming}]
[require Tcl 8.5]
[require json::write [opt [vset PACKAGE_VERSION]]]
[description]
[para]
The [package json::write] package provides a simple Tcl-only library
for generation of text in the JSON [uri http://www.json.org/] data
exchange format as specified in
RFC 4627 [uri http://www.ietf.org/rfc/rfc4627.txt].
[section COMMANDS]
[list_begin definitions]
[call [cmd ::json::write] [method indented]]
This method returns the current state of the indentation setting.
[call [cmd ::json::write] [method indented] [arg flag]]
This and the method [method aligned] configure the layout of the JSON
generated by the package.
[para]
If this [arg flag] is set (default) the package will break the
generated JSON code across lines and indent it according to its inner
structure, with each key of an object on a separate line.
[para]
If this flag is not set, the whole JSON object will be written on a
single line, with minimum spacing between all elements.
[call [cmd ::json::write] [method aligned]]
This method returns the current state of the alignment setting.
[call [cmd ::json::write] [method aligned] [arg flag]]
This and the method [method indented] configure the layout of the JSON
generated by the package.
[para]
If this [arg flag] is set (default) the package ensures that the
values for the keys in an object are vertically aligned with each
other, for a nice table effect. To make this work this also implies
that [var indented] is set as well.
[para]
If this flag is not set, the output is formatted as per the value of
[var indented], without trying to align the values for object keys.
[call [cmd ::json::write] [method string] [arg s]]
This method takes the string [arg s] and returns it properly quoted
for JSON as its result.
[call [cmd ::json::write] [method array] [arg arg]...]
This method takes a series of JSON formatted arguments and returns
them as a properly formatted JSON array as its result.
[call [cmd ::json::write] [method object] [arg key] [arg value]...]
This method takes a series of key/value arguments, the values already
formatted for JSON, and returns them as a properly formatted JSON
object as its result, with the keys formatted as JSON strings.
[list_end]
[para]
[section RELATED]
To parse json, instead of writing it, see package [package json].
[vset CATEGORY json]
[include ../doctools2base/include/feedback.inc]
[manpage_end]

View File

@ -0,0 +1,42 @@
# -*- tcl -*- json_write.pcx
# Syntax of the commands provided by package json::write.
#
# For use by TclDevKit's static syntax checker (v4.1+).
# See http://www.activestate.com/solutions/tcl/
# See http://aspn.activestate.com/ASPN/docs/Tcl_Dev_Kit/4.0/Checker.html#pcx_api
# for the specification of the format of the code in this file.
#
package require pcx
pcx::register json::write
pcx::tcldep 1.0 needs tcl 8.5
namespace eval ::json::write {}
#pcx::message FOO {... text ...} type
#pcx::scan <VERSION> <NAME> <RULE>
pcx::check 1.0 std ::json::write {checkSimpleArgs 1 -1 {
{checkOption {
{indented {checkSimpleArgs 0 1 {
checkBoolean
}}}
{aligned {checkSimpleArgs 0 1 {
checkBoolean
}}}
{string {checkSimpleArgs 1 1 {
checkWord
}}}
{array {checkSimpleArgs 0 -1 {
checkWord
}}}
{object {checkSimpleArgsModNk 0 -1 2 0 {
checkWord
checkWord
}}}
} {}}
}}
# Initialization via pcx::init.
# Use a ::json::write::init procedure for non-standard initialization.
pcx::complete

View File

@ -0,0 +1,200 @@
# json_write.tcl --
#
# Commands for the generation of JSON (Java Script Object Notation).
#
# Copyright (c) 2009-2011 Andreas Kupries <andreas_kupries@sourceforge.net>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: json_write.tcl,v 1.2 2011/08/24 20:09:44 andreas_kupries Exp $
# ### ### ### ######### ######### #########
## Requisites
package require Tcl 8.5
namespace eval ::json::write {
namespace export \
string array object indented aligned
namespace ensemble create
}
# ### ### ### ######### ######### #########
## API.
proc ::json::write::indented {{bool {}}} {
variable indented
if {[llength [info level 0]] > 2} {
return -code error {wrong # args: should be "json::write indented ?bool?"}
} elseif {[llength [info level 0]] == 2} {
if {![::string is boolean -strict $bool]} {
return -code error "Expected boolean, got \"$bool\""
}
set indented $bool
if {!$indented} {
variable aligned 0
}
}
return $indented
}
proc ::json::write::aligned {{bool {}}} {
variable aligned
if {[llength [info level 0]] > 2} {
return -code error {wrong # args: should be "json::write aligned ?bool?"}
} elseif {[llength [info level 0]] == 2} {
if {![::string is boolean -strict $bool]} {
return -code error "Expected boolean, got \"$bool\""
}
set aligned $bool
if {$aligned} {
variable indented 1
}
}
return $aligned
}
proc ::json::write::string {s} {
variable quotes
return "\"[::string map $quotes $s]\""
}
proc ::json::write::array {args} {
# always compact form.
return "\[[join $args ,]\]"
}
proc ::json::write::object {args} {
# The dict in args maps string keys to json-formatted data. I.e.
# we have to quote the keys, but not the values, as the latter are
# already in the proper format.
variable aligned
variable indented
if {[llength $args] %2 == 1} {
return -code error {wrong # args, expected an even number of arguments}
}
set dict {}
foreach {k v} $args {
lappend dict [string $k] $v
}
if {$aligned} {
set max [MaxKeyLength $dict]
}
if {$indented} {
set content {}
foreach {k v} $dict {
if {$aligned} {
set k [AlignLeft $max $k]
}
if {[::string match *\n* $v]} {
# multi-line value
lappend content " $k : [Indent $v { } 1]"
} else {
# single line value.
lappend content " $k : $v"
}
}
if {[llength $content]} {
return "\{\n[join $content ,\n]\n\}"
} else {
return "\{\}"
}
} else {
# ultra compact form.
set tmp {}
foreach {k v} $dict {
lappend tmp "$k:$v"
}
return "\{[join $tmp ,]\}"
}
}
# ### ### ### ######### ######### #########
## Internals.
proc ::json::write::Indent {text prefix skip} {
set pfx ""
set result {}
foreach line [split $text \n] {
if {!$skip} { set pfx $prefix } else { incr skip -1 }
lappend result ${pfx}$line
}
return [join $result \n]
}
proc ::json::write::MaxKeyLength {dict} {
# Find the max length of the keys in the dictionary.
set lengths 0 ; # This will be the max if the dict is empty, and
# prevents the mathfunc from throwing errors for
# that case.
foreach str [dict keys $dict] {
lappend lengths [::string length $str]
}
return [tcl::mathfunc::max {*}$lengths]
}
proc ::json::write::AlignLeft {fieldlen str} {
return [format %-${fieldlen}s $str]
#return $str[::string repeat { } [expr {$fieldlen - [::string length $str]}]]
}
# ### ### ### ######### ######### #########
namespace eval ::json::write {
# Configuration of the layout to write.
# indented = boolean. objects are indented.
# aligned = boolean. object keys are aligned vertically.
# aligned => indented.
# Combinations of the format specific entries
# I A |
# - - + ---------------------
# 0 0 | Ultracompact (no whitespace, single line)
# 1 0 | Indented
# 0 1 | Not possible, per the implications above.
# 1 1 | Indented + vertically aligned keys
# - - + ---------------------
variable indented 1
variable aligned 1
variable quotes \
[list "\"" "\\\"" \\ \\\\ \b \\b \f \\f \n \\n \r \\r \t \\t \
\x00 \\u0000 \x01 \\u0001 \x02 \\u0002 \x03 \\u0003 \
\x04 \\u0004 \x05 \\u0005 \x06 \\u0006 \x07 \\u0007 \
\x0b \\u000b \x0e \\u000e \x0f \\u000f \x10 \\u0010 \
\x11 \\u0011 \x12 \\u0012 \x13 \\u0013 \x14 \\u0014 \
\x15 \\u0015 \x16 \\u0016 \x17 \\u0017 \x18 \\u0018 \
\x19 \\u0019 \x1a \\u001a \x1b \\u001b \x1c \\u001c \
\x1d \\u001d \x1e \\u001e \x1f \\u001f \x7f \\u007f \
\x80 \\u0080 \x81 \\u0081 \x82 \\u0082 \x83 \\u0083 \
\x84 \\u0084 \x85 \\u0085 \x86 \\u0086 \x87 \\u0087 \
\x88 \\u0088 \x89 \\u0089 \x8a \\u008a \x8b \\u008b \
\x8c \\u008c \x8d \\u008d \x8e \\u008e \x8f \\u008f \
\x90 \\u0090 \x91 \\u0091 \x92 \\u0092 \x93 \\u0093 \
\x94 \\u0094 \x95 \\u0095 \x96 \\u0096 \x97 \\u0097 \
\x98 \\u0098 \x99 \\u0099 \x9a \\u009a \x9b \\u009b \
\x9c \\u009c \x9d \\u009d \x9e \\u009e \x9f \\u009f ]
}
# ### ### ### ######### ######### #########
## Ready
package provide json::write 1.0.3
return

View File

@ -0,0 +1,218 @@
# json_write.test - Copyright (C) 2009 Andreas Kupries <andreas_kupries@sourceforge.net>
#
# Tests for the Tcllib json::write package
#
# -------------------------------------------------------------------------
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
# -------------------------------------------------------------------------
# RCS: @(#) $Id: json_write.test,v 1.1 2009/11/25 04:41:01 andreas_kupries Exp $
# -------------------------------------------------------------------------
source [file join \
[file dirname [file dirname [file join [pwd] [info script]]]] \
devtools testutilities.tcl]
testsNeedTcl 8.5
testsNeedTcltest 2.0
testing {
useLocal json_write.tcl json::write
}
# -------------------------------------------------------------------------
set data {grammar {
rules {
A {is {/ {t +} {t -}} mode value}
D {is {/ {t 0} {t 1} } mode value}
E {is {/ {x {t (} {n E} {t )}} {x {n F} {* {x {n M} {n F}}}}} mode value}
F {is {x {n T} {* {x {n A} {n T}}}} mode value}
M {is {/ {t *} {t /}} mode value}
N {is {x {? {n S}} {+ {n D}}} mode value}
S {is {/ {t +} {t -}} mode value}
T {is {n N} mode value}
}
start {n Expression}
}}
proc gen {serial} {
array set g $serial
array set g $g(grammar)
unset g(grammar)
# Assemble the rules ...
set rules {}
foreach {symbol def} $g(rules) {
lassign $def _ is _ mode
lappend rules $symbol \
[json::write object \
is [json::write string $is] \
mode [json::write string $mode]]
}
# Assemble the final result ...
return [json::write object grammar \
[json::write object \
rules [json::write object {*}$rules] \
start [json::write string $g(start)]]]
}
# -------------------------------------------------------------------------
# Tests
# -------------------------------------------------------------------------
test json-write-1.0 {default configuration} -body {
list [json::write indented] [json::write aligned]
} -result {1 1}
test json-write-1.1 {implied configurations} -body {
json::write indented 0
list [json::write indented] [json::write aligned]
} -result {0 0}
test json-write-1.2 {implied configurations} -body {
json::write indented 0
json::write aligned 0
json::write aligned 1
list [json::write indented] [json::write aligned]
} -result {1 1}
# -------------------------------------------------------------------------
test json-write-2.0 {argument errors} -body {
json::write indented X Y
} -returnCodes 1 -result {wrong # args: should be "json::write indented ?bool?"}
test json-write-2.1 {argument errors} -body {
json::write aligned X Y
} -returnCodes 1 -result {wrong # args: should be "json::write aligned ?bool?"}
test json-write-2.2 {argument errors} -body {
json::write string
} -returnCodes 1 -result {wrong # args: should be "json::write string s"}
test json-write-2.3 {argument errors} -body {
json::write string A B
} -returnCodes 1 -result {wrong # args: should be "json::write string s"}
test json-write-2.4 {argument errors} -body {
json::write object A
} -returnCodes 1 -result {wrong # args, expected an even number of arguments}
# -------------------------------------------------------------------------
test json-write-3.0 {indented, aligned} -setup {
json::write indented 1
json::write aligned 1
} -body {
gen $data
} -result {{
"grammar" : {
"rules" : {
"A" : {
"is" : "/ {t +} {t -}",
"mode" : "value"
},
"D" : {
"is" : "/ {t 0} {t 1} ",
"mode" : "value"
},
"E" : {
"is" : "/ {x {t (} {n E} {t )}} {x {n F} {* {x {n M} {n F}}}}",
"mode" : "value"
},
"F" : {
"is" : "x {n T} {* {x {n A} {n T}}}",
"mode" : "value"
},
"M" : {
"is" : "/ {t *} {t /}",
"mode" : "value"
},
"N" : {
"is" : "x {? {n S}} {+ {n D}}",
"mode" : "value"
},
"S" : {
"is" : "/ {t +} {t -}",
"mode" : "value"
},
"T" : {
"is" : "n N",
"mode" : "value"
}
},
"start" : "n Expression"
}
}}
test json-write-3.1 {indented, !aligned} -setup {
json::write indented 1
json::write aligned 0
} -body {
gen $data
} -result {{
"grammar" : {
"rules" : {
"A" : {
"is" : "/ {t +} {t -}",
"mode" : "value"
},
"D" : {
"is" : "/ {t 0} {t 1} ",
"mode" : "value"
},
"E" : {
"is" : "/ {x {t (} {n E} {t )}} {x {n F} {* {x {n M} {n F}}}}",
"mode" : "value"
},
"F" : {
"is" : "x {n T} {* {x {n A} {n T}}}",
"mode" : "value"
},
"M" : {
"is" : "/ {t *} {t /}",
"mode" : "value"
},
"N" : {
"is" : "x {? {n S}} {+ {n D}}",
"mode" : "value"
},
"S" : {
"is" : "/ {t +} {t -}",
"mode" : "value"
},
"T" : {
"is" : "n N",
"mode" : "value"
}
},
"start" : "n Expression"
}
}}
test json-write-3.1 {!indented, !aligned} -setup {
json::write indented 0
json::write aligned 0
} -body {
gen $data
} -result {{"grammar":{"rules":{"A":{"is":"/ {t +} {t -}","mode":"value"},"D":{"is":"/ {t 0} {t 1} ","mode":"value"},"E":{"is":"/ {x {t (} {n E} {t )}} {x {n F} {* {x {n M} {n F}}}}","mode":"value"},"F":{"is":"x {n T} {* {x {n A} {n T}}}","mode":"value"},"M":{"is":"/ {t *} {t /}","mode":"value"},"N":{"is":"x {? {n S}} {+ {n D}}","mode":"value"},"S":{"is":"/ {t +} {t -}","mode":"value"},"T":{"is":"n N","mode":"value"}},"start":"n Expression"}}}
# -------------------------------------------------------------------------
test json-write-4.0 {string quoting} -body {
json::write string "a\"b\\c\bd\fe\nf\rg\th\0i\1j\2k\3l\177m"
} -result "\"a\\\"b\\\\c\\bd\\fe\\nf\\rg\\th\\u0000i\\u0001j\\u0002k\\u0003l\\u007fm\""
# -------------------------------------------------------------------------
unset data
rename gen {}
testsuiteCleanup
# Local Variables:
# mode: tcl
# indent-tabs-mode: nil
# End:

View File

@ -0,0 +1,171 @@
# jsonc.tcl --
#
# Implementation of a JSON parser in C.
# Binding to a yacc/bison parser by Mikhail.
#
# Copyright (c) 2013,2015 - critcl wrapper - Andreas Kupries <andreas_kupries@users.sourceforge.net>
# Copyright (c) 2013 - C binding - mi+tcl.tk-2013@aldan.algebra.com
package require critcl
# @sak notprovided jsonc
package provide jsonc 1.1.2
package require Tcl 8.4
#critcl::cheaders -g
#critcl::debug memory symbols
critcl::cheaders -Ic c/*.h
critcl::csources c/*.c
# # ## ### Import base declarations, forwards ### ## # #
critcl::ccode {
#include <json_y.h>
}
# # ## ### Main Conversion ### ## # #
namespace eval ::json {
critcl::ccommand json2dict_critcl {dummy I objc objv} {
struct context context = { NULL };
if (objc != 2) {
Tcl_WrongNumArgs(I, 1, objv, "json");
return TCL_ERROR;
}
context.text = Tcl_GetStringFromObj(objv[1], &context.remaining);
context.I = I;
context.has_error = 0;
context.result = TCL_ERROR;
jsonparse (&context);
return context.result;
}
# Issue with critcl 2 used here. Cannot use '-', incomplete distinction of C and Tcl names.
# The json.tcl file making use of this code has a wrapper fixing the issue.
critcl::ccommand many_json2dict_critcl {dummy I objc objv} {
struct context context = { NULL };
int max;
int found;
Tcl_Obj* result = Tcl_NewListObj (0, NULL);
if ((objc < 2) || (objc > 3)) {
Tcl_WrongNumArgs(I, 1, objv, "jsonText ?max?");
return TCL_ERROR;
}
if (objc == 3) {
if (Tcl_GetIntFromObj(I, objv[2], &max) != TCL_OK) {
return TCL_ERROR;
}
if (max <= 0) {
Tcl_AppendResult (I, "Bad limit ",
Tcl_GetString (objv[2]),
" of json entities to extract.",
NULL);
Tcl_SetErrorCode (I, "JSON", "BAD-LIMIT", NULL);
return TCL_ERROR;
}
} else {
max = -1;
}
context.text = Tcl_GetStringFromObj(objv[1], &context.remaining);
context.I = I;
context.has_error = 0;
found = 0;
/* Iterate over the input until
* - we have gotten all requested values.
* - we have run out of input
* - we have run into an error
*/
while ((max < 0) || max) {
context.result = TCL_ERROR;
jsonparse (&context);
/* parse error, abort */
if (context.result != TCL_OK) {
Tcl_DecrRefCount (result);
return TCL_ERROR;
}
/* Proper value extracted, extend result */
found ++;
Tcl_ListObjAppendElement(I, result,
Tcl_GetObjResult (I));
/* Count down on the number of still missing
* values, if not asking for all (-1)
*/
if (max > 0) max --;
/* Jump over trailing whitespace for proper end-detection */
jsonskip (&context);
/* Abort if we have consumed all input */
if (!context.remaining) break;
/* Clear scratch pad before continuing */
context.obj = NULL;
}
/* While all parses were ok we reached end of
* input without getting all requested values,
* this is an error
*/
if (max > 0) {
char buf [30];
sprintf (buf, "%d", found);
Tcl_ResetResult (I);
Tcl_AppendResult (I, "Bad limit ",
Tcl_GetString (objv[2]),
" of json entities to extract, found only ",
buf,
".",
NULL);
Tcl_SetErrorCode (I, "JSON", "BAD-LIMIT", "TOO", "LARGE", NULL);
Tcl_DecrRefCount (result);
return TCL_ERROR;
}
/* We are good and done */
Tcl_SetObjResult(I, result);
return TCL_OK;
}
if 0 {critcl::ccommand validate_critcl {dummy I objc objv} {
struct context context = { NULL };
if (objc != 2) {
Tcl_WrongNumArgs(I, 1, objv, "jsonText");
return TCL_ERROR;
}
context.text = Tcl_GetStringFromObj(objv[1], &context.remaining);
context.I = I;
context.result = TCL_ERROR;
/* Iterate over the input until we have run
* out of text, or encountered an error. We
* use only the lexer here, and told it to not
* create superfluous token values.
*/
while (context.remaining) {
if (jsonlex (&context) == -1) {
Tcl_SetObjResult(I, Tcl_NewBooleanObj (0));
return TCL_OK;
}
}
/* We are good and done */
Tcl_SetObjResult(I, Tcl_NewBooleanObj (1));
return TCL_OK;
}}
}

View File

@ -0,0 +1,7 @@
# Tcl package index file, version 1.1
if {![package vsatisfies [package provide Tcl] 8.4]} {return}
package ifneeded json 1.3.4 [list source [file join $dir json.tcl]]
if {![package vsatisfies [package provide Tcl] 8.5]} {return}
package ifneeded json::write 1.0.3 [list source [file join $dir json_write.tcl]]

View File

@ -0,0 +1 @@
{precision zip Latitude 37.7668 Longitude -122.3959 Address {} City {SAN FRANCISCO} State CA Zip 94107 Country US} {precision zip Latitude 37.371991 Longitude -122.026020 Address {} City SUNNYVALE State CA Zip 94085 Country US}

View File

@ -0,0 +1 @@
list dict

View File

@ -0,0 +1 @@
glossary {title {example glossary} mixlist {{a "" str} -0.09 null {} {member true}} GlossDiv {title S GlossList {{ID SGML GlossTerm {Standard \" Language} Acronym SGML\\ Abbrev {ISO 8879:1986} GlossDef {A meta-markup language, used ...} GlossSeeAlso {GML XML markup}}}}}

View File

@ -0,0 +1 @@
dict * {dict GlossDiv {dict GlossList {list dict}}}

View File

@ -0,0 +1 @@
menu {id file value File: unival @@@: popup {menuitem {{value Open onclick OpenDoc()} {value Close onclick CloseDoc()}}}}

View File

@ -0,0 +1 @@
dict * {dict popup {dict * {list dict}}}

View File

@ -0,0 +1 @@
menu {header Viewer items {{id Open} {id OpenNew label {Open New}} null {id ZoomIn label {Zoom In}} {id ZoomOut label {Zoom Out}} null {id Help} {id About label {About Viewer...}}}}

View File

@ -0,0 +1 @@
dict * {dict items {list 0 dict 1 dict 3 dict 4 dict 6 dict 7 dict}}

View File

@ -0,0 +1,157 @@
#use fileutil/fileutil.tcl fileutil
catch {unset JSON}
catch {unset TCL}
catch {unset DICTSORT}
proc dictsort3 {spec data} {
while [llength $spec] {
set type [lindex $spec 0]
set spec [lrange $spec 1 end]
switch -- $type {
dict {
lappend spec * string
set json {}
foreach {key} [lsort [dict keys $data]] {
set val [dict get $data $key]
foreach {keymatch valtype} $spec {
if {[string match $keymatch $key]} {
lappend json $key [dictsort3 $valtype $val]
break
}
}
}
return $json
}
list {
lappend spec * string
set json {}
set idx 0
foreach {val} $data {
foreach {keymatch valtype} $spec {
if {$idx == $keymatch || $keymatch eq "*"} {
lappend json [dictsort3 $valtype $val]
break
}
}
incr idx
}
return $json
}
string {
return $data
}
default {
error "Invalid type"
}
}
}
}
foreach f [TestFilesGlob tests/*.json] {
set name [file rootname [file tail $f]]
set JSON($name) [tcltest::viewFile $f]
}
foreach f [TestFilesGlob tests/*.result] {
set name [file rootname [file tail $f]]
set TCL($name) [tcltest::viewFile $f]
}
foreach f [TestFilesGlob tests/*.sort] {
set name [file rootname [file tail $f]]
set DICTSORT($name) [tcltest::viewFile $f]
}
# Postprocessing result of one test case, insert proper expected unicodepoint
set TCL(menu) [string map [list @@@ \u6021] $TCL(menu)]
set JSON(emptyList) {[]}
set TCL(emptyList) {}
set JSON(emptyList2) {{"menu": []}}
set TCL(emptyList2) {menu {}}
set JSON(emptyList3) {["menu", []]}
set TCL(emptyList3) {menu {}}
set JSON(emptyList4) {[[]]}
set TCL(emptyList4) {{}}
set JSON(escapes) {"\t\r\n\f\b\/\\\""}
set TCL(escapes) "\t\r\n\f\b/\\\""
foreach {label json tcl} {
fp1.1 1.1 1.1
fp1. 1. 1.
fp.1 .1 .1
fp0.1 0.1 0.1
fp1 1 1
} {
set JSON($label) $json
set TCL($label) $tcl
}
foreach f [TestFilesGlob tests/*.fail] {
set name [file rootname [file tail $f]]
set FAIL($name) [tcltest::viewFile $f]
}
foreach f [TestFilesGlob tests/*.err] {
set name [file rootname [file tail $f]]
set ERR($name) [tcltest::viewFile $f]
}
## Tcl has strict escape checking.
## C uses Tcl_UtfBacklash, and allows lots of irregular escapes.
set FAIL(escape1) {"\%"}
set ERR(escape1-tcl) {unexpected token ""\%"" at position 0; expecting STRING}
set ERR(escape1-critcl) {bad escape 3 bytes before end, around ``%''}
set FAIL(escape2) {"\."}
set ERR(escape2-tcl) {unexpected token ""\."" at position 0; expecting STRING}
set ERR(escape2-critcl) {bad escape 3 bytes before end, around ``.''}
set FAIL(escape3) {["\%"]}
set ERR(escape3-tcl) {unexpected token ""\%"" at position 1; expecting STRING}
set ERR(escape3-critcl) {bad escape 4 bytes before end, around ``%''}
set FAIL(escape4) {["\."]}
set ERR(escape4-tcl) {unexpected token ""\."" at position 1; expecting STRING}
set ERR(escape4-critcl) {bad escape 4 bytes before end, around ``.''}
set FAIL(escape5) {{"a":"\%"}}
set ERR(escape5-tcl) {unexpected token ""\%"" at position 3; expecting STRING}
set ERR(escape5-critcl) {bad escape 4 bytes before end, around ``%''}
set FAIL(escape6) {{"a":"\."}}
set ERR(escape6-tcl) {unexpected token ""\."" at position 3; expecting STRING}
set ERR(escape6-critcl) {bad escape 4 bytes before end, around ``.''}
proc resultfor {name} {
global TCL
transform $TCL($name) $name
}
proc transform {res name} {
global DICTSORT
if {[info exists DICTSORT($name)]} {
return [dictsort3 $DICTSORT($name) $res]
} else {
return $res
}
}
proc transform* {res args} {
set t {}
foreach r $res n $args {
lappend t [transform $r $n]
}
return $t
}

View File

@ -0,0 +1 @@
widget {debug on window {title {Sample Widget} name main_window width 500 height 500} text {data {Click Here} size 36 style bold name null hOffset 250 vOffset 100 alignment center onMouseUp {sun1.opacity = (sun1.opacity / 100) * 90;}}}

View File

@ -0,0 +1 @@
dict * {dict text dict window dict}

32
cpp_to_py/common/lib/sdc/mask.h Executable file
View File

@ -0,0 +1,32 @@
#pragma once
#include "common/lib/Helper.h"
namespace gt::sdc {
struct TimingMask {
inline static constexpr auto min_mask = 0x01;
inline static constexpr auto max_mask = 0x02;
inline static constexpr auto rise_mask = 0x04;
inline static constexpr auto fall_mask = 0x08;
constexpr TimingMask(std::optional<std::byte> min,
std::optional<std::byte> max,
std::optional<std::byte> rise,
std::optional<std::byte> fall) {
if (min) mask |= min_mask;
if (max) mask |= max_mask;
if (!min && !max) mask |= (min_mask | max_mask);
if (rise) mask |= rise_mask;
if (fall) mask |= fall_mask;
if (!rise && !fall) mask |= (rise_mask | fall_mask);
}
int mask{0};
constexpr bool operator|(Split el) const { return (el == MIN) ? mask & min_mask : mask & max_mask; }
constexpr bool operator|(Tran rf) const { return (rf == RISE) ? mask & rise_mask : mask & fall_mask; }
};
}; // namespace gt::sdc

View File

@ -0,0 +1,29 @@
#include "object.h"
namespace gt::sdc {
Object parse_port(const std::string& line) {
if (line.find("all_inputs") != std::string::npos) {
return AllInputs{};
}
if (line.find("all_outputs") != std::string::npos) {
return AllOutputs{};
}
const static std::regex ws_re("\\s+|\\n+|\\t+");
auto itr = std::sregex_token_iterator(line.begin(), line.end(), ws_re, -1);
auto end = std::sregex_token_iterator();
// auto num = std::distance(itr, end);
GetPorts get_ports;
for (; itr != end; ++itr) {
get_ports.ports.push_back(itr->str());
}
return get_ports;
}
}; // namespace gt::sdc

View File

@ -0,0 +1,61 @@
#pragma once
#include "tokenizer.h"
namespace gt::sdc {
struct CurrentDesign {};
struct AllClocks {};
struct GetClocks {
std::vector<std::string> clocks;
};
struct AllInputs {};
struct AllOutputs {};
struct GetPorts {
std::vector<std::string> ports;
};
struct GetCells {
std::vector<std::string> cells;
};
struct GetPins {
std::vector<std::string> pins;
};
struct GetNets {
std::vector<std::string> nets;
};
struct GetLibs {
std::vector<std::string> libs;
};
struct GetLibCells {};
struct GetLibPins {};
struct AllRegisters {};
using Object = std::variant<CurrentDesign,
GetClocks,
AllClocks,
GetPorts,
AllInputs,
AllOutputs,
GetPins,
GetCells,
GetNets,
GetLibs,
GetLibCells,
GetLibPins,
AllRegisters>;
Object parse_port(const std::string&);
}; // namespace gt::sdc

View File

@ -0,0 +1,319 @@
#include "sdc.h"
namespace gt::sdc {
std::unique_ptr<char*, std::function<void(char**)>> c_args(const std::vector<std::string>& args) {
std::unique_ptr<char*, std::function<void(char**)>> ptr(new char*[args.size() + 1], [n = args.size()](char** ptr) {
for (size_t i = 0; i <= n; ++i) {
delete[] ptr[i];
}
delete[] ptr;
});
for (size_t i = 0; i < args.size(); ++i) {
ptr.get()[i] = new char[args[i].length() + 1];
std::strcpy(ptr.get()[i], args[i].c_str());
}
ptr.get()[args.size()] = nullptr;
return ptr;
}
void SDC::read(const std::filesystem::path& path) {
logger.infoif(!std::filesystem::exists(path), "sdc file %s doesn't exist", path.c_str());
logger.info("loading sdc %s", path.c_str());
auto sdc_path = std::filesystem::absolute(path);
auto sdc_json = sdc_path;
sdc_json.replace_extension(".json");
if (auto cpid = ::fork(); cpid == -1) {
logger.error("can't fork sdc reader");
return;
}
// child
else if (cpid == 0) {
#define TCLSH_PATH "/usr/bin/tclsh"
auto sdc_home = std::filesystem::current_path() / "cpp_to_py" / "common" / "lib" / "sdc";
if (::chdir(sdc_home.c_str()) == -1) {
logger.error("can't enter into %s", sdc_home.c_str());
::exit(EXIT_FAILURE);
}
std::vector<std::string> args{TCLSH_PATH, "sdc.tcl", sdc_path.c_str(), sdc_json.c_str()};
::execvp(args[0].c_str(), c_args(args).get());
logger.error("exec failed: %s", strerror(errno));
::exit(EXIT_FAILURE);
logger.warning("sdc reader not implemented yet");
}
// parent
else {
int s;
do {
int w = ::waitpid(cpid, &s, WUNTRACED | WCONTINUED);
logger.errorif(w == -1, "failed to reap sdc reader");
if (WIFEXITED(s)) {
logger.errorif(WEXITSTATUS(s) != EXIT_SUCCESS, "sdc reader exited with failure");
} else if (WIFSIGNALED(s)) {
logger.error("sdc reader killed by signal %s", WTERMSIG(s));
return;
} else if (WIFSTOPPED(s)) {
logger.info("sdc reader stopped");
} else if (WIFCONTINUED(s)) {
logger.info("sdc reader continued");
}
} while (!WIFEXITED(s) && !WIFSIGNALED(s));
std::ifstream ifs(sdc_json);
logger.infoif(!ifs, "failed to open %s", sdc_json);
Json json;
ifs >> json;
for (const auto& j : json) {
if (const auto& c = j["command"]; c == "set_input_delay") {
commands.emplace_back(std::in_place_type_t<SetInputDelay>{}, j);
} else if (c == "set_driving_cell") {
commands.emplace_back(std::in_place_type_t<SetDrivingCell>{}, j);
} else if (c == "set_input_transition") {
commands.emplace_back(std::in_place_type_t<SetInputTransition>{}, j);
} else if (c == "set_output_delay") {
commands.emplace_back(std::in_place_type_t<SetOutputDelay>{}, j);
} else if (c == "set_load") {
commands.emplace_back(std::in_place_type_t<SetLoad>{}, j);
} else if (c == "create_clock") {
commands.emplace_back(std::in_place_type_t<CreateClock>{}, j);
} else if (c == "set_units") {
commands.emplace_back(std::in_place_type_t<SetUnits>{}, j);
} else {
logger.error("sdc command %s not supported yet", c);
}
}
try {
std::filesystem::remove(sdc_json);
} catch (const std::exception& e) {
logger.warning("can't remove %s: %s", sdc_json, e.what());
}
}
}
// Constructor
SetUnits::SetUnits(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
auto& key = itr.key();
if (key == "-time") {
time = unquoted(itr.value());
} else if (key == "-capacitance") {
capacitance = unquoted(itr.value());
} else if (key == "-voltage") {
voltage = unquoted(itr.value());
} else if (key == "-current") {
current = unquoted(itr.value());
} else if (key == "-resistance") {
resistance = unquoted(itr.value());
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetInputDelay::SetInputDelay(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (auto& key = itr.key(); key == "-clock") {
clock = itr.value();
} else if (key == "-clock_fall") {
clock_fall.emplace();
} else if (key == "-level_sensitive") {
level_sensitive.emplace();
} else if (key == "-rise") {
rise.emplace();
} else if (key == "-fall") {
fall.emplace();
} else if (key == "-min") {
min.emplace();
} else if (key == "-max") {
max.emplace();
} else if (key == "-add_delay") {
add_delay.emplace();
} else if (key == "-network_latency_included") {
network_latency_included.emplace();
} else if (key == "-source_latency_included") {
source_latency_included.emplace();
} else if (key == "delay_value") {
delay_value = std::stof(unquoted(itr.value()));
} else if (key == "port_pin_list") {
port_pin_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetDrivingCell::SetDrivingCell(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (const auto& key = itr.key(); key == "-clock") {
clock = itr.value();
} else if (key == "-clock_fall") {
clock_fall.emplace();
} else if (key == "-lib_cell") {
// TODO: do nothing
} else if (key == "-pin") {
// TODO: do nothing
} else if (key == "-min") {
min.emplace();
} else if (key == "-max") {
max.emplace();
} else if (key == "-input_transition_fall") {
fall.emplace();
transitions[1] = std::stof(unquoted(itr.value()));
} else if (key == "-input_transition_rise") {
rise.emplace();
transitions[0] = std::stof(unquoted(itr.value()));
} else if (key == "port_list") {
port_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetInputTransition::SetInputTransition(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (const auto& key = itr.key(); key == "-clock") {
clock = itr.value();
} else if (key == "-clock_fall") {
clock_fall.emplace();
} else if (key == "-rise") {
rise.emplace();
} else if (key == "-fall") {
fall.emplace();
} else if (key == "-min") {
min.emplace();
} else if (key == "-max") {
max.emplace();
} else if (key == "transition") {
transition = std::stof(unquoted(itr.value()));
} else if (key == "port_list") {
port_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetOutputDelay::SetOutputDelay(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (auto& key = itr.key(); key == "-clock") {
clock = itr.value();
} else if (key == "-clock_fall") {
clock_fall.emplace();
} else if (key == "-level_sensitive") {
level_sensitive.emplace();
} else if (key == "-rise") {
rise.emplace();
} else if (key == "-fall") {
fall.emplace();
} else if (key == "-min") {
min.emplace();
} else if (key == "-max") {
max.emplace();
} else if (key == "-add_delay") {
add_delay.emplace();
} else if (key == "-network_latency_included") {
network_latency_included.emplace();
} else if (key == "-source_latency_included") {
source_latency_included.emplace();
} else if (key == "delay_value") {
delay_value = std::stof(unquoted(itr.value()));
} else if (key == "port_pin_list") {
port_pin_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetLoad::SetLoad(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (const auto& key = itr.key(); key == "-min") {
min.emplace();
} else if (key == "-max") {
max.emplace();
} else if (key == "-subtract_pin_load") {
subtract_pin_load.emplace();
} else if (key == "-pin_load") {
pin_load.emplace();
} else if (key == "-wire_load") {
wire_load.emplace();
} else if (key == "objects") {
objects = parse_port(unquoted(itr.value()));
} else if (key == "value") {
value = std::stof(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
CreateClock::CreateClock(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (auto& key = itr.key(); key == "-period") {
period = std::stof(unquoted(itr.value()));
} else if (key == "-add") {
add.emplace();
} else if (key == "-comment") {
comment = itr.value();
} else if (key == "-name") {
name = itr.value();
} else if (key == "-waveform") {
// TODO
} else if (key == "port_pin_list") {
port_pin_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
// Constructor
SetClockUncertainty::SetClockUncertainty(const Json& json) {
for (auto itr = json.begin(); itr != json.end(); ++itr) {
if (auto& key = itr.key(); key == "uncertainty") {
} else if (key == "object_list") {
object_list = parse_port(unquoted(itr.value()));
} else if (key == "command") {
logger.errorif(itr.value() != command, "wrong command field: %s", itr.value());
} else {
logger.error("%s: %s not supported", command, std::quoted(key));
}
}
}
}; // namespace gt::sdc

View File

@ -0,0 +1,148 @@
#pragma once
#include "common/lib/sdc/json.hpp"
#include "common/lib/tokenizer.h"
#include "mask.h"
#include "object.h"
namespace gt::sdc {
using Json = nlohmann::json;
std::unique_ptr<char*, std::function<void(char**)>> c_args(const std::vector<std::string>&);
// Set a fixed transition on input or inout ports
struct SetUnits {
inline static constexpr auto command = "set_units";
std::optional<std::string> time;
std::optional<std::string> capacitance;
std::optional<std::string> resistance;
std::optional<std::string> current;
std::optional<std::string> voltage;
SetUnits() = default;
SetUnits(const Json&);
};
struct SetInputDelay {
inline static constexpr auto command = "set_input_delay";
std::string clock;
std::optional<std::byte> clock_fall;
std::optional<std::byte> level_sensitive;
std::optional<std::byte> add_delay;
std::optional<std::byte> network_latency_included;
std::optional<std::byte> source_latency_included;
std::optional<std::byte> min;
std::optional<std::byte> max;
std::optional<std::byte> rise;
std::optional<std::byte> fall;
std::optional<float> delay_value;
std::optional<Object> port_pin_list;
SetInputDelay() = default;
SetInputDelay(const Json&);
};
struct SetDrivingCell {
inline static constexpr auto command = "set_driving_cell";
std::string clock;
std::optional<std::byte> min;
std::optional<std::byte> max;
std::optional<std::byte> rise;
std::optional<std::byte> fall;
std::optional<std::byte> clock_fall;
std::array<std::optional<float>, 2> transitions;
std::optional<Object> port_list;
SetDrivingCell() = default;
SetDrivingCell(const Json&);
};
// Set a fixed transition on input or inout ports
struct SetInputTransition {
inline static constexpr auto command = "set_input_transition";
std::string clock;
std::optional<std::byte> min;
std::optional<std::byte> max;
std::optional<std::byte> rise;
std::optional<std::byte> fall;
std::optional<std::byte> clock_fall;
std::optional<float> transition;
std::optional<Object> port_list;
SetInputTransition() = default;
SetInputTransition(const Json&);
};
struct SetOutputDelay {
inline static constexpr auto command = "set_output_delay";
std::string clock;
std::optional<std::byte> clock_fall;
std::optional<std::byte> level_sensitive;
std::optional<std::byte> rise;
std::optional<std::byte> fall;
std::optional<std::byte> max;
std::optional<std::byte> min;
std::optional<std::byte> add_delay;
std::optional<std::byte> network_latency_included;
std::optional<std::byte> source_latency_included;
std::optional<float> delay_value;
std::optional<Object> port_pin_list;
SetOutputDelay() = default;
SetOutputDelay(const Json&);
};
struct SetLoad {
inline static constexpr auto command = "set_load";
std::optional<std::byte> min;
std::optional<std::byte> max;
std::optional<std::byte> subtract_pin_load;
std::optional<std::byte> pin_load;
std::optional<std::byte> wire_load;
std::optional<float> value;
std::optional<Object> objects;
SetLoad() = default;
SetLoad(const Json&);
};
struct CreateClock {
inline static constexpr auto command = "create_clock";
std::optional<float> period;
std::optional<std::byte> add;
std::string name;
std::string comment;
std::optional<std::array<float, MAX_TRAN>> waveform;
std::optional<Object> port_pin_list;
CreateClock() = default;
CreateClock(const Json&);
};
struct SetClockUncertainty {
inline static constexpr auto command = "set_clock_uncertainty";
std::optional<float> uncertainty;
std::optional<Object> object_list;
SetClockUncertainty() = default;
SetClockUncertainty(const Json&);
};
using Command = std::variant<SetUnits, SetInputDelay, SetDrivingCell, SetInputTransition, SetOutputDelay, SetLoad, CreateClock>;
struct SDC {
std::vector<Command> commands;
void read(const std::filesystem::path&);
};
}; // namespace gt::sdc

View File

@ -0,0 +1,93 @@
#!/usr/bin/env tclsh
source [file join [file dirname [info script]] sdcparsercore.tcl]
lappend auto_path [file join json]
package require json
package require json::write
# disable json indentation
json::write indented false
# environment variable
#global env
#puts $env(PATH)
# Namespace gt ----------------------------------------------------------------
namespace eval gt {
# sdcjson
variable sdc_json [list]
# callback procedure
proc sdc_callback {cmd parsing_result} {
variable sdc_json
# put reference to data structure after parsing
upvar $parsing_result res
# Switch on cmd type
switch -- $cmd {
create_clock -
set_input_delay -
set_input_transition -
set_output_delay -
set_driving_cell -
set_clock_uncertainty -
set_load -
set_units {
set cmd_body [list "command" [json::write string $cmd]]
foreach {key value} [array get res] {
lappend cmd_body $key [json::write string $value]
}
#puts stdout [json::write object {*}$cmd_body]
lappend sdc_json [json::write object {*}$cmd_body]
return ""
}
get_clocks -
get_ports {
return [join $res(patterns) " "]
}
all_inputs {
return "all_inputs"
}
all_clocks {
return "all_clocks"
}
all_outputs {
return "all_outputs"
}
default {
puts stderr "$cmd not supported yet"
}
}
}
}
# end of gt namespace ---------------------------------------------------------
# main program
sdc::register_callback gt::sdc_callback
sdc::parse_file [lindex $argv 0]
set json_output [open [lindex $argv 1] w]
#puts stdout [json::write array {*}$gt::sdc_json]
puts -nonewline $json_output [json::write array {*}$gt::sdc_json]
close $json_output

View File

@ -0,0 +1,363 @@
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2000 (c) Synopsys.
#
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.1
#
# Project : SDC-parser
#
# Authors : A.Gratchev
# Intrinsix Corp.
# anso@intrinsix.com
#
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
}
# !(param(-level_sensitive) && param(-edge_triggered))
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
} {param(-period)}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
} {(param(patterns) && !param(-of_objects)) \
|| (param(-of_objects) && !param(patterns) && !param(-hierarchical))}
declare get_clocks {
{patterns List }
} {param(patterns)}
declare get_lib_cells {
{patterns List }
} {param(patterns)}
declare get_lib_pins {
{patterns List }
} {param(patterns)}
declare get_libs {
{patterns List }
} {param(patterns)}
declare get_nets {
{patterns List }
{-hierarchical Flag }
} {param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
} {param(patterns)}
declare get_ports {
{patterns List }
} {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(port_pin_list)}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list)}
# && !(param(-rise) && param(-fall))
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && !(param(object_list) && (param(-from) || param(-to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list)}
# && !(param(-to) ^ param(-from))
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
} {param(port_list)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(-from) || param(-to) || param(-through)}
# && !(param(-rise) && param(-fall)) ;# && !(param(-setup) && param(-hold))
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list)}
# && !((param(-clock_fall) || param(-level_sensitive)) && !param(clock_name))
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value)}
# && !(param(-rise) && param(-fall))
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value)}
# && !(param(-rise) && param(-fall))
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list)}
# && !((param(-clock_fall) || param(-level_sensitive)) && !param(clock_name))
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{-group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,386 @@
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2000 (c) Synopsys.
#
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.2
#
# Project : SDC-parser
#
# Authors : A.Gratchev
# A.Sokhatski
# Intrinsix Corp.
# anso@intrinsix.com
#
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns))}
# && !param(-hierarchical))}
declare get_clocks {
{patterns List }
} {param(patterns)}
declare get_lib_cells {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{patterns List }
} {param(patterns)}
declare get_nets {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_ports {
{patterns List }
} {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && !(param(object_list) && (param(-from) || param(-to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
} {param(port_list)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{-group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,397 @@
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2001 (c) Synopsys.
#
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.3
#
# Project : SDC-parser
#
# Authors : Ibna Faruque, A.Gratchev,A.Sokhatski
# Contributors : Specklin Benoit,Matthew Liberty
# Updated : Oct 29, 2001
# Bug Fixes : set_driving_cell, set_case_analysis, set_clock_uncertainty
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{port_pin_list List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns))}
# && !param(-hierarchical))}
declare get_clocks {
{patterns List }
} {param(patterns)}
declare get_lib_cells {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{patterns List }
} {param(patterns)}
declare get_nets {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_ports {
{patterns List }
} {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ (param(-from) && param(-to))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,444 @@
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2003 (c) Synopsys.
#
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.3
#
# Project : SDC-parser
#
# Authors : Ibna Faruque, A.Gratchev,A.Sokhatski
# Contributors : Specklin Benoit,Matthew Liberty
# Updated : Jan 7, 2003
# Bug Fixes : set_driving_cell, set_case_analysis, set_clock_uncertainty
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{port_pin_list List }
{-add Flag }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns))}
# && !param(-hierarchical))}
declare get_clocks {
{patterns List }
} {param(patterns)}
declare get_lib_cells {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{patterns List }
} {param(patterns)}
declare get_nets {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_ports {
{patterns List }
} {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ (param(-from) && param(-to))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,553 @@
################################################################################
#
# Copyright 2005 (c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.5
#
# : Ibna Faruque
# Updated : April 5, 2005
# Bug Fixes :
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{port_pin_list List }
{-add Flag }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
#} {param(patterns)}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
#} {param(patterns)}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,572 @@
################################################################################
#
# Copyright 2006 (c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.5
#
# : Ibna Faruque
# Updated : june 12, 2006
# Bug Fixes :
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare create_clock {
{-period Float {$par>=0}}
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{port_pin_list List }
{-add Flag }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
#} {param(patterns)}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
#} {param(patterns)}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1}}
{-rise Flag }
{-fall Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare create_voltage_area {
{-name String {1} }
{-coordinate List }
{-guard_band_x List }
{-guard_band_y List }
{cell_list List {1} }
} {param(-name) && {param(cell_list)}}
declare set_level_shifter_strategy {
{-rule Enum {all low_to_high high_to_low}}
} {param(-rule)}
declare set_level_shifter_threshold {
{-voltage Float {1} }
{-percent Float {1} }
} {param(-voltage)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,707 @@
################################################################################
#
# Copyright 2007 (c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.7
#
# Update By : Ibna Faruque
# Updated On : March, 2007
# Bug Fixes :
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
#added on SDC1.7
declare all_registers {
{-clock List }
{-rise_clock List }
{-fall_clock List }
{-no_hierarchy Flag }
{-cells Flag }
{-data_pins Flag }
{-clock_pins Flag }
{-slave_clock_pins Flag }
{-async_pins Flag }
{-output_pins Flag }
{-level_sensitive Flag }
{-edge_triggered Flag }
{-master_slave Flag }
}
declare create_clock {
{-period Float {$par>=0} }
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{-combinational Flag }
{port_pin_list List }
{-add Flag }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
# added SDC1.7
declare group_path {
{-name String }
{-default Flag }
{-weight Float {$par>=0.0 && $par <=100.0} }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-rise_through List {dup} }
{-fall_through List {dup} }
} {((param(-name) && !param(-default)) || \
(param(-default) && !param(-name)) || !param(-name) && \
(param(-from) ^ param(-rise_from) ^ param(-fall_from)))}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
# sdc1.7 updte
declare set_units {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
# set_unit synonym for set_units
declare set_unit {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
# sdc1.7 command
declare set_clock_groups {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# set_clock_group synonym for set_clock_groups
declare set_clock_group {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# sdc1.7 command
declare set_clock_sense {
{-clocks List }
{-positive Flag }
{-negative Flag }
{-stop_propagation Flag }
{-pulse Enum {rise_triggered_high_pulse rise_triggered_low_pulse \
fall_triggered_high_pulse fall_triggered_low_pulse} }
{pins List }
} {(param(-positive) ^ param(-negative) ^ param(-stop_propagation) ^ param(-pulse)) }
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
#sdc1.7
declare set_ideal_latency {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.7
declare set_ideal_network {
{object_list List }
{-no_propagate Flag }
} {param(object_list)}
#sdc1.7
declare set_ideal_transition {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_throough List {dup} }
{-rise_throough List {dup} }
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1} }
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise_through List {dup}}
{-fall_through List {dup}}
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare create_voltage_area {
{-name String {1} }
{-coordinate List }
{-guard_band_x List }
{-guard_band_y List }
{cell_list List {1} }
} {param(-name) && {param(cell_list)}}
declare set_level_shifter_strategy {
{-rule Enum {all low_to_high high_to_low}}
} {param(-rule)}
declare set_level_shifter_threshold {
{-voltage Float {1} }
{-percent Float {1} }
} {param(-voltage)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,715 @@
################################################################################
#
# Copyright 2009 (c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.8
#
# Update By : Ibna Faruque
# Updated On : July, 2009
# Bug Fixes :
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
#added on SDC1.7
declare all_registers {
{-clock List }
{-rise_clock List }
{-fall_clock List }
{-no_hierarchy Flag }
{-cells Flag }
{-data_pins Flag }
{-clock_pins Flag }
{-slave_clock_pins Flag }
{-async_pins Flag }
{-output_pins Flag }
{-level_sensitive Flag }
{-edge_triggered Flag }
{-master_slave Flag }
}
declare create_clock {
{-period Float {$par>=0} }
{-name String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{-combinational Flag }
{port_pin_list List }
{-add Flag }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
# added SDC1.7
declare group_path {
{-name String }
{-default Flag }
{-weight Float {$par>=0.0 && $par <=100.0} }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-rise_through List {dup} }
{-fall_through List {dup} }
} {((param(-name) && !param(-default)) || \
(param(-default) && !param(-name)) || !param(-name) && \
(param(-from) ^ param(-rise_from) ^ param(-fall_from)))}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
# sdc1.7 updte
declare set_units {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
# set_unit synonym for set_units
declare set_unit {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
# sdc1.7 command
declare set_clock_groups {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List {dup} }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# set_clock_group synonym for set_clock_groups
declare set_clock_group {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# sdc1.7 command
declare set_clock_sense {
{-clocks List }
{-positive Flag }
{-negative Flag }
{-stop_propagation Flag }
{-pulse Enum {rise_triggered_high_pulse rise_triggered_low_pulse \
fall_triggered_high_pulse fall_triggered_low_pulse} }
{pins List }
} {(param(-positive) ^ param(-negative) ^ param(-stop_propagation) ^ param(-pulse)) }
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
#sdc1.7
declare set_ideal_latency {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.7
declare set_ideal_network {
{object_list List }
{-no_propagate Flag }
} {param(object_list)}
#sdc1.7
declare set_ideal_transition {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.8
declare set_voltage {
{value Float {1}}
{-object_list List }
{-min Float {$par>=0} }
} {param(value) && param(-object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_throough List {dup} }
{-rise_throough List {dup} }
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1} }
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise_through List {dup}}
{-fall_through List {dup}}
{-through List {dup}}
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-rise Flag }
{-fall Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare create_voltage_area {
{-name String {1} }
{-coordinate List }
{-guard_band_x List }
{-guard_band_y List }
{cell_list List {1} }
} {param(-name) && {param(cell_list)}}
declare set_level_shifter_strategy {
{-rule Enum {all low_to_high high_to_low}}
} {param(-rule)}
declare set_level_shifter_threshold {
{-voltage Float {1} }
{-percent Float {1} }
} {param(-voltage)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,724 @@
################################################################################
#
# Copyright 2011(c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 1.8
#
# Update By : Ibna Faruque
# Updated On : January, 2011
# Bug Fixes :
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
#added on SDC1.7
declare all_registers {
{-clock List }
{-rise_clock List }
{-fall_clock List }
{-no_hierarchy Flag }
{-cells Flag }
{-data_pins Flag }
{-clock_pins Flag }
{-slave_clock_pins Flag }
{-async_pins Flag }
{-output_pins Flag }
{-level_sensitive Flag }
{-edge_triggered Flag }
{-master_slave Flag }
}
#added -comment for sdc1.9
declare create_clock {
{-period Float {$par>=0} }
{-name String }
{-comment String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{-combinational Flag }
{port_pin_list List }
{-add Flag }
{-comment String }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
# added SDC1.7
declare group_path {
{-name String }
{-default Flag }
{-weight Float {$par>=0.0 && $par <=100.0} }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-rise_through List {dup} }
{-fall_through List {dup} }
{-comment String }
} {((param(-name) && !param(-default)) || \
(param(-default) && !param(-name)) || !param(-name) && \
(param(-from) ^ param(-rise_from) ^ param(-fall_from)))}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
# sdc1.7 updte
declare set_units {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
# set_unit synonym for set_units
declare set_unit {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
# sdc1.7 command
declare set_clock_groups {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List {dup} }
{-comment String }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# set_clock_group synonym for set_clock_groups
declare set_clock_group {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List }
{-comment String }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# sdc1.7 command
declare set_clock_sense {
{-clocks List }
{-positive Flag }
{-negative Flag }
{-stop_propagation Flag }
{-pulse Enum {rise_triggered_high_pulse rise_triggered_low_pulse \
fall_triggered_high_pulse fall_triggered_low_pulse} }
{pins List }
} {(param(-positive) ^ param(-negative) ^ param(-stop_propagation) ^ param(-pulse)) }
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
#sdc1.7
declare set_ideal_latency {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.7
declare set_ideal_network {
{object_list List }
{-no_propagate Flag }
} {param(object_list)}
#sdc1.7
declare set_ideal_transition {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.8
declare set_voltage {
{value Float {1}}
{-object_list List }
{-min Float {$par>=0} }
} {param(value) && param(-object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_throough List {dup} }
{-rise_throough List {dup} }
{-comment String }
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1} }
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
{-comment String }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
{-comment String }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise_through List {dup}}
{-fall_through List {dup}}
{-through List {dup}}
{-comment String }
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-rise Flag }
{-fall Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare create_voltage_area {
{-name String {1} }
{-coordinate List }
{-guard_band_x List }
{-guard_band_y List }
{cell_list List {1} }
} {param(-name) && {param(cell_list)}}
declare set_level_shifter_strategy {
{-rule Enum {all low_to_high high_to_low}}
} {param(-rule)}
declare set_level_shifter_threshold {
{-voltage Float {1} }
{-percent Float {1} }
} {param(-voltage)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,733 @@
################################################################################
#
# Copyright 2013(c) Synopsys, Inc.
#
################################################################################
#
# Title : SDC-parser commands declaration for SDC version 2.0
#
# Update By : Ibna Faruque
# Updated On : July, 2013
# Bug Fixes : -combinational for create_generated_clock
################################################################################
declare all_clocks {
}
declare all_inputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
declare all_outputs {
{-level_sensitive Flag }
{-edge_triggered Flag }
{-clock List }
} {!(param(-level_sensitive) && param(-edge_triggered))}
#added on SDC1.7
declare all_registers {
{-clock List }
{-rise_clock List }
{-fall_clock List }
{-no_hierarchy Flag }
{-cells Flag }
{-data_pins Flag }
{-clock_pins Flag }
{-slave_clock_pins Flag }
{-async_pins Flag }
{-output_pins Flag }
{-level_sensitive Flag }
{-edge_triggered Flag }
{-master_slave Flag }
}
#added -comment for sdc1.9
declare create_clock {
{-period Float {$par>=0} }
{-name String }
{-comment String }
{-waveform List {type_Float {length($length>=2 && ($length % 2)==0)} } }
{port_pin_list List }
{-add Flag }
} {param(-period) && (param(-name) || param(port_pin_list))}
declare create_generated_clock {
{-name String }
{-source List }
{-edges List {type_Float {length($length>=2} } }
{-divide_by Int {1 && $par>=0} }
{-multiply_by Int {1 && $par>=0} }
{-edge_shift List }
{-duty_cycle Float {$par>=0 && $par <=100} }
{-invert Flag }
{-combinational Flag }
{port_pin_list List }
{-add Flag }
{-comment String }
{-master_clock List }
} {param(-source) && param(port_pin_list) && !(param(-multiply_by) && param(-divide_by))}
declare current_design {
}
declare current_instance {
{-instance String }
}
# added SDC1.7
declare group_path {
{-name String }
{-default Flag }
{-weight Float {$par>=0.0 && $par <=100.0} }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-rise_through List {dup} }
{-fall_through List {dup} }
{-comment String }
} {((param(-name) && !param(-default)) || \
(param(-default) && !param(-name)) || !param(-name) && \
(param(-from) ^ param(-rise_from) ^ param(-fall_from)))}
declare get_cells {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
# { }
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
# && !param(-hierarchical))}
# get_cell synonym for get_cells
declare get_cell {
{-of_objects List }
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_clocks {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_clock {
{patterns List }
{-regexp Flag }
{-nocase Flag }
}
declare get_lib_cells {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_cell {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pins {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_lib_pin {
{patterns List }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {param(patterns)}
declare get_libs {
{-regexp Flag }
{-nocase Flag }
{patterns List }
}
declare get_nets {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_net {
{patterns List }
{-of_objects List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
} {(param(patterns) && !param(-of_objects)) || \
(param(-of_objects) && !param(patterns)) || !param(patterns)}
declare get_pins {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_pin {
{patterns List }
{-hierarchical Flag }
{-regexp Flag }
{-nocase Flag }
{-hsc Enum {{/} {@} {^} {#} {.} {|}}}
}
declare get_ports {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
declare get_port {
{-hierarchical Flag }
{-regexp Flag }
{patterns List }
}
# } {param(patterns)}
# sdc1.7 updte
declare set_units {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
# set_unit synonym for set_units
declare set_unit {
{-capacitance String }
{-resistance String }
{-time String }
{-voltage String }
{-current String }
{-power String }
}
declare set_case_analysis {
{value Enum {0 1 rising falling zero one rise fall}}
{port_pin_list List }
} {param(value) && param(port_pin_list)}
declare set_clock_gating_check {
{-setup Float {$par>=0}}
{-hold Float {$par>=0}}
{-rise Flag }
{-fall Flag }
{-high Flag }
{-low Flag }
{object_list List }
} {(param(-setup) || param(-hold) || param(-high) || param(-low)) && \
!(param(-high) && param(-low))}
# sdc1.7 command
declare set_clock_groups {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List {dup} }
{-comment String }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# set_clock_group synonym for set_clock_groups
declare set_clock_group {
{-name String }
{-physically_exclusive Flag }
{-logically_exclusive Flag }
{-asynchronous Flag }
{-allow_paths Flag }
{-group List }
{-comment String }
} {(param(-physically_exclusive) ^ param(-logically_exclusive) ^ param(-asynchronous)) }
# sdc1.7 command
declare set_clock_sense {
{-clocks List }
{-positive Flag }
{-negative Flag }
{-stop_propagation Flag }
{-pulse Enum {rise_triggered_high_pulse rise_triggered_low_pulse \
fall_triggered_high_pulse fall_triggered_low_pulse} }
{pins List }
} {(param(-positive) ^ param(-negative) ^ param(-stop_propagation) ^ param(-pulse)) }
declare set_clock_latency {
{delay Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-source Flag }
{-early Flag }
{-late Flag }
{-clock List }
} {param(delay) && param(object_list)}
#sdc1.7
declare set_ideal_latency {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.7
declare set_ideal_network {
{object_list List }
{-no_propagate Flag }
} {param(object_list)}
#sdc1.7
declare set_ideal_transition {
{value Float {1}}
{object_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(value) && param(object_list)}
#sdc1.8
declare set_voltage {
{value Float {1}}
{-object_list List }
{-min Float {$par>=0} }
} {param(value) && param(-object_list)}
declare set_clock_transition {
{transition Float {1}}
{clock_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(transition) && param(clock_list) && \
!(param(-rise) && param(-fall))}
declare set_clock_uncertainty {
{uncertainty Float {1}}
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{object_list List }
} {param(uncertainty) && param(object_list) ^ \
(((param(-from) ^ param(-rise_from) ^ param(-fall_from))) \
&& (param(-to) ^ param(-rise_to) ^ param(-fall_to)))}
declare set_disable_timing {
{object_list List }
{-from String }
{-to String }
} {param(object_list) && \
!(param(-to) ^ param(-from))}
declare set_drive {
{resistance Float {$par>=0}}
{port_list List }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
} {param(resistance) && param(port_list)}
declare set_driving_cell {
{-lib_cell String }
{-rise Flag }
{-fall Flag }
{-library String }
{-pin String }
{-from_pin String }
{-multiply_by Float {$par>=0}}
{-dont_scale Flag }
{-no_design_rule Flag }
{-input_transition_rise Float {$par>=0}}
{-input_transition_fall Float {$par>=0}}
{port_list List }
{-min Flag }
{-max Flag }
{-clock List }
{-clock_fall Flag }
} {param(port_list) && param(-lib_cell)}
declare set_false_path {
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_throough List {dup} }
{-rise_throough List {dup} }
{-comment String }
} {(param(-from) || param(-to) || param(-through)) && \
!(param(-rise) && param(-fall)) && !(param(-setup) && param(-hold))}
declare set_fanout_load {
{value Float {$par>=0}}
{port_list List }
} {param(value) && param(port_list)}
declare set_hierarchy_separator {
{hchar Enum {{/} {@} {^} {#} {.} {|}}}
} {param(hchar)}
declare set_input_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1} }
{-reference_pin List }
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_input_transition {
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{transition Float {$par>=0}}
{port_list List }
{-clock List }
{-clock_fall Flag }
} {param(transition) && param(port_list)}
declare set_load {
{-min Flag }
{-max Flag }
{-substract_pin_load Flag }
{-pin_load Flag }
{-wire_load Flag }
{value Float {$par>=0}}
{objects List }
} {param(value) && param(objects)}
declare set_logic_dc {
{port_list List }
} {param(port_list)}
declare set_logic_one {
{port_list List }
} {param(port_list)}
declare set_logic_zero {
{port_list List }
} {param(port_list)}
declare set_max_area {
{area_value Float {$par>=0}}
} {param(area_value)}
declare set_max_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_max_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
{-comment String }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_max_fanout {
{fanout_value Float {$par>=0}}
{object_list List }
} {param(fanout_value) && param(object_list)}
declare set_max_time_borrow {
{delay_value Float {$par>=0}}
{object_list List }
} {param(delay_value) && param(object_list)}
declare set_max_transition {
{transition_value Float {$par>=0}}
{-clock_path Flag }
{-fall Flag }
{-rise Flag}
{object_list List }
} {param(transition_value) && param(object_list)}
declare set_min_capacitance {
{capacitance_value Float {$par>=0}}
{object_list List }
} {param(capacitance_value) && param(object_list)}
declare set_min_delay {
{delay_value Float {1} }
{-rise Flag }
{-fall Flag }
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-through List {dup} }
{-fall_through List {dup} }
{-rise_through List {dup} }
{-comment String }
} {param(delay_value) && \
!(param(-rise) && param(-fall))}
declare set_multicycle_path {
{path_multiplier Int {1}}
{-setup Flag }
{-hold Flag }
{-rise Flag }
{-fall Flag }
{-start Flag }
{-end Flag }
{-from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise_from List }
{-fall_from List }
{-rise_through List {dup}}
{-fall_through List {dup}}
{-through List {dup}}
{-comment String }
} {param(path_multiplier)}
declare set_operating_conditions {
{-analysis_type Enum {single bc_wc on_chip_variation}}
{-library List }
{-max String }
{-min String }
{-max_library List }
{-object_list List }
{-min_library List }
{condition String }
}
declare set_output_delay {
{-clock List }
{-clock_fall Flag }
{-level_sensitive Flag }
{-rise Flag }
{-fall Flag }
{-min Flag }
{-max Flag }
{-add_delay Flag }
{delay_value Float {1}}
{-reference_pin List }
{port_pin_list List }
{-network_latency_included Flag }
{-source_latency_included Flag }
} {param(delay_value) && param(port_pin_list) && \
!((param(-clock_fall) || param(-level_sensitive)) && !param(-clock))}
declare set_port_fanout_number {
{fanout_number Int {($par>=0) && ($par<=100000)}}
{port_list List }
} {param(fanout_number) && param(port_list)}
declare set_propagated_clock {
{object_list List }
} {param(object_list)}
declare set_resistance {
{value Float {$par>=0}}
{net_list List }
{-min Flag }
{-max Flag }
} {param(value) && param(net_list)}
declare set_wire_load_min_block_size {
{size Float {$par>=0}}
} {param(size)}
declare set_wire_load_mode {
{mode_name Enum {top enclosed segmented}}
} {param(mode_name)}
declare set_wire_load_model {
{-name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(-name)}
declare set_wire_load_selection_group {
{group_name String }
{-library List }
{-min Flag }
{-max Flag }
{object_list List }
} {param(group_name)}
declare set_data_check {
{-from List }
{-rise_from List }
{-fall_from List }
{-to List }
{-rise_to List }
{-fall_to List }
{-rise Flag }
{-fall Flag }
{-setup Flag }
{-hold Flag }
{-clock List }
{value Float {$par>=0} }
} {(param(-rise_from) || param(-from) || param(-fall_from)) && \
((param(-to) || param(-rise_to)) || param(-fall_to)) }
declare set_timing_derate {
{derate_value Float {$par>=0.1 } }
{object_list List }
# {derate_value Float {$par>=0.1 && $par<=2.0}}
{-min Flag }
{-max Flag }
{-rise Flag }
{-fall Flag }
{-early Flag }
{-late Flag }
{-clock Flag }
{-data Flag }
{-net_delay Flag }
{-cell_delay Flag }
{-cell_check Flag }
} {param(derate_value) && (param(-early) && !param(-late)) || (param(-late) && !param(-early))}
declare set_max_dynamic_power {
{power_value Float {$par>=0} }
{-unit Enum {GW MW KW W mW uW nW pW fW aW} }
} {param(power_value)}
declare set_max_leakage_power {
{power_value Float {$par>=0}}
{-unit Enum {GW MW KW W mW uW nW pW fW aW}}
} {param(power_value)}
declare create_voltage_area {
{-name String {1} }
{-coordinate List }
{-guard_band_x List }
{-guard_band_y List }
{cell_list List {1} }
} {param(-name) && {param(cell_list)}}
declare set_level_shifter_strategy {
{-rule Enum {all low_to_high high_to_low}}
} {param(-rule)}
declare set_level_shifter_threshold {
{-voltage Float {1} }
{-percent Float {1} }
} {param(-voltage)}
declare set_min_porosity {
{porosity_value Float {$par>=0 && $par <=90}}
{object_list List }
} {param(porosity_value) && param(object_list)}
# sdc 2.0 new constructs
declare set_min_pulse_width {
{value Float {$par>=0} }
{object_list List }
{-low Flag }
{-high Flag }
} {param(value)}
# register_new_type EdgeList {
# if {[sdc::check_type List $value]} {
# if {[expr {[llength $value] % 2}] || [llength $value]==0} {
# return 0
# }
#
# set startvalue -0.1
#
# foreach parv $value {
# if {[catch {expr {$parv + 1}}]} {
# return 0
# }
# if {$parv<=$startvalue} {
# return 0
# }
# set startvalue $parv
# }
#
# return 1
# } else {
# return 0
# }
# }

View File

@ -0,0 +1,147 @@
#!/bin/sh
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2011 Synopsys, Inc.
#
#
################################################################################
#
# Title : SDC-parser command line application
#
################################################################################\
exec tclsh "$0" "$@"
source [file join [file dirname [info script]] sdcparsercore.tcl]
proc usage {} {
global argv0
return "
Usage:
$argv0
<filename> \[filename \[...\]\] - source file name(s)
-f <filename> - read command line arguments from file
-d<debug_level> - set debug level
-d0 - no error messages, quiet mode
-d1 - brief error messages (default)
-d2 - extended error messages
-l <log_filename> - set log file name
-v <sdc_version> - set default sdc version
-eda <eda_source_file> - file name which contains tcl source of eda tool
"
}
#-------------------------------------------------------------------------------
# Function : process_command_line
# Description : Analize command line
# Paremeters : argv - list of command line parameters
# Return : Result data structure
#-------------------------------------------------------------------------------
proc process_command_line {argv {startdir ""}} {
if {$argv==""} {
puts [usage]
exit
} else {
set argwait ""
set files ""
foreach arg $argv {
switch -- $argwait {
f {
set argwait ""
if {[catch {set fname [::open $arg]}]!=0} {
puts stderr "Can't open file: $arg"
} else {
while {![eof $fname]} {
append data "[gets $fname] "
}
catch {close $fname}
set lparams [split $data]
while {[set pos [lsearch $lparams ""]]!=-1} {
set lparams [lreplace $lparams $pos $pos]
}
set files [concat $files [process_command_line \
$lparams [file dirname $arg]]]
}
}
e {
set argwait ""
catch {source $arg}
}
l {
set argwait ""
sdc::set_log_file $arg
catch {file delete $arg}
}
v {
set argwait ""
sdc::set_version $arg
}
default {
switch -glob -- $arg {
-f {
set argwait f
continue
}
-l {
set argwait l
continue
}
-d[0-2] {
sdc::set_debug_level [string index $arg 2]
}
-eda {
set argwait e
continue
}
-v {
set argwait v
continue
}
-help {
puts [usage]
continue
}
default {
lappend files [file join $startdir $arg]
}
}
}
}
}
}
return $files
}
#-------------------------------------------------------------------------------
# Main section
#-------------------------------------------------------------------------------
set filelist [process_command_line $argv]
if {$filelist!=""} {
foreach file $filelist {
sdc::parse_file $file
}
#if {$sdc::debuglevel>0} {
if {$sdc::errorstotal} {
puts "Found $sdc::errorstotal error(s) total."
} else {
puts "No errors found."
}
#}
} else {
puts "No files found."
puts [usage]
}

View File

@ -0,0 +1,870 @@
################################################################################
# > COPYRIGHT NOTICE <
#
# Copyright 2012 (c) Synopsys.
#
#
################################################################################
#
# Title : SDC-parser engine
#
# Project : SDC-parser
#
# : A.Gratchev
# Intrinsix Corp.
# : Ibna faruque
# Synopsys, Inc.
################################################################################
#
# List of procedures
#
# API procedures
#
#-------------------------------------------------------------------------------
# Function : sdc::declare
# Description : Declares SDC file command (each SDC command should be
# : declared for particular SDC version)
#-------------------------------------------------------------------------------
# Function : sdc::parse_file
# Description : Runs sdc-parser for source of SDC file
#-------------------------------------------------------------------------------
# Function : sdc::out_message
# Description : Puts message to the console / log file depending on settings
#-------------------------------------------------------------------------------
# Function : sdc::parse_command
# Description : Runs sdc-parser for one SDC command
#-------------------------------------------------------------------------------
# Function : sdc::register_callback
# Description : Sets a callback
#-------------------------------------------------------------------------------
# Function : sdc::set_log_file
# Description : Sets name of log-file
#-------------------------------------------------------------------------------
# Function : sdc::set_debug_level
# Description : Sets the level of debug messages
#-------------------------------------------------------------------------------
# Function : sdc::set_version
# Description : sets the sdcversion for use
#-------------------------------------------------------------------------------
#
# Internal rountines
#
#-------------------------------------------------------------------------------
# Function : sdc::proceesserror
# Description : Creates an error message from standart Tcl $errorInfo
#-------------------------------------------------------------------------------
# Function : sdc::setversion
# Description : Handler of setting of "sdc_version" variable
#-------------------------------------------------------------------------------
# Function : sdc::puterror
# Description : Puts some misc error messages
################################################################################
# ----------------------------------------------------------------------
# Revision History :
# ----------------------------------------------------------------------
# Date By Changes Description
# ----------------------------------------------------------------------
# 11/17/00 A.Gratchev Initial coding and debugging
# 02/22/01 A.Sokhatski Simplified code which processes list of
# parameters with defined type (by customer request)
# 12/27/12 Ibna Faruque Added SDC version 2.0 spec
namespace eval sdc {
variable validsdcversions [list 2.0 1.9 1.8 1.7 1.6 1.5 1.2 1.1 1.4 1.3] ;# list of valid sdc_versions
variable sdc_version ;# current sdc_version
variable lineno 0 ;# line number in processing file
variable statement "" ;# current read statement
variable procdefs ;# internal array of sdc commands declarations
variable proccond ;# internal array of sdc commands conditions
variable callback "" ;# name of callback procedure
variable logfile "" ;# name of log-file
variable debuglevel 1 ;# debug level (can be 0,1,2)
variable errors 0 ;# number of errors in one command
variable errorstotal 0 ;# total errors which was found
variable filename "" ;# current processing file
#-------------------------------------------------------------------------------
# Function : sdc::declare
# Description : Declares SDC file command (each SDC command should be
# : declared for particular SDC version)
# Parameters : proc - name of the command (Ex.: create_clock)
# : defargs - list of descriptions of commands parameters
# : cond - describing correct set of SDC-command's
# : arguments
# Return : Nothing
#-------------------------------------------------------------------------------
proc declare {proc defargs {cond 1}} {
variable procdefs
variable proccond
variable sdc_version
# checking for duplicate of declaration
if {![info exists procdefs($sdc_version,$proc)]} {
set procdefs($sdc_version,$proc) $defargs
set proccond($sdc_version,$proc) $cond
} else {
puts stderr "FATAL ERROR: Procedure \"$proc\" of version \
$sdc_version already declared!"
exit -1
}
# declarating sdc-command as procedure in slave Tcl-interp
sdc$sdc_version eval "
__proc $proc {args} {
__return \[parse_command $sdc_version $proc \$args\]
} "
}
proc register_new_type {type body} {
if {[info commands ::__user_type_handler_$type]==""} {
eval "
proc ::__user_type_handler_$type {value ext_list} \{
$body
\}
"
} else {
puts stderr "FATAL ERROR: Type \"$type\" already declared!"
exit -1
}
}
# create slave Tcl-interp for each sdc version
foreach v $validsdcversions {
interp create sdc$v
sdc$v eval {
# make trace handler on variable sdc_version
# for checking of valid
trace variable sdc_version w __set_v
proc __set_v {name args} {
__upvar $name sdcv
setversion $sdcv
}
# redefine procedure list which converting
# hierarhical list to simple list
proc list {args} {
set res ""
__foreach a $args {
set res [__concat $res $a]
}
__return $res
}
proc unknown {cmd_name args} {
puterror INVALID_COMMAND "$cmd_name"
__return ""
}
}
# disable all tcl commands
foreach pr [sdc$v eval info commands] {
sdc$v hide $pr
}
# enable and rename only needed procedures
sdc$v expose __set_v
sdc$v expose proc __proc
sdc$v expose upvar __upvar
sdc$v expose return __return
sdc$v expose foreach __foreach
sdc$v expose concat __concat
sdc$v expose list
sdc$v expose set
sdc$v expose expr
sdc$v expose unknown
sdc$v alias setversion sdc::setversion
sdc$v alias parse_command sdc::parse_command
sdc$v alias puterror sdc::puterror
set sdc_version $v
# include source file
# which contains of describing of sdc commands
if {[catch {source [file join [file dirname [info script]] \
sdc$v.tcl]}]} {
puts stderr "FATAL ERROR: Can't load file \"sdc$v.tcl\"!"
exit -1
}
}
set sdc_version [lindex $validsdcversions 0]
}
#-------------------------------------------------------------------------------
# Function : sdc::parse_file
# Description : Runs sdc-parser for source of SDC file
# Parameters : filename - file name of sdc source (SDC commands)
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::parse_file {file_name} {
variable validsdcversions
variable sdc_version
variable lineno 1
variable statement ""
if {[catch {set fname [::open $file_name]}]!=0} {
out_message "Can't open file: $file_name"
} else {
variable filename $file_name
set lines 1
while {![eof $fname]} {
append statement [gets $fname]
set stlen [string length $statement]
# read next line if statement is not complite
if {[string index $statement [expr {$stlen - 1}]]=="\\" \
|| ![info complete $statement]} {
append statement "\n"
incr lines
if {![eof $fname]} {
continue
}
}
# run sdc command
if {[catch {sdc$sdc_version eval $statement}]} {
processerror
}
set statement ""
incr lineno $lines
set lines 1
}
catch {close $fname}
}
}
#-------------------------------------------------------------------------------
# Function : sdc::proceesserror
# Description : Creates an error message from standart Tcl $errorInfo
# Parameters : None
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::processerror {} {
variable lineno
variable logfile
variable debuglevel
variable errors
variable errorstotal
variable filename
global errorCode errorInfo
incr errors
incr errorstotal
set err [split $errorInfo "\n"]
set errMsg [lindex $err 0]
set errSt [lindex $err 2]
set f 0
foreach errL [lrange $err 3 end] {
if {[string match {*line [0-9]*)} $errL]} {
set f 1
set errSt [join [lrange $err 2 [expr \
{[lsearch -exact $err $errL] - 1}]] "\n"]
break
}
}
if {$f} {
set errLine ""
for {set i [expr {[string length $errL] - 2}]} \
{($i>=0) && ([set c [string index $errL $i]]!=" ")} {incr i -1} {
set errLine "$c$errLine"
}
set errLine [expr {$lineno + $errLine - 1}]
} else {
set errLine $lineno
}
switch -- $debuglevel {
0 {
set errmsg ""
}
2 {
set errmsg "$filename, $errLine: $errMsg\n while executing $errSt\n"
}
1 -
default {
set errmsg "$filename, $errLine: $errMsg"
}
}
if {$errmsg!=""} {
out_message $errmsg
}
}
#-------------------------------------------------------------------------------
# Function : sdc::setversion
# Description : Handler of setting of "sdc_version" variable
# Parameters : sdcv - a new sdc_version value
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::setversion {sdcv} {
variable validsdcversions
variable sdc_version
if {[lsearch -exact $validsdcversions $sdcv]==-1} {
puterror INCORRECT_SDC_VERSION
} else {
set sdc_version $sdcv
}
}
#-------------------------------------------------------------------------------
# Function : sdc::puterror
# Description : Puts some misc error messages
# Parameters : msg - text of the message
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::puterror {msg_id args} {
variable statement
global errorInfo
switch -exact -- $msg_id {
INCORRECT_SDC_VERSION {
set errorInfo "incorrect sdc_version"
}
INVALID_COMMAND {
set errorInfo "invalid command \"[lindex $args 0]\""
}
VALUE_NOT_SPECIFIED {
set errorInfo "value not specified for \"[lindex $args 0]\""
}
INCORRECT_ARGUMENT {
set errorInfo "incorrect argument \"[lindex $args 1]\"\
for \"[lindex $args 0]\""
}
INCORRECT_ARGUMENT_PRE {
set errorInfo "incorrect argument \"[lindex $args 1]\"\
for \"[lindex $args 0]\"\
Too many pretendents"
}
INCORRECT_ARGUMENT_DUP {
set errorInfo "duplicate arguments \"[lindex $args 0]\"\
for \"[lindex $args 1]\""
}
INCORRECT_ARGUMENT_MANY {
set errorInfo "incorrect argument \"[lindex $args 1]\"\
for \"[lindex $args 0]\"\
(too many arguments?)"
}
INCORRECT_VALUE_RANGE {
set errorInfo "incorrect value for \"[lindex $args 0]\",\
must be [lindex $args 1]"
}
INCORRECT_TYPE {
set errorInfo "incorrect value for \"[lindex $args 0]\""
}
INCORRECT_TYPE_FLOAT {
set errorInfo "incorrect value for \"[lindex $args 0]\",\
must be float type"
}
INCORRECT_TYPE_INT {
set errorInfo "incorrect value for \"[lindex $args 0]\",\
must be integer type"
}
INCORRECT_TYPE_STRING {
set errorInfo "incorrect value for \"[lindex $args 0]\",\
must be string type"
}
INCORRECT_TYPE_LIST {
set errorInfo "incorrect value for \"[lindex $args 0]\",\
must be list type"
}
INCORRECT_TYPE_LIST_ELEM {
set errorInfo "incorrect type of elements of list for\
\"[lindex $args 0]\",\
must be [lindex $args 1] type"
}
INCORRECT_TYPE_LIST_LENGTH {
set errorInfo "incorrect length of list for \"[lindex $args 0]\""
}
INCORRECT_SET {
set errorInfo "incorrect set of required parameters for\
\"[lindex $args 0]\""
}
USER {
set errorInfo "[lindex $args 0]"
}
default {
set errorInfo "unknown error message $msg_id"
}
}
append errorInfo "\nwhile executing\n\"$statement\"\n(line 1)"
processerror
}
#-------------------------------------------------------------------------------
# Function : sdc::out_message
# Description : Puts message to the console / log file depending on settings
# Parameters : msg - text of the message
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::out_message {msg} {
variable logfile
puts stderr $msg
if {$logfile!=""} {
if {[catch {set flog [::open $logfile a+]}]==0} {
puts $flog $msg
catch {close $flog}
} else {
puts stderr "INTERNAL: Can't write to log-file $logfile"
set logfile ""
}
}
}
#-------------------------------------------------------------------------------
# Function : sdc::check_type
# Description : Check type of argument
# Parameters : type - type of argument
# : value - value to be cheked
# Return : True or false
#-------------------------------------------------------------------------------
proc sdc::check_type {type value args} {
variable errors
switch -- $type {
float -
Float {
# for checking that it is Float add 1 and catch exception
if {![catch {expr {$value + 1}}]} {
return 1
} else {
return 0
}
}
int -
Int {
if {![catch {expr {$value + 1}}] \
&& [expr {int($value) == $value}]} {
return 1
} else {
return 0
}
}
string -
String {
return 1
}
enum -
Enum {
foreach val [lindex $args 0] {
if {$val==$value} {
return 1
}
}
return 0
}
list -
List {
if {![catch {llength $value}]} {
return 1
} else {
return 0
}
}
unknown -
Unknown {
return 1
}
default {
if {[info commands ::__user_type_handler_$type]==""} {
puterror USER "INTERNAL: unknown type of param:\
\"$type\", ignored"
incr errors -1
return 1
} else {
if {![catch {set res [eval {::__user_type_handler_$type $value\
[lindex $args 0]}]}]} {
if {$res} {
return 1
} else {
return 0
}
} else {
puterror USER "INTERNAL: error while executing\
user's checking procedure for type:\
\"$type\", ignored"
incr errors -1
return 0
}
}
}
} ;#switch
}
#-------------------------------------------------------------------------------
# Function : sdc::parse_command
# Description : Runs sdc-parser for one SDC command
# Parameters : ver - version number of SDC (Ex.: 1.1)
# : proc - name of the command (Ex.: create_clock)
# : arguments - list of command's arguments
# Return : Callback result or empty
#-------------------------------------------------------------------------------
proc sdc::parse_command {ver proc arguments} {
variable procdefs
variable proccond
variable errors 0
variable callback
# local variables for parameters presentation
#
# procpars - matching parameter lists from command declaration
# procpar - matching parameter list
# parexpect - matching parameter list (for -name parameter) or empty
# param_array - internal array for parsed command
# data_structure - result data structure for EDA procedure
set i 0
set num [llength $arguments]
set parexpect ""
while {$i<$num} {
set par [lindex $arguments $i]
if {[string match {-[a-zA-Z]*} $par]} {
# if here, par is key param
incr i
if {$parexpect!=""} {
puterror VALUE_NOT_SPECIFIED "$proc [lindex $parexpect 0]"
}
# finding descriptions of matching parameters
set procpars ""
foreach procpar $procdefs($ver,$proc) {
if {[string match "$par*" [lindex $procpar 0]]} {
if {[lindex $procpar 0]==$par} {
set procpars [list $procpar]
break
} else {
lappend procpars $procpar
}
}
}
# how many matchings found?
switch -- [llength $procpars] {
0 {
puterror INCORRECT_ARGUMENT $proc $par
continue
}
1 {
set procpar [join $procpars]
if {([lindex $procpar 1]=="List" &&
[lsearch -exact [lindex $procpar 2] dup]!=-1) ||
![info exists param_array([lindex $procpar 0],key)]} {
set param_array([lindex $procpar 0],key) 1
} else {
puterror INCORRECT_ARGUMENT_DUP \
[lindex $procpar 0] $proc
}
set parexpect $procpar
}
default {
puterror INCORRECT_ARGUMENT_PRE $proc $par
continue
}
}
# if argument is "Flag", go to analyze the next argument
if {[lindex $parexpect 1]=="Flag"} {
set parexpect ""
set param_array([lindex $procpar 0],value) yes
continue
}
if {$i>=$num} {
puterror VALUE_NOT_SPECIFIED "$proc [lindex $parexpect 0]"
break
}
set par [lindex $arguments $i]
}
if {$parexpect==""} {
# positional argument, find the first empty
set f 0
foreach procpar $procdefs($ver,$proc) {
if {[string index [lindex $procpar 0] 0]!="-"} {
if {![info exists param_array([lindex $procpar 0],value)]} {
set f 1
set parexpect $procpar
break
} else {
continue
}
}
}
if {!$f} {
puterror INCORRECT_ARGUMENT_MANY $proc $par
}
} else {
set f 1
}
# value of argument, check format
if {$f} {
switch -- [lindex $parexpect 1] {
float -
Float {
# for checking that it is Float add 1 and catch exception
if {[check_type Float $par]} {
if {![catch {set f [expr [lindex $parexpect 2]]}] \
&& $f} {
set param_array([lindex $parexpect 0],value) $par
} else {
regsub -all -- {\$par} [lindex $parexpect 2] {} cond
puterror INCORRECT_VALUE_RANGE "$proc [lindex \
$parexpect 0]" $cond
catch {unset param_array([lindex $parexpect 0],key)}
}
} else {
puterror INCORRECT_TYPE_FLOAT \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
int -
Int {
if {[check_type Int $par]} {
if {![catch {set f [expr [lindex $parexpect 2]]}] \
&& $f} {
set param_array([lindex $parexpect 0],value) $par
} else {
regsub -all -- {\$par} [lindex $parexpect 2] {} cond
puterror INCORRECT_VALUE_RANGE "$proc [lindex \
$parexpect 0]" $cond
catch {unset param_array([lindex $parexpect 0],key)}
}
} else {
puterror INCORRECT_TYPE_INT \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
string -
String {
if {[check_type String $par]} {
set param_array([lindex $parexpect 0],value) $par
} else {
puterror INCORRECT_TYPE_STRING \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
enum -
Enum {
if {[check_type Enum $par [lindex $parexpect 2]]} {
set param_array([lindex $parexpect 0],value) $par
} else {
puterror INCORRECT_TYPE \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
list -
List {
if {[check_type List $par]} {
if {[set type_id [lsearch -glob [set attr [lindex \
$parexpect 2]] {length(*)}]]!=-1} {
set length [llength $par]
if {[catch {set res [expr "[string range [lindex \
$attr $type_id] 6 end]"]}] || !$res} {
puterror INCORRECT_TYPE_LIST_LENGTH \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex \
$parexpect 0],key)}
break
}
}
if {[set type_id [lsearch -glob $attr {type_*}]]!=-1} {
foreach par_elem $par {
if {[check_type [set type_elem [string range \
[lindex $attr $type_id] 5 end]] $par_elem]} {
catch {lappend param_array([lindex \
$parexpect 0],value)\
$par_elem}
} else {
puterror INCORRECT_TYPE_LIST_ELEM \
"$proc [lindex $parexpect 0]" \
$type_elem
catch {unset param_array([lindex \
$parexpect 0],key)}
break
}
}
} else {
if {[catch {set param_array([lindex \
$parexpect 0],value)\
[list $param_array([lindex $parexpect 0],value) \
$par]}]} {
set param_array([lindex $parexpect 0],value) \
$par
}
}
} else {
puterror INCORRECT_TYPE_LIST \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
unknown -
Unknown {
set param_array([lindex $parexpect 0],value) $par
}
default {
if {[check_type [lindex $parexpect 1] $par [lrange $parexpect 2 end]]} {
set param_array([lindex $parexpect 0],value) $par
} else {
puterror INCORRECT_TYPE \
"$proc [lindex $parexpect 0]"
catch {unset param_array([lindex $parexpect 0],key)}
}
}
} ;#switch
}
set parexpect ""
incr i
} ;#while
# check whether set of SDC-command's arguments is correct
set cond $proccond($ver,$proc)
foreach procpar $procdefs($ver,$proc) {
set par [lindex $procpar 0]
regsub -all -- "param\\\($par\\\)" $cond \
[info exists param_array($par,value)] cond
}
if {[catch {set ok [expr $cond]}]} {
puterror USER "INTERNAL: error in expression: \"$proccond($ver,$proc)\" \
($cond), ignored"
incr errors -1
} else {
if {!$ok} {
puterror INCORRECT_SET $proc
}
}
# create result data structure
set result ""
foreach procpar $procdefs($ver,$proc) {
if {[info exists param_array([lindex $procpar 0],value)]} {
set data_structure([lindex $procpar 0]) \
$param_array([lindex $procpar 0],value)
}
}
# call "callback" procedure
if {$callback!="" && !$errors} {
return [$callback $proc data_structure]
} else {
return ""
}
}
#-------------------------------------------------------------------------------
# Function : sdc::register_callback
# Description : Sets a callback
# Parameters : proc_name - name of "callback" procedure (if proc_name
# : is empty callback will be disabled)
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::register_callback {proc_name} {
variable callback $proc_name
}
#-------------------------------------------------------------------------------
# Function : sdc::set_log_file
# Description : Sets name of log-file
# Parameters : filename - name of log-file
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::set_log_file {filename} {
variable logfile $filename
}
#-------------------------------------------------------------------------------
# Function : sdc::set_debug_level
# Description : Sets the level of debug messages
# Parameters : level - lovel of debug
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::set_debug_level {level} {
variable debuglevel $level
}
#-------------------------------------------------------------------------------
# Function : sdc::set_version
# Description : sets the sdcversion for use
# Parameters : ver - version number of SDC
# Return : Nothing
#-------------------------------------------------------------------------------
proc sdc::set_version {ver} {
setversion $ver
}

View File

@ -0,0 +1,99 @@
#include "sdc.h"
namespace gt::sdc {
std::vector<std::string> tokenize(const std::string& line) {
// Parse the token.
std::string token;
std::vector<std::string> tokens;
auto add_token = [](auto& tokens, auto& token) {
if (!token.empty()) {
tokens.push_back(std::move(token));
}
};
for (auto itr = line.begin(); itr != line.end(); ++itr) {
if (*itr == '#' || *itr == '\n' || *itr == '\r') {
break;
}
if (*itr == ' ') {
add_token(tokens, token);
}
// "quotation string"
else if (*itr == '"') {
logger.infoif(!token.empty(), "syntax error in parsing '\"'");
if (auto [b, e] = find_quote_pair(itr, line.end()); b != e) {
while (++b != e) {
token.push_back(*b);
}
add_token(tokens, token);
itr = e;
} else {
logger.info("can't find quote pair \" \"");
}
}
// [ ... ]
else if (*itr == '[') {
logger.infoif(!token.empty(), "syntax error in parsing '['");
token.push_back('[');
add_token(tokens, token);
auto [b, e] = find_bracket_pair(itr, line.end());
logger.infoif(b == line.end(), "can't find bracket pair [ ]");
for (auto i = std::next(b); i != e; ++i) {
if (*i == '{' || *i == '}') continue;
if (*i == ' ') {
add_token(tokens, token);
} else {
token.push_back(*i);
}
}
add_token(tokens, token);
token.push_back(']');
add_token(tokens, token);
itr = e;
}
// { ... }
else if (*itr == '{') {
logger.infoif(!token.empty(), "syntax error in parsing '{'");
token.push_back('{');
add_token(tokens, token);
auto [b, e] = find_brace_pair(itr, line.end());
logger.infoif(b == line.end(), "can't find brace pair { }");
for (auto i = std::next(b); i != e; ++i) {
if (*i == '{' || *i == '}') continue;
if (*i == ' ') {
add_token(tokens, token);
} else {
token.push_back(*i);
}
}
add_token(tokens, token);
token.push_back('}');
add_token(tokens, token);
itr = e;
} else {
token.push_back(*itr);
}
}
add_token(tokens, token);
return tokens;
}
}; // namespace gt::sdc

View File

@ -0,0 +1,11 @@
#pragma once
#include "common/common.h"
#include "common/lib/Helper.h"
namespace gt::sdc {
using token_iter_t = std::vector<std::string>::iterator;
std::vector<std::string> tokenize(const std::string&);
}; // namespace gt::sdc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2007-2018 Dr. Colin Hirsch and Daniel Frey
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,35 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_HPP
#define TAO_PEGTL_HPP
#include "pegtl/config.hpp"
#include "pegtl/version.hpp"
#include "pegtl/ascii.hpp"
#include "pegtl/parse.hpp"
#include "pegtl/rules.hpp"
#include "pegtl/uint16.hpp"
#include "pegtl/uint32.hpp"
#include "pegtl/uint64.hpp"
#include "pegtl/uint8.hpp"
#include "pegtl/utf16.hpp"
#include "pegtl/utf32.hpp"
#include "pegtl/utf8.hpp"
#include "pegtl/argv_input.hpp"
#include "pegtl/buffer_input.hpp"
#include "pegtl/cstream_input.hpp"
#include "pegtl/file_input.hpp"
#include "pegtl/istream_input.hpp"
#include "pegtl/memory_input.hpp"
#include "pegtl/read_input.hpp"
#include "pegtl/string_input.hpp"
// The following are not included by
// default because they include <iostream>.
// #include "pegtl/analyze.hpp"
#endif

View File

@ -0,0 +1,135 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP
#define TAO_PEGTL_ANALYSIS_ANALYZE_CYCLES_HPP
#include <cassert>
#include <map>
#include <set>
#include <stdexcept>
#include <iostream>
#include <utility>
#include "../config.hpp"
#include "grammar_info.hpp"
#include "insert_guard.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
class analyze_cycles_impl
{
protected:
explicit analyze_cycles_impl( const bool verbose ) noexcept
: m_verbose( verbose ),
m_problems( 0 )
{
}
const bool m_verbose;
unsigned m_problems;
grammar_info m_info;
std::set< std::string > m_stack;
std::map< std::string, bool > m_cache;
std::map< std::string, bool > m_results;
const std::map< std::string, rule_info >::const_iterator find( const std::string& name ) const noexcept
{
const auto iter = m_info.map.find( name );
assert( iter != m_info.map.end() );
return iter;
}
bool work( const std::map< std::string, rule_info >::const_iterator& start, const bool accum )
{
const auto j = m_cache.find( start->first );
if( j != m_cache.end() ) {
return j->second;
}
if( const auto g = make_insert_guard( m_stack, start->first ) ) {
switch( start->second.type ) {
case rule_type::ANY: {
bool a = false;
for( const auto& r : start->second.rules ) {
a = a || work( find( r ), accum || a );
}
return m_cache[ start->first ] = true;
}
case rule_type::OPT: {
bool a = false;
for( const auto& r : start->second.rules ) {
a = a || work( find( r ), accum || a );
}
return m_cache[ start->first ] = false;
}
case rule_type::SEQ: {
bool a = false;
for( const auto& r : start->second.rules ) {
a = a || work( find( r ), accum || a );
}
return m_cache[ start->first ] = a;
}
case rule_type::SOR: {
bool a = true;
for( const auto& r : start->second.rules ) {
a = a && work( find( r ), accum );
}
return m_cache[ start->first ] = a;
}
}
throw std::logic_error( "code should be unreachable: invalid rule_type value" ); // NOLINT, LCOV_EXCL_LINE
}
if( !accum ) {
++m_problems;
if( m_verbose ) {
std::cout << "problem: cycle without progress detected at rule class " << start->first << std::endl; // LCOV_EXCL_LINE
}
}
return m_cache[ start->first ] = accum;
}
};
template< typename Grammar >
class analyze_cycles
: private analyze_cycles_impl
{
public:
explicit analyze_cycles( const bool verbose )
: analyze_cycles_impl( verbose )
{
Grammar::analyze_t::template insert< Grammar >( m_info );
}
std::size_t problems()
{
for( auto i = m_info.map.begin(); i != m_info.map.end(); ++i ) {
m_results[ i->first ] = work( i, false );
m_cache.clear();
}
return m_problems;
}
template< typename Rule >
bool consumes() const noexcept
{
const auto i = m_results.find( internal::demangle< Rule >() );
assert( i != m_results.end() );
return i->second;
}
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,29 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_COUNTED_HPP
#define TAO_PEGTL_ANALYSIS_COUNTED_HPP
#include "../config.hpp"
#include "generic.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
template< rule_type Type, unsigned Count, typename... Rules >
struct counted
: generic< ( Count != 0 ) ? Type : rule_type::OPT, Rules... >
{
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,39 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_GENERIC_HPP
#define TAO_PEGTL_ANALYSIS_GENERIC_HPP
#include "../config.hpp"
#include "grammar_info.hpp"
#include "insert_rules.hpp"
#include "rule_type.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
template< rule_type Type, typename... Rules >
struct generic
{
template< typename Name >
static std::string insert( grammar_info& g )
{
const auto r = g.insert< Name >( Type );
if( r.second ) {
insert_rules< Rules... >::insert( g, r.first->second );
}
return r.first->first;
}
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,40 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP
#define TAO_PEGTL_ANALYSIS_GRAMMAR_INFO_HPP
#include <map>
#include <string>
#include <utility>
#include "../config.hpp"
#include "../internal/demangle.hpp"
#include "rule_info.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
struct grammar_info
{
using map_t = std::map< std::string, rule_info >;
map_t map;
template< typename Name >
std::pair< map_t::iterator, bool > insert( const rule_type type )
{
return map.insert( map_t::value_type( internal::demangle< Name >(), rule_info( type ) ) );
}
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,68 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_INSERT_GUARD_HPP
#define TAO_PEGTL_ANALYSIS_INSERT_GUARD_HPP
#include <utility>
#include "../config.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
template< typename C >
class insert_guard
{
public:
insert_guard( C& container, const typename C::value_type& value )
: m_i( container.insert( value ) ),
m_c( &container )
{
}
insert_guard( const insert_guard& ) = delete;
insert_guard( insert_guard&& other ) noexcept
: m_i( other.m_i ),
m_c( other.m_c )
{
other.m_c = nullptr;
}
~insert_guard()
{
if( m_c && m_i.second ) {
m_c->erase( m_i.first );
}
}
void operator=( const insert_guard& ) = delete;
void operator=( insert_guard&& ) = delete;
explicit operator bool() const noexcept
{
return m_i.second;
}
private:
const std::pair< typename C::iterator, bool > m_i;
C* m_c;
};
template< typename C >
insert_guard< C > make_insert_guard( C& container, const typename C::value_type& value )
{
return insert_guard< C >( container, value );
}
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,45 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_INSERT_RULES_HPP
#define TAO_PEGTL_ANALYSIS_INSERT_RULES_HPP
#include "../config.hpp"
#include "grammar_info.hpp"
#include "rule_info.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
template< typename... >
struct insert_rules;
template<>
struct insert_rules<>
{
static void insert( grammar_info& /*unused*/, rule_info& /*unused*/ )
{
}
};
template< typename Rule, typename... Rules >
struct insert_rules< Rule, Rules... >
{
static void insert( grammar_info& g, rule_info& r )
{
r.rules.push_back( Rule::analyze_t::template insert< Rule >( g ) );
insert_rules< Rules... >::insert( g, r );
}
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,37 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_RULE_INFO_HPP
#define TAO_PEGTL_ANALYSIS_RULE_INFO_HPP
#include <string>
#include <vector>
#include "../config.hpp"
#include "rule_type.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
struct rule_info
{
explicit rule_info( const rule_type in_type ) noexcept
: type( in_type )
{
}
rule_type type;
std::vector< std::string > rules;
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,29 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYSIS_RULE_TYPE_HPP
#define TAO_PEGTL_ANALYSIS_RULE_TYPE_HPP
#include "../config.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace analysis
{
enum class rule_type : char
{
ANY, // Consumption-on-success is always true; assumes bounded repetition of conjunction of sub-rules.
OPT, // Consumption-on-success not necessarily true; assumes bounded repetition of conjunction of sub-rules.
SEQ, // Consumption-on-success depends on consumption of (non-zero bounded repetition of) conjunction of sub-rules.
SOR // Consumption-on-success depends on consumption of (non-zero bounded repetition of) disjunction of sub-rules.
};
} // namespace analysis
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,25 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ANALYZE_HPP
#define TAO_PEGTL_ANALYZE_HPP
#include "config.hpp"
#include "analysis/analyze_cycles.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
template< typename Rule >
std::size_t analyze( const bool verbose = true )
{
return analysis::analyze_cycles< Rule >( verbose ).problems();
}
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,23 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_APPLY_MODE_HPP
#define TAO_PEGTL_APPLY_MODE_HPP
#include "config.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
enum class apply_mode : bool
{
ACTION = true,
NOTHING = false
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,57 @@
// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ARGV_INPUT_HPP
#define TAO_PEGTL_ARGV_INPUT_HPP
#include <cstddef>
#include <sstream>
#include <string>
#include <utility>
#include "config.hpp"
#include "eol.hpp"
#include "memory_input.hpp"
#include "tracking_mode.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
inline std::string make_argv_source( const std::size_t argn )
{
std::ostringstream os;
os << "argv[" << argn << ']';
return os.str();
}
} // namespace internal
template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf >
struct argv_input
: public memory_input< P, Eol >
{
template< typename T >
argv_input( char** argv, const std::size_t argn, T&& in_source )
: memory_input< P, Eol >( static_cast< const char* >( argv[ argn ] ), std::forward< T >( in_source ) )
{
}
argv_input( char** argv, const std::size_t argn )
: argv_input( argv, argn, internal::make_argv_source( argn ) )
{
}
};
#ifdef __cpp_deduction_guides
template< typename... Ts >
argv_input( Ts&&... )->argv_input<>;
#endif
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,68 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_ASCII_HPP
#define TAO_PEGTL_ASCII_HPP
#include "config.hpp"
#include "eol.hpp"
#include "internal/result_on_found.hpp"
#include "internal/rules.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
inline namespace ascii
{
// clang-format off
struct alnum : internal::alnum {};
struct alpha : internal::alpha {};
struct any : internal::any< internal::peek_char > {};
struct blank : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {};
struct digit : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {};
struct eolf : internal::eolf {};
struct identifier_first : internal::identifier_first {};
struct identifier_other : internal::identifier_other {};
struct identifier : internal::identifier {};
template< char... Cs > struct istring : internal::istring< Cs... > {};
template< char... Cs > struct keyword : internal::seq< internal::string< Cs... >, internal::not_at< internal::identifier_other > > {};
struct lower : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'a', 'z' > {};
template< char... Cs > struct not_one : internal::one< internal::result_on_found::FAILURE, internal::peek_char, Cs... > {};
template< char Lo, char Hi > struct not_range : internal::range< internal::result_on_found::FAILURE, internal::peek_char, Lo, Hi > {};
struct nul : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ) > {};
template< char... Cs > struct one : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, Cs... > {};
struct print : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 32 ), char( 126 ) > {};
template< char Lo, char Hi > struct range : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, Lo, Hi > {};
template< char... Cs > struct ranges : internal::ranges< internal::peek_char, Cs... > {};
struct seven : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 0 ), char( 127 ) > {};
struct shebang : internal::if_must< false, internal::string< '#', '!' >, internal::until< internal::eolf > > {};
struct space : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\n', '\r', '\t', '\v', '\f' > {};
template< char... Cs > struct string : internal::string< Cs... > {};
template< char C > struct three : internal::three< C > {};
template< char C > struct two : internal::two< C > {};
struct upper : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, 'A', 'Z' > {};
struct xdigit : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {};
// clang-format on
template<>
struct keyword<>
{
template< typename Input >
static bool match( Input& /*unused*/ ) noexcept
{
static_assert( sizeof( Input ) == 0, "empty keywords not allowed" );
return false;
}
};
} // namespace ascii
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#include "internal/pegtl_string.hpp"
#endif

View File

@ -0,0 +1,185 @@
// Copyright (c) 2016-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_BUFFER_INPUT_HPP
#define TAO_PEGTL_BUFFER_INPUT_HPP
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include "config.hpp"
#include "eol.hpp"
#include "memory_input.hpp"
#include "position.hpp"
#include "tracking_mode.hpp"
#include "internal/action_input.hpp"
#include "internal/bump_impl.hpp"
#include "internal/iterator.hpp"
#include "internal/marker.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string >
class buffer_input
{
public:
static constexpr tracking_mode tracking_mode_v = tracking_mode::IMMEDIATE;
using reader_t = Reader;
using eol_t = Eol;
using source_t = Source;
using iterator_t = internal::iterator;
using action_t = internal::action_input< buffer_input >;
template< typename T, typename... As >
buffer_input( T&& in_source, const std::size_t maximum, As&&... as )
: m_reader( std::forward< As >( as )... ),
m_maximum( maximum ),
m_buffer( new char[ maximum ] ),
m_current( m_buffer.get() ),
m_end( m_buffer.get() ),
m_source( std::forward< T >( in_source ) )
{
}
buffer_input( const buffer_input& ) = delete;
buffer_input( buffer_input&& ) = delete;
~buffer_input() = default;
void operator=( const buffer_input& ) = delete;
void operator=( buffer_input&& ) = delete;
bool empty()
{
require( 1 );
return m_current.data == m_end;
}
std::size_t size( const std::size_t amount )
{
require( amount );
return std::size_t( m_end - m_current.data );
}
const char* current() const noexcept
{
return m_current.data;
}
const char* end( const std::size_t amount )
{
require( amount );
return m_end;
}
std::size_t byte() const noexcept
{
return m_current.byte;
}
std::size_t line() const noexcept
{
return m_current.line;
}
std::size_t byte_in_line() const noexcept
{
return m_current.byte_in_line;
}
const Source& source() const noexcept
{
return m_source;
}
char peek_char( const std::size_t offset = 0 ) const noexcept
{
return m_current.data[ offset ];
}
std::uint8_t peek_byte( const std::size_t offset = 0 ) const noexcept
{
return static_cast< std::uint8_t >( peek_char( offset ) );
}
void bump( const std::size_t in_count = 1 ) noexcept
{
internal::bump( m_current, in_count, Eol::ch );
}
void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
{
internal::bump_in_this_line( m_current, in_count );
}
void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
{
internal::bump_to_next_line( m_current, in_count );
}
void discard() noexcept
{
const auto s = m_end - m_current.data;
std::memmove( m_buffer.get(), m_current.data, s );
m_current.data = m_buffer.get();
m_end = m_buffer.get() + s;
}
void require( const std::size_t amount )
{
if( m_current.data + amount > m_end ) {
if( m_current.data + amount <= m_buffer.get() + m_maximum ) {
if( const auto r = m_reader( m_end, amount - std::size_t( m_end - m_current.data ) ) ) {
m_end += r;
}
else {
m_maximum = 0;
}
}
}
}
template< rewind_mode M >
internal::marker< iterator_t, M > mark() noexcept
{
return internal::marker< iterator_t, M >( m_current );
}
TAO_PEGTL_NAMESPACE::position position( const iterator_t& it ) const
{
return TAO_PEGTL_NAMESPACE::position( it, m_source );
}
TAO_PEGTL_NAMESPACE::position position() const
{
return position( m_current );
}
const iterator_t& iterator() const noexcept
{
return m_current;
}
private:
Reader m_reader;
std::size_t m_maximum;
std::unique_ptr< char[] > m_buffer;
iterator_t m_current;
char* m_end;
const Source m_source;
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,20 @@
// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONFIG_HPP
#define TAO_PEGTL_CONFIG_HPP
// Compatibility, remove with 3.0
#ifdef TAOCPP_PEGTL_NAMESPACE
#define TAO_PEGTL_NAMESPACE TAOCPP_PEGTL_NAMESPACE
#endif
#ifndef TAO_PEGTL_NAMESPACE
#define TAO_PEGTL_NAMESPACE pegtl
#endif
// Enable some improvements to the readability of
// demangled type names under some circumstances.
// #define TAO_PEGTL_PRETTY_DEMANGLE
#endif

View File

@ -0,0 +1,43 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ABNF_HPP
#define TAO_PEGTL_CONTRIB_ABNF_HPP
#include "../config.hpp"
#include "../internal/rules.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace abnf
{
// Core ABNF rules according to RFC 5234, Appendix B
// clang-format off
struct ALPHA : internal::ranges< internal::peek_char, 'a', 'z', 'A', 'Z' > {};
struct BIT : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '0', '1' > {};
struct CHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 1 ), char( 127 ) > {};
struct CR : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\r' > {};
struct CRLF : internal::string< '\r', '\n' > {};
struct CTL : internal::ranges< internal::peek_char, char( 0 ), char( 31 ), char( 127 ) > {};
struct DIGIT : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, '0', '9' > {};
struct DQUOTE : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '"' > {};
struct HEXDIG : internal::ranges< internal::peek_char, '0', '9', 'a', 'f', 'A', 'F' > {};
struct HTAB : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\t' > {};
struct LF : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, '\n' > {};
struct LWSP : internal::star< internal::sor< internal::string< '\r', '\n' >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > >, internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > > {};
struct OCTET : internal::any< internal::peek_char > {};
struct SP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ' > {};
struct VCHAR : internal::range< internal::result_on_found::SUCCESS, internal::peek_char, char( 33 ), char( 126 ) > {};
struct WSP : internal::one< internal::result_on_found::SUCCESS, internal::peek_char, ' ', '\t' > {};
// clang-format on
} // namespace abnf
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,75 @@
// Copyright (c) 2015-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ALPHABET_HPP
#define TAO_PEGTL_CONTRIB_ALPHABET_HPP
#include "../config.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace alphabet
{
static const int a = 'a';
static const int b = 'b';
static const int c = 'c';
static const int d = 'd';
static const int e = 'e';
static const int f = 'f';
static const int g = 'g';
static const int h = 'h';
static const int i = 'i';
static const int j = 'j';
static const int k = 'k';
static const int l = 'l';
static const int m = 'm';
static const int n = 'n';
static const int o = 'o';
static const int p = 'p';
static const int q = 'q';
static const int r = 'r';
static const int s = 's';
static const int t = 't';
static const int u = 'u';
static const int v = 'v';
static const int w = 'w';
static const int x = 'x';
static const int y = 'y';
static const int z = 'z';
static const int A = 'A';
static const int B = 'B';
static const int C = 'C';
static const int D = 'D';
static const int E = 'E';
static const int F = 'F';
static const int G = 'G';
static const int H = 'H';
static const int I = 'I';
static const int J = 'J';
static const int K = 'K';
static const int L = 'L';
static const int M = 'M';
static const int N = 'N';
static const int O = 'O';
static const int P = 'P';
static const int Q = 'Q';
static const int R = 'R';
static const int S = 'S';
static const int T = 'T';
static const int U = 'U';
static const int V = 'V';
static const int W = 'W';
static const int X = 'X';
static const int Y = 'Y';
static const int Z = 'Z';
} // namespace alphabet
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,101 @@
// Copyright (c) 2015-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_CHANGES_HPP
#define TAO_PEGTL_CONTRIB_CHANGES_HPP
#include "../config.hpp"
#include "../normal.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
struct dummy_disabled_state
{
template< typename... Ts >
void success( Ts&&... /*unused*/ ) const noexcept
{
}
};
template< bool >
struct conditional;
template<>
struct conditional< true >
{
template< typename R, typename >
using type = R;
};
template<>
struct conditional< false >
{
template< typename, typename R >
using type = R;
};
template< apply_mode A, typename State >
using state_disable_helper = typename conditional< A == apply_mode::ACTION >::template type< State, dummy_disabled_state >;
} // namespace internal
template< typename Rule, typename State, template< typename... > class Base = normal >
struct change_state
: public Base< Rule >
{
template< apply_mode A,
rewind_mode M,
template< typename... > class Action,
template< typename... > class Control,
typename Input,
typename... States >
static bool match( Input& in, States&&... st )
{
internal::state_disable_helper< A, State > s;
if( Base< Rule >::template match< A, M, Action, Control >( in, s ) ) {
s.success( st... );
return true;
}
return false;
}
};
template< typename Rule, template< typename... > class Action, template< typename... > class Base = normal >
struct change_action
: public Base< Rule >
{
template< apply_mode A,
rewind_mode M,
template< typename... > class,
template< typename... > class Control,
typename Input,
typename... States >
static bool match( Input& in, States&&... st )
{
return Base< Rule >::template match< A, M, Action, Control >( in, st... );
}
};
template< template< typename... > class Action, template< typename... > class Base >
struct change_both_helper
{
template< typename T >
using change_action = change_action< T, Action, Base >;
};
template< typename Rule, typename State, template< typename... > class Action, template< typename... > class Base = normal >
struct change_state_and_action
: public change_state< Rule, State, change_both_helper< Action, Base >::template change_action >
{
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,58 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_COUNTER_HPP
#define TAO_PEGTL_CONTRIB_COUNTER_HPP
#include <map>
#include <string>
#include "../config.hpp"
#include "../normal.hpp"
#include "../internal/demangle.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
struct counter_data
{
unsigned start = 0;
unsigned success = 0;
unsigned failure = 0;
};
struct counter_state
{
std::map< std::string, counter_data > counts;
};
template< typename Rule >
struct counter
: normal< Rule >
{
template< typename Input >
static void start( const Input& /*unused*/, counter_state& ts )
{
++ts.counts[ internal::demangle< Rule >() ].start;
}
template< typename Input >
static void success( const Input& /*unused*/, counter_state& ts )
{
++ts.counts[ internal::demangle< Rule >() ].success;
}
template< typename Input >
static void failure( const Input& /*unused*/, counter_state& ts )
{
++ts.counts[ internal::demangle< Rule >() ].failure;
}
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,151 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_HTTP_HPP
#define TAO_PEGTL_CONTRIB_HTTP_HPP
#include "../ascii.hpp"
#include "../config.hpp"
#include "../rules.hpp"
#include "../utf8.hpp"
#include "abnf.hpp"
#include "uri.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace http
{
// HTTP 1.1 grammar according to RFC 7230.
// This grammar is a direct PEG translation of the original HTTP grammar.
// It should be considered experimental -- in case of any issues, in particular
// missing rules for attached actions, please contact the developers.
using OWS = star< abnf::WSP >; // optional whitespace
using RWS = plus< abnf::WSP >; // required whitespace
using BWS = OWS; // "bad" whitespace
// cppcheck-suppress constStatement
using obs_text = not_range< 0x00, 0x7F >;
using obs_fold = seq< abnf::CRLF, plus< abnf::WSP > >;
// clang-format off
struct tchar : sor< abnf::ALPHA, abnf::DIGIT, one< '!', '#', '$', '%', '&', '\'', '*', '+', '-', '.', '^', '_', '`', '|', '~' > > {};
struct token : plus< tchar > {};
struct field_name : token {};
struct field_vchar : sor< abnf::VCHAR, obs_text > {};
struct field_content : list< field_vchar, plus< abnf::WSP > > {};
struct field_value : star< sor< field_content, obs_fold > > {};
struct header_field : seq< field_name, one< ':' >, OWS, field_value, OWS > {};
struct method : token {};
struct absolute_path : plus< one< '/' >, uri::segment > {};
struct origin_form : seq< absolute_path, uri::opt_query > {};
struct absolute_form : uri::absolute_URI {};
struct authority_form : uri::authority {};
struct asterisk_form : one< '*' > {};
struct request_target : sor< origin_form, absolute_form, authority_form, asterisk_form > {};
struct status_code : rep< 3, abnf::DIGIT > {};
struct reason_phrase : star< sor< abnf::VCHAR, obs_text, abnf::WSP > > {};
struct HTTP_version : if_must< string< 'H', 'T', 'T', 'P', '/' >, abnf::DIGIT, one< '.' >, abnf::DIGIT > {};
struct request_line : if_must< method, abnf::SP, request_target, abnf::SP, HTTP_version, abnf::CRLF > {};
struct status_line : if_must< HTTP_version, abnf::SP, status_code, abnf::SP, reason_phrase, abnf::CRLF > {};
struct start_line : sor< status_line, request_line > {};
struct message_body : star< abnf::OCTET > {};
struct HTTP_message : seq< start_line, star< header_field, abnf::CRLF >, abnf::CRLF, opt< message_body > > {};
struct Content_Length : plus< abnf::DIGIT > {};
struct uri_host : uri::host {};
struct port : uri::port {};
struct Host : seq< uri_host, opt< one< ':' >, port > > {};
// PEG are different from CFGs! (this replaces ctext and qdtext)
using text = sor< abnf::HTAB, range< 0x20, 0x7E >, obs_text >;
struct quoted_pair : if_must< one< '\\' >, sor< abnf::VCHAR, obs_text, abnf::WSP > > {};
struct quoted_string : if_must< abnf::DQUOTE, until< abnf::DQUOTE, sor< quoted_pair, text > > > {};
struct transfer_parameter : seq< token, BWS, one< '=' >, BWS, sor< token, quoted_string > > {};
struct transfer_extension : seq< token, star< OWS, one< ';' >, OWS, transfer_parameter > > {};
struct transfer_coding : sor< istring< 'c', 'h', 'u', 'n', 'k', 'e', 'd' >,
istring< 'c', 'o', 'm', 'p', 'r', 'e', 's', 's' >,
istring< 'd', 'e', 'f', 'l', 'a', 't', 'e' >,
istring< 'g', 'z', 'i', 'p' >,
transfer_extension > {};
struct rank : sor< seq< one< '0' >, opt< one< '.' >, rep_opt< 3, abnf::DIGIT > > >,
seq< one< '1' >, opt< one< '.' >, rep_opt< 3, one< '0' > > > > > {};
struct t_ranking : seq< OWS, one< ';' >, OWS, one< 'q', 'Q' >, one< '=' >, rank > {};
struct t_codings : sor< istring< 't', 'r', 'a', 'i', 'l', 'e', 'r', 's' >, seq< transfer_coding, opt< t_ranking > > > {};
struct TE : opt< sor< one< ',' >, t_codings >, star< OWS, one< ',' >, opt< OWS, t_codings > > > {};
template< typename T >
using make_comma_list = seq< star< one< ',' >, OWS >, T, star< OWS, one< ',' >, opt< OWS, T > > >;
struct connection_option : token {};
struct Connection : make_comma_list< connection_option > {};
struct Trailer : make_comma_list< field_name > {};
struct Transfer_Encoding : make_comma_list< transfer_coding > {};
struct protocol_name : token {};
struct protocol_version : token {};
struct protocol : seq< protocol_name, opt< one< '/' >, protocol_version > > {};
struct Upgrade : make_comma_list< protocol > {};
struct pseudonym : token {};
struct received_protocol : seq< opt< protocol_name, one< '/' > >, protocol_version > {};
struct received_by : sor< seq< uri_host, opt< one< ':' >, port > >, pseudonym > {};
struct comment : if_must< one< '(' >, until< one< ')' >, sor< comment, quoted_pair, text > > > {};
struct Via : make_comma_list< seq< received_protocol, RWS, received_by, opt< RWS, comment > > > {};
struct http_URI : if_must< istring< 'h', 't', 't', 'p', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {};
struct https_URI : if_must< istring< 'h', 't', 't', 'p', 's', ':', '/', '/' >, uri::authority, uri::path_abempty, uri::opt_query, uri::opt_fragment > {};
struct partial_URI : seq< uri::relative_part, uri::opt_query > {};
struct chunk_size : plus< abnf::HEXDIG > {};
struct chunk_ext_name : token {};
struct chunk_ext_val : sor< quoted_string, token > {};
struct chunk_ext : star_must< one< ';' >, chunk_ext_name, if_must< one< '=' >, chunk_ext_val > > {};
struct chunk_data : until< at< abnf::CRLF >, abnf::OCTET > {};
struct chunk : seq< chunk_size, opt< chunk_ext >, abnf::CRLF, chunk_data, abnf::CRLF > {};
struct last_chunk : seq< plus< one< '0' > >, opt< chunk_ext >, abnf::CRLF > {};
struct trailer_part : star< header_field, abnf::CRLF > {};
struct chunked_body : seq< until< last_chunk, chunk >, trailer_part, abnf::CRLF > {};
// clang-format on
} // namespace http
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,76 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ICU_INTERNAL_HPP
#define TAO_PEGTL_CONTRIB_ICU_INTERNAL_HPP
#include <unicode/uchar.h>
#include "../../config.hpp"
#include "../../analysis/generic.hpp"
#include "../../internal/skip_control.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
namespace icu
{
template< typename Peek, UProperty P, bool V = true >
struct binary_property
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< typename Input >
static bool match( Input& in ) noexcept( noexcept( Peek::peek( in ) ) )
{
if( const auto r = Peek::peek( in ) ) {
if( u_hasBinaryProperty( r.data, P ) == V ) {
in.bump( r.size );
return true;
}
}
return false;
}
};
template< typename Peek, UProperty P, int V >
struct property_value
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< typename Input >
static bool match( Input& in ) noexcept( noexcept( Peek::peek( in ) ) )
{
if( const auto r = Peek::peek( in ) ) {
if( u_getIntPropertyValue( r.data, P ) == V ) {
in.bump( r.size );
return true;
}
}
return false;
}
};
} // namespace icu
template< typename Peek, UProperty P, bool V >
struct skip_control< icu::binary_property< Peek, P, V > > : std::true_type
{
};
template< typename Peek, UProperty P, int V >
struct skip_control< icu::property_value< Peek, P, V > > : std::true_type
{
};
} // namespace internal
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,212 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ICU_UTF16_HPP
#define TAO_PEGTL_CONTRIB_ICU_UTF16_HPP
#include "internal.hpp"
#include "../../config.hpp"
#include "../../utf16.hpp"
#include "../../internal/peek_utf16.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace utf16_be
{
namespace icu
{
template< UProperty P, bool V = true >
struct binary_property
: internal::icu::binary_property< internal::peek_utf16_be, P, V >
{
};
template< UProperty P, int V >
struct property_value
: internal::icu::property_value< internal::peek_utf16_be, P, V >
{
};
// clang-format off
struct alphabetic : binary_property< UCHAR_ALPHABETIC > {};
struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {};
struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {};
struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {};
struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {};
struct dash : binary_property< UCHAR_DASH > {};
struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {};
struct deprecated : binary_property< UCHAR_DEPRECATED > {};
struct diacritic : binary_property< UCHAR_DIACRITIC > {};
struct extender : binary_property< UCHAR_EXTENDER > {};
struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {};
struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {};
struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {};
struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {};
struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {};
struct hyphen : binary_property< UCHAR_HYPHEN > {};
struct id_continue : binary_property< UCHAR_ID_CONTINUE > {};
struct id_start : binary_property< UCHAR_ID_START > {};
struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {};
struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {};
struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {};
struct join_control : binary_property< UCHAR_JOIN_CONTROL > {};
struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {};
struct lowercase : binary_property< UCHAR_LOWERCASE > {};
struct math : binary_property< UCHAR_MATH > {};
struct nfc_inert : binary_property< UCHAR_NFC_INERT > {};
struct nfd_inert : binary_property< UCHAR_NFD_INERT > {};
struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {};
struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {};
struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {};
struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {};
struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {};
struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {};
struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {};
struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {};
struct posix_print : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {};
struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {};
struct radical : binary_property< UCHAR_RADICAL > {};
struct s_term : binary_property< UCHAR_S_TERM > {};
struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {};
struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {};
struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {};
struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {};
struct uppercase : binary_property< UCHAR_UPPERCASE > {};
struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {};
struct white_space : binary_property< UCHAR_WHITE_SPACE > {};
struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {};
struct xid_start : binary_property< UCHAR_XID_START > {};
template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {};
template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {};
template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {};
template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {};
template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {};
template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {};
template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {};
template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {};
template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {};
template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {};
// UNormalizationCheckResult requires an additional header <unicode/unorm2.h>:
// template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {};
template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {};
template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {};
template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {};
template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {};
// clang-format on
} // namespace icu
} // namespace utf16_be
namespace utf16_le
{
namespace icu
{
template< UProperty P, bool V = true >
struct binary_property
: internal::icu::binary_property< internal::peek_utf16_le, P, V >
{
};
template< UProperty P, int V >
struct property_value
: internal::icu::property_value< internal::peek_utf16_le, P, V >
{
};
// clang-format off
struct alphabetic : binary_property< UCHAR_ALPHABETIC > {};
struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {};
struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {};
struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {};
struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {};
struct dash : binary_property< UCHAR_DASH > {};
struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {};
struct deprecated : binary_property< UCHAR_DEPRECATED > {};
struct diacritic : binary_property< UCHAR_DIACRITIC > {};
struct extender : binary_property< UCHAR_EXTENDER > {};
struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {};
struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {};
struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {};
struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {};
struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {};
struct hyphen : binary_property< UCHAR_HYPHEN > {};
struct id_continue : binary_property< UCHAR_ID_CONTINUE > {};
struct id_start : binary_property< UCHAR_ID_START > {};
struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {};
struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {};
struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {};
struct join_control : binary_property< UCHAR_JOIN_CONTROL > {};
struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {};
struct lowercase : binary_property< UCHAR_LOWERCASE > {};
struct math : binary_property< UCHAR_MATH > {};
struct nfc_inert : binary_property< UCHAR_NFC_INERT > {};
struct nfd_inert : binary_property< UCHAR_NFD_INERT > {};
struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {};
struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {};
struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {};
struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {};
struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {};
struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {};
struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {};
struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {};
struct posix_print : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {};
struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {};
struct radical : binary_property< UCHAR_RADICAL > {};
struct s_term : binary_property< UCHAR_S_TERM > {};
struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {};
struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {};
struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {};
struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {};
struct uppercase : binary_property< UCHAR_UPPERCASE > {};
struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {};
struct white_space : binary_property< UCHAR_WHITE_SPACE > {};
struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {};
struct xid_start : binary_property< UCHAR_XID_START > {};
template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {};
template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {};
template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {};
template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {};
template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {};
template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {};
template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {};
template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {};
template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {};
template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {};
// UNormalizationCheckResult requires an additional header <unicode/unorm2.h>:
// template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {};
template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {};
template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {};
template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {};
template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {};
// clang-format on
} // namespace icu
} // namespace utf16_le
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,212 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ICU_UTF32_HPP
#define TAO_PEGTL_CONTRIB_ICU_UTF32_HPP
#include "internal.hpp"
#include "../../config.hpp"
#include "../../utf32.hpp"
#include "../../internal/peek_utf32.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace utf32_be
{
namespace icu
{
template< UProperty P, bool V = true >
struct binary_property
: internal::icu::binary_property< internal::peek_utf32_be, P, V >
{
};
template< UProperty P, int V >
struct property_value
: internal::icu::property_value< internal::peek_utf32_be, P, V >
{
};
// clang-format off
struct alphabetic : binary_property< UCHAR_ALPHABETIC > {};
struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {};
struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {};
struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {};
struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {};
struct dash : binary_property< UCHAR_DASH > {};
struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {};
struct deprecated : binary_property< UCHAR_DEPRECATED > {};
struct diacritic : binary_property< UCHAR_DIACRITIC > {};
struct extender : binary_property< UCHAR_EXTENDER > {};
struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {};
struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {};
struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {};
struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {};
struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {};
struct hyphen : binary_property< UCHAR_HYPHEN > {};
struct id_continue : binary_property< UCHAR_ID_CONTINUE > {};
struct id_start : binary_property< UCHAR_ID_START > {};
struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {};
struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {};
struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {};
struct join_control : binary_property< UCHAR_JOIN_CONTROL > {};
struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {};
struct lowercase : binary_property< UCHAR_LOWERCASE > {};
struct math : binary_property< UCHAR_MATH > {};
struct nfc_inert : binary_property< UCHAR_NFC_INERT > {};
struct nfd_inert : binary_property< UCHAR_NFD_INERT > {};
struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {};
struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {};
struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {};
struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {};
struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {};
struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {};
struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {};
struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {};
struct posix_print : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {};
struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {};
struct radical : binary_property< UCHAR_RADICAL > {};
struct s_term : binary_property< UCHAR_S_TERM > {};
struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {};
struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {};
struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {};
struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {};
struct uppercase : binary_property< UCHAR_UPPERCASE > {};
struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {};
struct white_space : binary_property< UCHAR_WHITE_SPACE > {};
struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {};
struct xid_start : binary_property< UCHAR_XID_START > {};
template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {};
template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {};
template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {};
template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {};
template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {};
template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {};
template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {};
template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {};
template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {};
template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {};
// UNormalizationCheckResult requires an additional header <unicode/unorm2.h>:
// template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {};
template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {};
template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {};
template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {};
template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {};
// clang-format on
} // namespace icu
} // namespace utf32_be
namespace utf32_le
{
namespace icu
{
template< UProperty P, bool V = true >
struct binary_property
: internal::icu::binary_property< internal::peek_utf32_le, P, V >
{
};
template< UProperty P, int V >
struct property_value
: internal::icu::property_value< internal::peek_utf32_le, P, V >
{
};
// clang-format off
struct alphabetic : binary_property< UCHAR_ALPHABETIC > {};
struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {};
struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {};
struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {};
struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {};
struct dash : binary_property< UCHAR_DASH > {};
struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {};
struct deprecated : binary_property< UCHAR_DEPRECATED > {};
struct diacritic : binary_property< UCHAR_DIACRITIC > {};
struct extender : binary_property< UCHAR_EXTENDER > {};
struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {};
struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {};
struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {};
struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {};
struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {};
struct hyphen : binary_property< UCHAR_HYPHEN > {};
struct id_continue : binary_property< UCHAR_ID_CONTINUE > {};
struct id_start : binary_property< UCHAR_ID_START > {};
struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {};
struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {};
struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {};
struct join_control : binary_property< UCHAR_JOIN_CONTROL > {};
struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {};
struct lowercase : binary_property< UCHAR_LOWERCASE > {};
struct math : binary_property< UCHAR_MATH > {};
struct nfc_inert : binary_property< UCHAR_NFC_INERT > {};
struct nfd_inert : binary_property< UCHAR_NFD_INERT > {};
struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {};
struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {};
struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {};
struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {};
struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {};
struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {};
struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {};
struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {};
struct posix_print : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {};
struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {};
struct radical : binary_property< UCHAR_RADICAL > {};
struct s_term : binary_property< UCHAR_S_TERM > {};
struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {};
struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {};
struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {};
struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {};
struct uppercase : binary_property< UCHAR_UPPERCASE > {};
struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {};
struct white_space : binary_property< UCHAR_WHITE_SPACE > {};
struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {};
struct xid_start : binary_property< UCHAR_XID_START > {};
template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {};
template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {};
template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {};
template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {};
template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {};
template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {};
template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {};
template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {};
template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {};
template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {};
// UNormalizationCheckResult requires an additional header <unicode/unorm2.h>:
// template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {};
template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {};
template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {};
template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {};
template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {};
// clang-format on
} // namespace icu
} // namespace utf32_le
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,117 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_ICU_UTF8_HPP
#define TAO_PEGTL_CONTRIB_ICU_UTF8_HPP
#include "internal.hpp"
#include "../../config.hpp"
#include "../../utf8.hpp"
#include "../../internal/peek_utf8.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace utf8
{
namespace icu
{
template< UProperty P, bool V = true >
struct binary_property
: internal::icu::binary_property< internal::peek_utf8, P, V >
{
};
template< UProperty P, int V >
struct property_value
: internal::icu::property_value< internal::peek_utf8, P, V >
{
};
// clang-format off
struct alphabetic : binary_property< UCHAR_ALPHABETIC > {};
struct ascii_hex_digit : binary_property< UCHAR_ASCII_HEX_DIGIT > {};
struct bidi_control : binary_property< UCHAR_BIDI_CONTROL > {};
struct bidi_mirrored : binary_property< UCHAR_BIDI_MIRRORED > {};
struct case_sensitive : binary_property< UCHAR_CASE_SENSITIVE > {};
struct dash : binary_property< UCHAR_DASH > {};
struct default_ignorable_code_point : binary_property< UCHAR_DEFAULT_IGNORABLE_CODE_POINT > {};
struct deprecated : binary_property< UCHAR_DEPRECATED > {};
struct diacritic : binary_property< UCHAR_DIACRITIC > {};
struct extender : binary_property< UCHAR_EXTENDER > {};
struct full_composition_exclusion : binary_property< UCHAR_FULL_COMPOSITION_EXCLUSION > {};
struct grapheme_base : binary_property< UCHAR_GRAPHEME_BASE > {};
struct grapheme_extend : binary_property< UCHAR_GRAPHEME_EXTEND > {};
struct grapheme_link : binary_property< UCHAR_GRAPHEME_LINK > {};
struct hex_digit : binary_property< UCHAR_HEX_DIGIT > {};
struct hyphen : binary_property< UCHAR_HYPHEN > {};
struct id_continue : binary_property< UCHAR_ID_CONTINUE > {};
struct id_start : binary_property< UCHAR_ID_START > {};
struct ideographic : binary_property< UCHAR_IDEOGRAPHIC > {};
struct ids_binary_operator : binary_property< UCHAR_IDS_BINARY_OPERATOR > {};
struct ids_trinary_operator : binary_property< UCHAR_IDS_TRINARY_OPERATOR > {};
struct join_control : binary_property< UCHAR_JOIN_CONTROL > {};
struct logical_order_exception : binary_property< UCHAR_LOGICAL_ORDER_EXCEPTION > {};
struct lowercase : binary_property< UCHAR_LOWERCASE > {};
struct math : binary_property< UCHAR_MATH > {};
struct nfc_inert : binary_property< UCHAR_NFC_INERT > {};
struct nfd_inert : binary_property< UCHAR_NFD_INERT > {};
struct nfkc_inert : binary_property< UCHAR_NFKC_INERT > {};
struct nfkd_inert : binary_property< UCHAR_NFKD_INERT > {};
struct noncharacter_code_point : binary_property< UCHAR_NONCHARACTER_CODE_POINT > {};
struct pattern_syntax : binary_property< UCHAR_PATTERN_SYNTAX > {};
struct pattern_white_space : binary_property< UCHAR_PATTERN_WHITE_SPACE > {};
struct posix_alnum : binary_property< UCHAR_POSIX_ALNUM > {};
struct posix_blank : binary_property< UCHAR_POSIX_BLANK > {};
struct posix_graph : binary_property< UCHAR_POSIX_GRAPH > {};
struct posix_print : binary_property< UCHAR_POSIX_PRINT > {};
struct posix_xdigit : binary_property< UCHAR_POSIX_XDIGIT > {};
struct quotation_mark : binary_property< UCHAR_QUOTATION_MARK > {};
struct radical : binary_property< UCHAR_RADICAL > {};
struct s_term : binary_property< UCHAR_S_TERM > {};
struct segment_starter : binary_property< UCHAR_SEGMENT_STARTER > {};
struct soft_dotted : binary_property< UCHAR_SOFT_DOTTED > {};
struct terminal_punctuation : binary_property< UCHAR_TERMINAL_PUNCTUATION > {};
struct unified_ideograph : binary_property< UCHAR_UNIFIED_IDEOGRAPH > {};
struct uppercase : binary_property< UCHAR_UPPERCASE > {};
struct variation_selector : binary_property< UCHAR_VARIATION_SELECTOR > {};
struct white_space : binary_property< UCHAR_WHITE_SPACE > {};
struct xid_continue : binary_property< UCHAR_XID_CONTINUE > {};
struct xid_start : binary_property< UCHAR_XID_START > {};
template< UCharDirection V > struct bidi_class : property_value< UCHAR_BIDI_CLASS, V > {};
template< UBlockCode V > struct block : property_value< UCHAR_BLOCK, V > {};
template< UDecompositionType V > struct decomposition_type : property_value< UCHAR_DECOMPOSITION_TYPE, V > {};
template< UEastAsianWidth V > struct east_asian_width : property_value< UCHAR_EAST_ASIAN_WIDTH, V > {};
template< UCharCategory V > struct general_category : property_value< UCHAR_GENERAL_CATEGORY, V > {};
template< UGraphemeClusterBreak V > struct grapheme_cluster_break : property_value< UCHAR_GRAPHEME_CLUSTER_BREAK, V > {};
template< UHangulSyllableType V > struct hangul_syllable_type : property_value< UCHAR_HANGUL_SYLLABLE_TYPE, V > {};
template< UJoiningGroup V > struct joining_group : property_value< UCHAR_JOINING_GROUP, V > {};
template< UJoiningType V > struct joining_type : property_value< UCHAR_JOINING_TYPE, V > {};
template< ULineBreak V > struct line_break : property_value< UCHAR_LINE_BREAK, V > {};
// UNormalizationCheckResult requires an additional header <unicode/unorm2.h>:
// template< UNormalizationCheckResult V > struct nfc_quick_check : property_value< UCHAR_NFC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfd_quick_check : property_value< UCHAR_NFD_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkc_quick_check : property_value< UCHAR_NFKC_QUICK_CHECK, V > {};
// template< UNormalizationCheckResult V > struct nfkd_quick_check : property_value< UCHAR_NFKD_QUICK_CHECK, V > {};
template< UNumericType V > struct numeric_type : property_value< UCHAR_NUMERIC_TYPE, V > {};
template< USentenceBreak V > struct sentence_break : property_value< UCHAR_SENTENCE_BREAK, V > {};
template< UWordBreakValues V > struct word_break : property_value< UCHAR_WORD_BREAK, V > {};
template< std::uint8_t V > struct canonical_combining_class : property_value< UCHAR_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct lead_canonical_combining_class : property_value< UCHAR_LEAD_CANONICAL_COMBINING_CLASS, V > {};
template< std::uint8_t V > struct trail_canonical_combining_class : property_value< UCHAR_TRAIL_CANONICAL_COMBINING_CLASS, V > {};
// clang-format on
} // namespace icu
} // namespace utf8
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,108 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_INTEGER_HPP
#define TAO_PEGTL_CONTRIB_INTEGER_HPP
#include <limits>
#include <type_traits>
#include "../ascii.hpp"
#include "../parse_error.hpp"
#include "../rules.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace integer
{
namespace internal
{
template< typename I, I Limit, typename Input >
I actual_convert( const Input& in, std::size_t index )
{
static constexpr I cutoff = Limit / 10;
static constexpr I cutlim = Limit % 10;
I out = in.peek_char( index ) - '0';
while( ++index < in.size() ) {
const I c = in.peek_char( index ) - '0';
if( ( out > cutoff ) || ( ( out == cutoff ) && ( c > cutlim ) ) ) {
throw parse_error( "integer out of range", in );
}
out *= 10;
out += c;
}
return out;
}
template< typename I, typename Input >
I convert_positive( const Input& in, std::size_t index )
{
static constexpr I limit = std::numeric_limits< I >::max();
return actual_convert< I, limit >( in, index );
}
template< typename I, typename Input >
I convert_negative( const Input& in, std::size_t index )
{
using U = typename std::make_unsigned< I >::type;
static constexpr U limit = static_cast< U >( std::numeric_limits< I >::max() ) + 1;
return static_cast< I >( ~actual_convert< U, limit >( in, index ) ) + 1;
}
} // namespace internal
struct unsigned_rule
: plus< digit >
{
};
struct unsigned_action
{
// Assumes that 'in' contains a non-empty sequence of ASCII digits.
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
using T = typename std::decay< decltype( st.converted ) >::type;
static_assert( std::is_integral< T >::value, "need integral type" );
static_assert( std::is_unsigned< T >::value, "need unsigned type" );
st.converted = internal::convert_positive< T >( in, 0 );
}
};
struct signed_rule
: seq< opt< one< '+', '-' > >, plus< digit > >
{
};
struct signed_action
{
// Assumes that 'in' contains a non-empty sequence of ASCII digits,
// with optional leading sign; with sign, in.size() must be >= 2.
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
using T = typename std::decay< decltype( st.converted ) >::type;
static_assert( std::is_integral< T >::value, "need integral type" );
static_assert( std::is_signed< T >::value, "need signed type" );
const auto c = in.peek_char();
if( c == '-' ) {
st.converted = internal::convert_negative< T >( in, 1 );
}
else {
st.converted = internal::convert_positive< T >( in, std::size_t( c == '+' ) );
}
}
};
} // namespace integer
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,98 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_JSON_HPP
#define TAO_PEGTL_CONTRIB_JSON_HPP
#include "../ascii.hpp"
#include "../config.hpp"
#include "../rules.hpp"
#include "../utf8.hpp"
#include "abnf.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace json
{
// JSON grammar according to RFC 8259
// clang-format off
struct ws : one< ' ', '\t', '\n', '\r' > {};
template< typename R, typename P = ws >
struct padr : internal::seq< R, internal::star< P > > {};
struct begin_array : padr< one< '[' > > {};
struct begin_object : padr< one< '{' > > {};
struct end_array : one< ']' > {};
struct end_object : one< '}' > {};
struct name_separator : pad< one< ':' >, ws > {};
struct value_separator : padr< one< ',' > > {};
struct false_ : string< 'f', 'a', 'l', 's', 'e' > {};
struct null : string< 'n', 'u', 'l', 'l' > {};
struct true_ : string< 't', 'r', 'u', 'e' > {};
struct digits : plus< abnf::DIGIT > {};
struct exp : seq< one< 'e', 'E' >, opt< one< '-', '+'> >, must< digits > > {};
struct frac : if_must< one< '.' >, digits > {};
struct int_ : sor< one< '0' >, digits > {};
struct number : seq< opt< one< '-' > >, int_, opt< frac >, opt< exp > > {};
struct xdigit : abnf::HEXDIG {};
struct unicode : list< seq< one< 'u' >, rep< 4, must< xdigit > > >, one< '\\' > > {};
struct escaped_char : one< '"', '\\', '/', 'b', 'f', 'n', 'r', 't' > {};
struct escaped : sor< escaped_char, unicode > {};
struct unescaped : utf8::range< 0x20, 0x10FFFF > {};
struct char_ : if_then_else< one< '\\' >, must< escaped >, unescaped > {};
struct string_content : until< at< one< '"' > >, must< char_ > > {};
struct string : seq< one< '"' >, must< string_content >, any >
{
using content = string_content;
};
struct key_content : until< at< one< '"' > >, must< char_ > > {};
struct key : seq< one< '"' >, must< key_content >, any >
{
using content = key_content;
};
struct value;
struct array_element;
struct array_content : opt< list_must< array_element, value_separator > > {};
struct array : seq< begin_array, array_content, must< end_array > >
{
using begin = begin_array;
using end = end_array;
using element = array_element;
using content = array_content;
};
struct member : if_must< key, name_separator, value > {};
struct object_content : opt< list_must< member, value_separator > > {};
struct object : seq< begin_object, object_content, must< end_object > >
{
using begin = begin_object;
using end = end_object;
using element = member;
using content = object_content;
};
struct value : padr< sor< string, number, object, array, false_, true_, null > > {};
struct array_element : seq< value > {};
struct text : seq< star< ws >, value > {};
// clang-format on
} // namespace json
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,373 @@
// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#define TAO_PEGTL_CONTRIB_PARSE_TREE_HPP
#include <cassert>
#include <memory>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include <vector>
#include "../config.hpp"
#include "../normal.hpp"
#include "../nothing.hpp"
#include "../parse.hpp"
#include "../internal/demangle.hpp"
#include "../internal/iterator.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace parse_tree
{
template< typename T >
struct basic_node
{
using node_t = T;
using children_t = std::vector< std::unique_ptr< node_t > >;
children_t children;
const std::type_info* id = nullptr;
std::string source;
TAO_PEGTL_NAMESPACE::internal::iterator m_begin;
TAO_PEGTL_NAMESPACE::internal::iterator m_end;
// each node will be default constructed
basic_node() = default;
// no copy/move is necessary
// (nodes are always owned/handled by a std::unique_ptr)
basic_node( const basic_node& ) = delete;
basic_node( basic_node&& ) = delete;
~basic_node() = default;
// no assignment either
basic_node& operator=( const basic_node& ) = delete;
basic_node& operator=( basic_node&& ) = delete;
bool is_root() const noexcept
{
return id == nullptr;
}
template< typename U >
bool is() const noexcept
{
return id == &typeid( U );
}
std::string name() const
{
assert( !is_root() );
return TAO_PEGTL_NAMESPACE::internal::demangle( id->name() );
}
position begin() const
{
return position( m_begin, source );
}
position end() const
{
return position( m_end, source );
}
bool has_content() const noexcept
{
return m_end.data != nullptr;
}
std::string content() const
{
assert( has_content() );
return std::string( m_begin.data, m_end.data );
}
template< typename... States >
void remove_content( States&&... /*unused*/ ) noexcept
{
m_end.reset();
}
// all non-root nodes are initialized by calling this method
template< typename Rule, typename Input, typename... States >
void start( const Input& in, States&&... /*unused*/ )
{
id = &typeid( Rule );
source = in.source();
m_begin = in.iterator();
}
// if parsing of the rule succeeded, this method is called
template< typename Rule, typename Input, typename... States >
void success( const Input& in, States&&... /*unused*/ ) noexcept
{
m_end = in.iterator();
}
// if parsing of the rule failed, this method is called
template< typename Rule, typename Input, typename... States >
void failure( const Input& /*unused*/, States&&... /*unused*/ ) noexcept
{
}
// if parsing succeeded and the (optional) transform call
// did not discard the node, it is appended to its parent.
// note that "child" is the node whose Rule just succeeded
// and "*this" is the parent where the node should be appended.
template< typename... States >
void emplace_back( std::unique_ptr< node_t > child, States&&... /*unused*/ )
{
assert( child );
children.emplace_back( std::move( child ) );
}
};
struct node
: basic_node< node >
{
};
namespace internal
{
template< typename Node >
struct state
{
std::vector< std::unique_ptr< Node > > stack;
state()
{
emplace_back();
}
void emplace_back()
{
stack.emplace_back( std::unique_ptr< Node >( new Node ) ); // NOLINT: std::make_unique requires C++14
}
std::unique_ptr< Node >& back() noexcept
{
return stack.back();
}
void pop_back() noexcept
{
return stack.pop_back();
}
};
template< typename Node, typename S, typename = void >
struct transform
{
template< typename... States >
static void call( std::unique_ptr< Node >& /*unused*/, States&&... /*unused*/ ) noexcept
{
}
};
template< typename Node, typename S >
struct transform< Node, S, decltype( S::transform( std::declval< std::unique_ptr< Node >& >() ), void() ) >
{
template< typename... States >
static void call( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( S::transform( n ) ) )
{
S::transform( n, st... );
}
};
template< template< typename > class S, template< typename > class C >
struct make_control
{
template< typename Rule, bool >
struct control;
template< typename Rule >
using type = control< Rule, S< Rule >::value >;
};
template< typename Control, template< typename... > class Action, typename Input, typename... States >
struct return_type_apply0
{
using type = decltype( Control::template apply0< Action >( std::declval< const Input& >(), std::declval< States&& >()... ) );
};
template< typename Control, template< typename... > class Action, typename Iterator, typename Input, typename... States >
struct return_type_apply
{
using type = decltype( Control::template apply< Action >( std::declval< const Iterator& >(), std::declval< const Input& >(), std::declval< States&& >()... ) );
};
template< template< typename > class S, template< typename > class C >
template< typename Rule >
struct make_control< S, C >::control< Rule, false >
: C< Rule >
{
template< typename Input, typename Node, typename... States >
static void start( const Input& in, state< Node >& state, States&&... st )
{
C< Rule >::start( in, st... );
state.emplace_back();
}
template< typename Input, typename Node, typename... States >
static void success( const Input& in, state< Node >& state, States&&... st )
{
C< Rule >::success( in, st... );
auto n = std::move( state.back() );
state.pop_back();
for( auto& c : n->children ) {
state.back()->children.emplace_back( std::move( c ) );
}
}
template< typename Input, typename Node, typename... States >
static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( C< Rule >::failure( in, st... ) ) )
{
C< Rule >::failure( in, st... );
state.pop_back();
}
template< typename Input, typename Node, typename... States >
static void raise( const Input& in, state< Node >& /*unused*/, States&&... st )
{
C< Rule >::raise( in, st... );
}
template< template< typename... > class Action, typename Input, typename Node, typename... States >
static typename return_type_apply0< C< Rule >, Action, Input, States... >::type apply0( const Input& in, state< Node >& /*unused*/, States&&... st )
{
return C< Rule >::template apply0< Action >( in, st... );
}
template< template< typename... > class Action, typename Iterator, typename Input, typename Node, typename... States >
static typename return_type_apply< C< Rule >, Action, Iterator, Input, States... >::type apply( const Iterator& begin, const Input& in, state< Node >& /*unused*/, States&&... st )
{
return C< Rule >::template apply< Action >( begin, in, st... );
}
};
template< template< typename > class S, template< typename > class C >
template< typename Rule >
struct make_control< S, C >::control< Rule, true >
: C< Rule >
{
template< typename Input, typename Node, typename... States >
static void start( const Input& in, state< Node >& state, States&&... st )
{
C< Rule >::start( in, st... );
state.emplace_back();
state.back()->template start< Rule >( in, st... );
}
template< typename Input, typename Node, typename... States >
static void success( const Input& in, state< Node >& state, States&&... st )
{
C< Rule >::success( in, st... );
auto n = std::move( state.back() );
state.pop_back();
n->template success< Rule >( in, st... );
transform< Node, S< Rule > >::call( n, st... );
if( n ) {
state.back()->emplace_back( std::move( n ), st... );
}
}
template< typename Input, typename Node, typename... States >
static void failure( const Input& in, state< Node >& state, States&&... st ) noexcept( noexcept( C< Rule >::failure( in, st... ) ) && noexcept( std::declval< node& >().template failure< Rule >( in, st... ) ) )
{
C< Rule >::failure( in, st... );
state.back()->template failure< Rule >( in, st... );
state.pop_back();
}
template< typename Input, typename Node, typename... States >
static void raise( const Input& in, state< Node >& /*unused*/, States&&... st )
{
C< Rule >::raise( in, st... );
}
template< template< typename... > class Action, typename Input, typename Node, typename... States >
static typename return_type_apply0< C< Rule >, Action, Input, States... >::type apply0( const Input& in, state< Node >& /*unused*/, States&&... st )
{
return C< Rule >::template apply0< Action >( in, st... );
}
template< template< typename... > class Action, typename Iterator, typename Input, typename Node, typename... States >
static typename return_type_apply< C< Rule >, Action, Iterator, Input, States... >::type apply( const Iterator& begin, const Input& in, state< Node >& /*unused*/, States&&... st )
{
return C< Rule >::template apply< Action >( begin, in, st... );
}
};
template< typename >
struct store_all : std::true_type
{
};
} // namespace internal
// some nodes don't need to store their content
struct remove_content : std::true_type
{
template< typename Node, typename... States >
static void transform( std::unique_ptr< Node >& n, States&&... st ) noexcept( noexcept( n->Node::remove_content( st... ) ) )
{
n->remove_content( st... );
}
};
// if a node has only one child, replace the node with its child
struct fold_one : std::true_type
{
template< typename Node, typename... States >
static void transform( std::unique_ptr< Node >& n, States&&... /*unused*/ ) noexcept( noexcept( n->children.size(), n->children.front() ) )
{
if( n->children.size() == 1 ) {
n = std::move( n->children.front() );
}
}
};
// if a node has no children, discard the node
struct discard_empty : std::true_type
{
template< typename Node, typename... States >
static void transform( std::unique_ptr< Node >& n, States&&... /*unused*/ ) noexcept( noexcept( n->children.empty() ) )
{
if( n->children.empty() ) {
n.reset();
}
}
};
template< typename Rule, typename Node, template< typename > class S = internal::store_all, template< typename > class C = normal, typename Input, typename... States >
std::unique_ptr< Node > parse( Input&& in, States&&... st )
{
internal::state< Node > state;
if( !TAO_PEGTL_NAMESPACE::parse< Rule, nothing, internal::make_control< S, C >::template type >( in, state, st... ) ) {
return nullptr;
}
assert( state.stack.size() == 1 );
return std::move( state.back() );
}
template< typename Rule, template< typename > class S = internal::store_all, template< typename > class C = normal, typename Input, typename... States >
std::unique_ptr< node > parse( Input&& in, States&&... st )
{
return parse< Rule, node, S, C >( in, st... );
}
} // namespace parse_tree
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,223 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_RAW_STRING_HPP
#define TAO_PEGTL_CONTRIB_RAW_STRING_HPP
#include <cstddef>
#include <type_traits>
#include "../apply_mode.hpp"
#include "../config.hpp"
#include "../rewind_mode.hpp"
#include "../internal/bytes.hpp"
#include "../internal/eof.hpp"
#include "../internal/eol.hpp"
#include "../internal/must.hpp"
#include "../internal/not_at.hpp"
#include "../internal/rule_conjunction.hpp"
#include "../internal/seq.hpp"
#include "../internal/skip_control.hpp"
#include "../internal/star.hpp"
#include "../analysis/generic.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
template< char Open, char Marker >
struct raw_string_open
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< apply_mode A,
rewind_mode,
template< typename... > class Action,
template< typename... > class Control,
typename Input >
static bool match( Input& in, std::size_t& marker_size ) noexcept( noexcept( in.size( 0 ) ) )
{
if( in.empty() || ( in.peek_char( 0 ) != Open ) ) {
return false;
}
for( std::size_t i = 1; i < in.size( i + 1 ); ++i ) {
switch( const auto c = in.peek_char( i ) ) {
case Open:
marker_size = i + 1;
in.bump_in_this_line( marker_size );
eol::match( in );
return true;
case Marker:
break;
default:
return false;
}
}
return false;
}
};
template< char Open, char Marker >
struct skip_control< raw_string_open< Open, Marker > > : std::true_type
{
};
template< char Marker, char Close >
struct at_raw_string_close
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
template< apply_mode A,
rewind_mode,
template< typename... > class Action,
template< typename... > class Control,
typename Input >
static bool match( Input& in, const std::size_t& marker_size ) noexcept( noexcept( in.size( 0 ) ) )
{
if( in.size( marker_size ) < marker_size ) {
return false;
}
if( in.peek_char( 0 ) != Close ) {
return false;
}
if( in.peek_char( marker_size - 1 ) != Close ) {
return false;
}
for( std::size_t i = 0; i < ( marker_size - 2 ); ++i ) {
if( in.peek_char( i + 1 ) != Marker ) {
return false;
}
}
return true;
}
};
template< char Marker, char Close >
struct skip_control< at_raw_string_close< Marker, Close > > : std::true_type
{
};
template< typename Cond, typename... Rules >
struct raw_string_until;
template< typename Cond >
struct raw_string_until< Cond >
{
using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, bytes< 1 > >, Cond >;
template< apply_mode A,
rewind_mode M,
template< typename... > class Action,
template< typename... > class Control,
typename Input,
typename... States >
static bool match( Input& in, const std::size_t& marker_size, States&&... /*unused*/ )
{
auto m = in.template mark< M >();
while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, marker_size ) ) {
if( in.empty() ) {
return false;
}
in.bump();
}
return m( true );
}
};
template< typename Cond, typename... Rules >
struct raw_string_until
{
using analyze_t = analysis::generic< analysis::rule_type::SEQ, star< not_at< Cond >, not_at< eof >, Rules... >, Cond >;
template< apply_mode A,
rewind_mode M,
template< typename... > class Action,
template< typename... > class Control,
typename Input,
typename... States >
static bool match( Input& in, const std::size_t& marker_size, States&&... st )
{
auto m = in.template mark< M >();
using m_t = decltype( m );
while( !Control< Cond >::template match< A, rewind_mode::REQUIRED, Action, Control >( in, marker_size ) ) {
if( in.empty() || ( !rule_conjunction< Rules... >::template match< A, m_t::next_rewind_mode, Action, Control >( in, st... ) ) ) {
return false;
}
}
return m( true );
}
};
template< typename Cond, typename... Rules >
struct skip_control< raw_string_until< Cond, Rules... > > : std::true_type
{
};
} // namespace internal
// raw_string matches Lua-style long literals.
//
// The following description was taken from the Lua documentation
// (see http://www.lua.org/docs.html):
//
// - An "opening long bracket of level n" is defined as an opening square
// bracket followed by n equal signs followed by another opening square
// bracket. So, an opening long bracket of level 0 is written as `[[`,
// an opening long bracket of level 1 is written as `[=[`, and so on.
// - A "closing long bracket" is defined similarly; for instance, a closing
// long bracket of level 4 is written as `]====]`.
// - A "long literal" starts with an opening long bracket of any level and
// ends at the first closing long bracket of the same level. It can
// contain any text except a closing bracket of the same level.
// - Literals in this bracketed form can run for several lines, do not
// interpret any escape sequences, and ignore long brackets of any other
// level.
// - For convenience, when the opening long bracket is immediately followed
// by a newline, the newline is not included in the string.
//
// Note that unlike Lua's long literal, a raw_string is customizable to use
// other characters than `[`, `=` and `]` for matching. Also note that Lua
// introduced newline-specific replacements in Lua 5.2, which we do not
// support on the grammar level.
template< char Open, char Marker, char Close, typename... Contents >
struct raw_string
{
using analyze_t = analysis::generic< analysis::rule_type::ANY >;
// This is used for binding the apply()-method and for error-reporting
// when a raw string is not closed properly or has invalid content.
struct content
: internal::raw_string_until< internal::at_raw_string_close< Marker, Close >, Contents... >
{
};
template< apply_mode A,
rewind_mode M,
template< typename... > class Action,
template< typename... > class Control,
typename Input,
typename... States >
static bool match( Input& in, States&&... st )
{
std::size_t marker_size;
if( internal::raw_string_open< Open, Marker >::template match< A, M, Action, Control >( in, marker_size ) ) {
internal::must< content >::template match< A, M, Action, Control >( in, marker_size, st... );
in.bump_in_this_line( marker_size );
return true;
}
return false;
}
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,72 @@
// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP
#define TAO_PEGTL_CONTRIB_REP_ONE_MIN_MAX_HPP
#include <algorithm>
#include "../config.hpp"
#include "../analysis/counted.hpp"
#include "../internal/bump_help.hpp"
#include "../internal/skip_control.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
template< unsigned Min, unsigned Max, char C >
struct rep_one_min_max
{
using analyze_t = analysis::counted< analysis::rule_type::ANY, Min >;
static_assert( Min <= Max, "invalid rep_one_min_max rule (maximum number of repetitions smaller than minimum)" );
template< typename Input >
static bool match( Input& in )
{
const auto size = in.size( Max + 1 );
if( size < Min ) {
return false;
}
std::size_t i = 0;
while( ( i < size ) && ( in.peek_char( i ) == C ) ) {
++i;
}
if( ( Min <= i ) && ( i <= Max ) ) {
bump_help< result_on_found::SUCCESS, Input, char, C >( in, i );
return true;
}
return false;
}
};
template< unsigned Min, unsigned Max, char C >
struct skip_control< rep_one_min_max< Min, Max, C > > : std::true_type
{
};
} // namespace internal
inline namespace ascii
{
template< unsigned Min, unsigned Max, char C >
struct rep_one_min_max : internal::rep_one_min_max< Min, Max, C >
{
};
struct ellipsis : internal::rep_one_min_max< 3, 3, '.' >
{
};
} // namespace ascii
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,42 @@
// Copyright (c) 2017-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_TO_STRING_HPP
#define TAO_PEGTL_CONTRIB_TO_STRING_HPP
#include <string>
#include "../config.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace internal
{
template< typename >
struct to_string;
template< template< char... > class X, char... Cs >
struct to_string< X< Cs... > >
{
static std::string get()
{
const char s[] = { Cs..., 0 };
return std::string( s, sizeof...( Cs ) );
}
};
} // namespace internal
template< typename T >
std::string to_string()
{
return internal::to_string< T >::get();
}
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,115 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_TRACER_HPP
#define TAO_PEGTL_CONTRIB_TRACER_HPP
#include <cassert>
#include <iomanip>
#include <iostream>
#include <utility>
#include <vector>
#include "../config.hpp"
#include "../normal.hpp"
#include "../internal/demangle.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
struct trace_state
{
unsigned rule = 0;
unsigned line = 0;
std::vector< unsigned > stack;
};
template< typename Rule >
struct tracer
: normal< Rule >
{
template< typename Input, typename... States >
static void start( const Input& in, States&&... /*unused*/ )
{
std::cerr << in.position() << " start " << internal::demangle< Rule >() << std::endl;
}
template< typename Input >
static void start( const Input& in, trace_state& ts )
{
std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ++ts.rule << " " << in.position() << " start " << internal::demangle< Rule >() << std::endl;
ts.stack.push_back( ts.rule );
}
template< typename Input, typename... States >
static void success( const Input& in, States&&... /*unused*/ )
{
std::cerr << in.position() << " success " << internal::demangle< Rule >() << std::endl;
}
template< typename Input >
static void success( const Input& in, trace_state& ts )
{
assert( !ts.stack.empty() );
std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " success " << internal::demangle< Rule >() << std::endl;
ts.stack.pop_back();
}
template< typename Input, typename... States >
static void failure( const Input& in, States&&... /*unused*/ )
{
std::cerr << in.position() << " failure " << internal::demangle< Rule >() << std::endl;
}
template< typename Input >
static void failure( const Input& in, trace_state& ts )
{
assert( !ts.stack.empty() );
std::cerr << std::setw( 6 ) << ++ts.line << " " << std::setw( 6 ) << ts.stack.back() << " " << in.position() << " failure " << internal::demangle< Rule >() << std::endl;
ts.stack.pop_back();
}
template< template< typename... > class Action, typename Input, typename... States >
static auto apply0( const Input& /*unused*/, States&&... st )
-> decltype( Action< Rule >::apply0( st... ) )
{
std::cerr << "apply0 " << internal::demangle< Action< Rule > >() << std::endl;
return Action< Rule >::apply0( st... );
}
template< template< typename... > class Action, typename Input >
static auto apply0( const Input& /*unused*/, trace_state& ts )
-> decltype( Action< Rule >::apply0( ts ) )
{
std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply0()" << std::endl;
return Action< Rule >::apply0( ts );
}
template< template< typename... > class Action, typename Iterator, typename Input, typename... States >
static auto apply( const Iterator& begin, const Input& in, States&&... st )
-> decltype( Action< Rule >::apply( std::declval< typename Input::action_t >(), st... ) )
{
std::cerr << "apply " << internal::demangle< Action< Rule > >() << std::endl;
using action_t = typename Input::action_t;
const action_t action_input( begin, in );
return Action< Rule >::apply( action_input, st... );
}
template< template< typename... > class Action, typename Iterator, typename Input >
static auto apply( const Iterator& begin, const Input& in, trace_state& ts )
-> decltype( Action< Rule >::apply( std::declval< typename Input::action_t >(), ts ) )
{
std::cerr << std::setw( 6 ) << ++ts.line << " " << internal::demangle< Action< Rule > >() << "::apply()" << std::endl;
using action_t = typename Input::action_t;
const action_t action_input( begin, in );
return Action< Rule >::apply( action_input, ts );
}
};
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,210 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_UNESCAPE_HPP
#define TAO_PEGTL_CONTRIB_UNESCAPE_HPP
#include <cassert>
#include <string>
#include "../ascii.hpp"
#include "../config.hpp"
#include "../parse_error.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace unescape
{
struct state
{
std::string unescaped;
};
// Utility functions for the unescape actions.
inline bool utf8_append_utf32( std::string& string, const unsigned utf32 )
{
if( utf32 <= 0x7f ) {
string += char( utf32 & 0xff );
return true;
}
if( utf32 <= 0x7ff ) {
char tmp[] = { char( ( ( utf32 & 0x7c0 ) >> 6 ) | 0xc0 ),
char( ( ( utf32 & 0x03f ) ) | 0x80 ) };
string.append( tmp, sizeof( tmp ) );
return true;
}
if( utf32 <= 0xffff ) {
if( utf32 >= 0xd800 && utf32 <= 0xdfff ) {
// nope, this is a UTF-16 surrogate
return false;
}
char tmp[] = { char( ( ( utf32 & 0xf000 ) >> 12 ) | 0xe0 ),
char( ( ( utf32 & 0x0fc0 ) >> 6 ) | 0x80 ),
char( ( ( utf32 & 0x003f ) ) | 0x80 ) };
string.append( tmp, sizeof( tmp ) );
return true;
}
if( utf32 <= 0x10ffff ) {
char tmp[] = { char( ( ( utf32 & 0x1c0000 ) >> 18 ) | 0xf0 ),
char( ( ( utf32 & 0x03f000 ) >> 12 ) | 0x80 ),
char( ( ( utf32 & 0x000fc0 ) >> 6 ) | 0x80 ),
char( ( ( utf32 & 0x00003f ) ) | 0x80 ) };
string.append( tmp, sizeof( tmp ) );
return true;
}
return false;
}
// This function MUST only be called for characters matching tao::TAO_PEGTL_NAMESPACE::ascii::xdigit!
template< typename I >
I unhex_char( const char c )
{
switch( c ) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return I( c - '0' );
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
return I( c - 'a' + 10 );
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
return I( c - 'A' + 10 );
}
throw std::runtime_error( "invalid character in unhex" ); // NOLINT, LCOV_EXCL_LINE
}
template< typename I >
I unhex_string( const char* begin, const char* end )
{
I r = 0;
while( begin != end ) {
r <<= 4;
r += unhex_char< I >( *begin++ );
}
return r;
}
// Actions for common unescape situations.
struct append_all
{
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
st.unescaped.append( in.begin(), in.size() );
}
};
// This action MUST be called for a character matching T which MUST be tao::TAO_PEGTL_NAMESPACE::one< ... >.
template< typename T, char... Rs >
struct unescape_c
{
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
assert( in.size() == 1 );
st.unescaped += apply_one( *in.begin(), static_cast< const T* >( nullptr ) );
}
template< char... Qs >
static char apply_one( const char c, const one< Qs... >* /*unused*/ )
{
static_assert( sizeof...( Qs ) == sizeof...( Rs ), "size mismatch between escaped characters and their mappings" );
return apply_two( c, { Qs... }, { Rs... } );
}
static char apply_two( const char c, const std::initializer_list< char >& q, const std::initializer_list< char >& r )
{
for( std::size_t i = 0; i < q.size(); ++i ) {
if( *( q.begin() + i ) == c ) {
return *( r.begin() + i );
}
}
throw std::runtime_error( "invalid character in unescape" ); // NOLINT, LCOV_EXCL_LINE
}
};
// See src/example/pegtl/unescape.cpp for why the following two actions
// skip the first input character. They also MUST be called
// with non-empty matched inputs!
struct unescape_u
{
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
assert( !in.empty() ); // First character MUST be present, usually 'u' or 'U'.
if( !utf8_append_utf32( st.unescaped, unhex_string< unsigned >( in.begin() + 1, in.end() ) ) ) {
throw parse_error( "invalid escaped unicode code point", in );
}
}
};
struct unescape_x
{
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
assert( !in.empty() ); // First character MUST be present, usually 'x'.
st.unescaped += unhex_string< char >( in.begin() + 1, in.end() );
}
};
// The unescape_j action is similar to unescape_u, however unlike
// unescape_u it
// (a) assumes exactly 4 hexdigits per escape sequence,
// (b) accepts multiple consecutive escaped 16-bit values.
// When applied to more than one escape sequence, unescape_j
// translates UTF-16 surrogate pairs in the input into a single
// UTF-8 sequence in st.unescaped, as required for JSON by RFC 8259.
struct unescape_j
{
template< typename Input, typename State >
static void apply( const Input& in, State& st )
{
assert( ( ( in.size() + 1 ) % 6 ) == 0 ); // Expects multiple "\\u1234", starting with the first "u".
for( const char* b = in.begin() + 1; b < in.end(); b += 6 ) {
const auto c = unhex_string< unsigned >( b, b + 4 );
if( ( 0xd800 <= c ) && ( c <= 0xdbff ) && ( b + 6 < in.end() ) ) {
const auto d = unhex_string< unsigned >( b + 6, b + 10 );
if( ( 0xdc00 <= d ) && ( d <= 0xdfff ) ) {
b += 6;
// note: no need to check the result code, as we are always >= 0x10000 and < 0x110000.
utf8_append_utf32( st.unescaped, ( ( ( c & 0x03ff ) << 10 ) | ( d & 0x03ff ) ) + 0x10000 );
continue;
}
}
if( !utf8_append_utf32( st.unescaped, c ) ) {
throw parse_error( "invalid escaped unicode code point", in );
}
}
}
};
} // namespace unescape
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

View File

@ -0,0 +1,115 @@
// Copyright (c) 2014-2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
#ifndef TAO_PEGTL_CONTRIB_URI_HPP
#define TAO_PEGTL_CONTRIB_URI_HPP
#include "../ascii.hpp"
#include "../config.hpp"
#include "../rules.hpp"
#include "../utf8.hpp"
#include "abnf.hpp"
namespace tao
{
namespace TAO_PEGTL_NAMESPACE
{
namespace uri
{
// URI grammar according to RFC 3986.
// This grammar is a direct PEG translation of the original URI grammar.
// It should be considered experimental -- in case of any issues, in particular
// missing rules for attached actions, please contact the developers.
// Note that this grammar has multiple top-level rules.
using dot = one< '.' >;
using colon = one< ':' >;
// clang-format off
struct dec_octet : sor< one< '0' >,
rep_min_max< 1, 2, abnf::DIGIT >,
seq< one< '1' >, abnf::DIGIT, abnf::DIGIT >,
seq< one< '2' >, range< '0', '4' >, abnf::DIGIT >,
seq< string< '2', '5' >, range< '0', '5' > > > {};
struct IPv4address : seq< dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet > {};
struct h16 : rep_min_max< 1, 4, abnf::HEXDIG > {};
struct ls32 : sor< seq< h16, colon, h16 >, IPv4address > {};
struct dcolon : two< ':' > {};
struct IPv6address : sor< seq< rep< 6, h16, colon >, ls32 >,
seq< dcolon, rep< 5, h16, colon >, ls32 >,
seq< opt< h16 >, dcolon, rep< 4, h16, colon >, ls32 >,
seq< opt< h16, opt< colon, h16 > >, dcolon, rep< 3, h16, colon >, ls32 >,
seq< opt< h16, rep_opt< 2, colon, h16 > >, dcolon, rep< 2, h16, colon >, ls32 >,
seq< opt< h16, rep_opt< 3, colon, h16 > >, dcolon, h16, colon, ls32 >,
seq< opt< h16, rep_opt< 4, colon, h16 > >, dcolon, ls32 >,
seq< opt< h16, rep_opt< 5, colon, h16 > >, dcolon, h16 >,
seq< opt< h16, rep_opt< 6, colon, h16 > >, dcolon > > {};
struct gen_delims : one< ':', '/', '?', '#', '[', ']', '@' > {};
struct sub_delims : one< '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=' > {};
struct unreserved : sor< abnf::ALPHA, abnf::DIGIT, one< '-', '.', '_', '~' > > {};
struct reserved : sor< gen_delims, sub_delims > {};
struct IPvFuture : if_must< one< 'v' >, plus< abnf::HEXDIG >, dot, plus< sor< unreserved, sub_delims, colon > > > {};
struct IP_literal : if_must< one< '[' >, sor< IPvFuture, IPv6address >, one< ']' > > {};
struct pct_encoded : if_must< one< '%' >, abnf::HEXDIG, abnf::HEXDIG > {};
struct pchar : sor< unreserved, pct_encoded, sub_delims, one< ':', '@' > > {};
struct query : star< sor< pchar, one< '/', '?' > > > {};
struct fragment : star< sor< pchar, one< '/', '?' > > > {};
struct segment : star< pchar > {};
struct segment_nz : plus< pchar > {};
struct segment_nz_nc : plus< sor< unreserved, pct_encoded, sub_delims, one< '@' > > > {}; // non-zero-length segment without any colon ":"
struct path_abempty : star< one< '/' >, segment > {};
struct path_absolute : seq< one< '/' >, opt< segment_nz, star< one< '/' >, segment > > > {};
struct path_noscheme : seq< segment_nz_nc, star< one< '/' >, segment > > {};
struct path_rootless : seq< segment_nz, star< one< '/' >, segment > > {};
struct path_empty : success {};
struct path : sor< path_noscheme, // begins with a non-colon segment
path_rootless, // begins with a segment
path_absolute, // begins with "/" but not "//"
path_abempty > {}; // begins with "/" or is empty
struct reg_name : star< sor< unreserved, pct_encoded, sub_delims > > {};
struct port : star< abnf::DIGIT > {};
struct host : sor< IP_literal, IPv4address, reg_name > {};
struct userinfo : star< sor< unreserved, pct_encoded, sub_delims, colon > > {};
struct opt_userinfo : opt< userinfo, one< '@' > > {};
struct authority : seq< opt_userinfo, host, opt< colon, port > > {};
struct scheme : seq< abnf::ALPHA, star< sor< abnf::ALPHA, abnf::DIGIT, one< '+', '-', '.' > > > > {};
using dslash = two< '/' >;
using opt_query = opt_must< one< '?' >, query >;
using opt_fragment = opt_must< one< '#' >, fragment >;
struct hier_part : sor< if_must< dslash, authority, path_abempty >, path_rootless, path_absolute, path_empty > {};
struct relative_part : sor< if_must< dslash, authority, path_abempty >, path_noscheme, path_absolute, path_empty > {};
struct relative_ref : seq< relative_part, opt_query, opt_fragment > {};
struct URI : seq< scheme, one< ':' >, hier_part, opt_query, opt_fragment > {};
struct URI_reference : sor< URI, relative_ref > {};
struct absolute_URI : seq< scheme, one< ':' >, hier_part, opt_query > {};
// clang-format on
} // namespace uri
} // namespace TAO_PEGTL_NAMESPACE
} // namespace tao
#endif

Some files were not shown because too many files have changed in this diff Show More