Sim: Make empty Sim.Params mean storing primary value in Value

This commit is contained in:
Mikolaj Wielgus 2022-11-22 07:06:53 +01:00
parent 1550a1e3a4
commit 23480cdee3
3 changed files with 25 additions and 70 deletions

View File

@ -943,10 +943,8 @@ void SIM_MODEL::doReadDataFields( unsigned aSymbolPinCount, const std::vector<T>
std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD ); std::string paramsField = GetFieldValue( aFields, PARAMS_FIELD );
if( paramsField == "" && HasPrimaryValue() ) if( !m_serde->ParseParams( paramsField ) )
m_serde->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) ); m_serde->ParseValue( GetFieldValue( aFields, VALUE_FIELD ) );
else
m_serde->ParseParams( paramsField );
} }
@ -959,10 +957,10 @@ void SIM_MODEL::doWriteFields( std::vector<T>& aFields ) const
SetFieldValue( aFields, ENABLE_FIELD, m_serde->GenerateEnable() ); SetFieldValue( aFields, ENABLE_FIELD, m_serde->GenerateEnable() );
SetFieldValue( aFields, PINS_FIELD, m_serde->GeneratePins() ); SetFieldValue( aFields, PINS_FIELD, m_serde->GeneratePins() );
SetFieldValue( aFields, PARAMS_FIELD, m_serde->GenerateParams() );
if( IsStoredInValue() ) if( IsStoredInValue() )
SetFieldValue( aFields, VALUE_FIELD, m_serde->GenerateValue() ); SetFieldValue( aFields, VALUE_FIELD, m_serde->GenerateValue() );
else
SetFieldValue( aFields, PARAMS_FIELD, m_serde->GenerateParams() );
} }

View File

@ -45,10 +45,7 @@ namespace SIM_SERDE_PARSER
template <> struct pinSequenceSelector<pinNumber> : std::true_type {}; template <> struct pinSequenceSelector<pinNumber> : std::true_type {};
template <typename Rule> struct fieldInferValueSelector : std::false_type {}; template <typename Rule> struct fieldInferValueSelector : std::false_type {};
template <> struct fieldInferValueSelector<fieldInferValueType> : std::true_type {};
template <> struct fieldInferValueSelector<fieldInferValuePrimaryValue> : std::true_type {};
template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {}; template <> struct fieldInferValueSelector<number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> : std::true_type {};
template <> struct fieldInferValueSelector<fieldParamValuePairs> : std::true_type {};
} }
@ -66,28 +63,8 @@ std::string SIM_SERDE::GenerateType() const
std::string SIM_SERDE::GenerateValue() const std::string SIM_SERDE::GenerateValue() const
{ {
std::string result; const SIM_MODEL::PARAM& param = m_model.GetUnderlyingParam( 0 );
std::string result = param.value->ToString();
for( int i = 0; i < m_model.GetParamCount(); ++i )
{
const SIM_MODEL::PARAM& param = m_model.GetUnderlyingParam( i );
if( i == 0 && m_model.HasPrimaryValue() )
{
result.append( param.value->ToString() );
continue;
}
if( param.value->ToString() == "" )
continue;
std::string paramValuePair = GenerateParamValuePair( param );
if( paramValuePair == "" )
continue; // Prevent adding empty spaces.
result.append( fmt::format( " {}", paramValuePair ) );
}
if( result == "" ) if( result == "" )
result = m_model.GetDeviceInfo().fieldValue; result = m_model.GetDeviceInfo().fieldValue;
@ -103,9 +80,12 @@ std::string SIM_SERDE::GenerateParams() const
for( int i = 0; i < m_model.GetParamCount(); ++i ) for( int i = 0; i < m_model.GetParamCount(); ++i )
{ {
if( i == 0 && m_model.IsStoredInValue() )
continue;
const SIM_MODEL::PARAM& param = m_model.GetUnderlyingParam( i ); const SIM_MODEL::PARAM& param = m_model.GetUnderlyingParam( i );
if( param.value->ToString() == "" ) if( param.value->ToString() == "" && !( i == 0 && !m_model.IsStoredInValue() ) )
continue; continue;
std::string paramValuePair = GenerateParamValuePair( param ); std::string paramValuePair = GenerateParamValuePair( param );
@ -172,7 +152,6 @@ void SIM_SERDE::ParseValue( const std::string& aValue )
{ {
try try
{ {
// TODO: Don't call this multiple times.
tao::pegtl::string_input<> in( aValue, SIM_MODEL::VALUE_FIELD ); tao::pegtl::string_input<> in( aValue, SIM_MODEL::VALUE_FIELD );
auto root = tao::pegtl::parse_tree::parse<SIM_SERDE_PARSER::fieldInferValueGrammar, auto root = tao::pegtl::parse_tree::parse<SIM_SERDE_PARSER::fieldInferValueGrammar,
SIM_SERDE_PARSER::fieldInferValueSelector, SIM_SERDE_PARSER::fieldInferValueSelector,
@ -181,19 +160,12 @@ void SIM_SERDE::ParseValue( const std::string& aValue )
for( const auto& node : root->children ) for( const auto& node : root->children )
{ {
if( node->is_type<SIM_SERDE_PARSER::fieldInferValuePrimaryValue>() ) if( node->is_type<SIM_SERDE_PARSER::number<SIM_VALUE::TYPE_FLOAT,
SIM_VALUE::NOTATION::SI>>()
&& node->string() != "" )
{ {
for( const auto& subnode : node->children ) m_model.SetParamValue( 0, node->string() );
{
if( subnode->is_type<SIM_SERDE_PARSER::number<SIM_VALUE::TYPE_FLOAT,
SIM_VALUE::NOTATION::SI>>() )
{
m_model.SetParamValue( 0, subnode->string() );
}
}
} }
else if( node->is_type<SIM_SERDE_PARSER::fieldParamValuePairs>() )
ParseParams( node->string() );
} }
} }
catch( const tao::pegtl::parse_error& e ) catch( const tao::pegtl::parse_error& e )
@ -205,7 +177,7 @@ void SIM_SERDE::ParseValue( const std::string& aValue )
} }
void SIM_SERDE::ParseParams( const std::string& aParams ) bool SIM_SERDE::ParseParams( const std::string& aParams )
{ {
tao::pegtl::string_input<> in( aParams, SIM_MODEL::PARAMS_FIELD ); tao::pegtl::string_input<> in( aParams, SIM_MODEL::PARAMS_FIELD );
std::unique_ptr<tao::pegtl::parse_tree::node> root; std::unique_ptr<tao::pegtl::parse_tree::node> root;
@ -227,6 +199,7 @@ void SIM_SERDE::ParseParams( const std::string& aParams )
} }
std::string paramName; std::string paramName;
bool isPrimaryValueSet = false;
for( const auto& node : root->children ) for( const auto& node : root->children )
{ {
@ -241,6 +214,9 @@ void SIM_SERDE::ParseParams( const std::string& aParams )
// TODO: Shouldn't be named "...fromSpiceCode" here... // TODO: Shouldn't be named "...fromSpiceCode" here...
m_model.SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI ); m_model.SetParamValue( paramName, node->string(), SIM_VALUE_GRAMMAR::NOTATION::SI );
if( paramName == m_model.GetParam( 0 ).info.name )
isPrimaryValueSet = true;
} }
else if( node->is_type<SIM_SERDE_PARSER::quotedString>() ) else if( node->is_type<SIM_SERDE_PARSER::quotedString>() )
{ {
@ -256,6 +232,8 @@ void SIM_SERDE::ParseParams( const std::string& aParams )
wxFAIL; wxFAIL;
} }
} }
return !m_model.HasPrimaryValue() || isPrimaryValueSet;
} }
@ -319,7 +297,7 @@ std::string SIM_SERDE::GenerateParamValuePair( const SIM_MODEL::PARAM& aParam )
std::string value = aParam.value->ToString(); std::string value = aParam.value->ToString();
if( value.find( " " ) != std::string::npos ) if( value == "" || value.find( " " ) != std::string::npos )
value = fmt::format( "\"{}\"", value ); value = fmt::format( "\"{}\"", value );
return fmt::format( "{}={}", aParam.info.name, value ); return fmt::format( "{}={}", aParam.info.name, value );

View File

@ -69,27 +69,8 @@ namespace SIM_SERDE_GRAMMAR
opt<sep>, opt<sep>,
tao::pegtl::eof> {}; tao::pegtl::eof> {};
struct fieldInferValueType : plus<upper> {}; struct fieldInferValue : sor<one<'R', 'C', 'L', 'V', 'I'>,
struct fieldInferValuePrimaryValue : seq<// HACK: Because `number` matches empty string, number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>> {};
// ensure it is not empty.
at<sor<tao::pegtl::digit,
seq<one<'.'>>,
tao::pegtl::digit>>,
// END HACK.
number<SIM_VALUE::TYPE_FLOAT, NOTATION::SI>,
// Hackish: match anything until param-value pairs.
// Because the user may want to write something like
// "10k 30% 30mW w=0.4", but we care only about the
// "10k" and "w=0.4".
star<not_at<sep,
try_catch<fieldParamValuePairs>>,
any>> {};
struct fieldInferValue : sor<seq<fieldInferValueType,
opt<sep,
fieldParamValuePairs>>,
seq<opt<fieldInferValuePrimaryValue>,
opt<sep>,
opt<fieldParamValuePairs>>> {};
struct fieldInferValueGrammar : must<opt<sep>, struct fieldInferValueGrammar : must<opt<sep>,
fieldInferValue, fieldInferValue,
opt<sep>, opt<sep>,
@ -99,8 +80,6 @@ namespace SIM_SERDE_GRAMMAR
template <typename> inline constexpr const char* errorMessage = nullptr; template <typename> inline constexpr const char* errorMessage = nullptr;
template <> inline constexpr auto errorMessage<opt<sep>> = ""; template <> inline constexpr auto errorMessage<opt<sep>> = "";
template <> inline constexpr auto errorMessage<opt<pinSequence>> = ""; template <> inline constexpr auto errorMessage<opt<pinSequence>> = "";
template <> inline constexpr auto errorMessage<opt<sor<fieldInferValueType,
fieldInferValuePrimaryValue>>> = "";
template <> inline constexpr auto errorMessage<one<'='>> = template <> inline constexpr auto errorMessage<one<'='>> =
"expected '='"; "expected '='";
template <> inline constexpr auto errorMessage<sor<quotedString, template <> inline constexpr auto errorMessage<sor<quotedString,
@ -110,7 +89,7 @@ namespace SIM_SERDE_GRAMMAR
"expected parameter=value pairs"; "expected parameter=value pairs";
template <> inline constexpr auto errorMessage<opt<fieldParamValuePairs>> = ""; template <> inline constexpr auto errorMessage<opt<fieldParamValuePairs>> = "";
template <> inline constexpr auto errorMessage<fieldInferValue> = template <> inline constexpr auto errorMessage<fieldInferValue> =
"expected parameter=value pairs, together possibly preceded by a type or primary value"; "expected 'R', 'C', 'L', 'V', 'I' or a number";
template <> inline constexpr auto errorMessage<tao::pegtl::eof> = template <> inline constexpr auto errorMessage<tao::pegtl::eof> =
"expected end of string"; "expected end of string";
@ -151,7 +130,7 @@ public:
SIM_MODEL::TYPE ParseDeviceAndType( const std::string& aDevice, SIM_MODEL::TYPE ParseDeviceAndType( const std::string& aDevice,
const std::string& aType ); const std::string& aType );
void ParseValue( const std::string& aValue ); void ParseValue( const std::string& aValue );
void ParseParams( const std::string& aParams ); bool ParseParams( const std::string& aParams );
void ParsePins( const std::string& aPins ); void ParsePins( const std::string& aPins );
void ParseEnable( const std::string& aEnable ); void ParseEnable( const std::string& aEnable );