changed semantic of [def] statements:
- [def] is used to define a variable (like before) but if we assign a string such as [def var "string"] the string is evaluated to bool in a different way: empty string is false, not empty string is true - added [def?] statement - similar like [def] but define a variable only if such a variable is not already defined - added [let] statement - similar like [def] but with lazy evaluation (it is an alias to a function) if it is called to assign a string e.g. [let var "string"] then this has the same meaning like [def] - an alias is only created when we assign a function e.g. [let var my_function] both [def] and [let] are using the same Vars object - added [let?] - make an alias but only if such a variable is not already defined - a std::map of variables moved outside of Generator added method void SetVariables(Vars & variables); - fixed: a result status was not correctly propagated when evaluating [def] statements, this was in Call(...) function: last_res from variables was set in Find() but later was overwritten by Call(...) called for parameters (recursively)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2018, Tomasz Sowa
|
||||
* Copyright (c) 2007-2021, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -486,7 +486,7 @@ bool PatternParser::IsNameChar(wchar_t c)
|
||||
return ((c>='a' && c<='z') ||
|
||||
(c>='A' && c<='Z') ||
|
||||
(c>='0' && c<='9') ||
|
||||
c=='_' || c=='-' || c=='.' || c=='#');
|
||||
c=='_' || c=='-' || c=='.' || c=='#' || c=='?');
|
||||
}
|
||||
|
||||
|
||||
@@ -784,10 +784,85 @@ void PatternParser::ReadDirectiveInclude(Item & item)
|
||||
void PatternParser::ReadDirectiveDef(Item & item)
|
||||
{
|
||||
item.type = Item::item_def;
|
||||
ReadFunction(item);
|
||||
|
||||
if( ReadFunction(item) )
|
||||
{
|
||||
if( item.function.parameters.size() > 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveDefIfNotSet(Item & item)
|
||||
{
|
||||
item.type = Item::item_def_if_not_set;
|
||||
|
||||
if( ReadFunction(item) )
|
||||
{
|
||||
if( item.function.parameters.size() > 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveLet(Item & item)
|
||||
{
|
||||
item.type = Item::item_let;
|
||||
|
||||
if( ReadFunction(item) )
|
||||
{
|
||||
std::vector<Item::Function*> & parameters = item.function.parameters;
|
||||
|
||||
if( parameters.size() > 1 )
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
else
|
||||
if( parameters.size() == 1 && parameters[0]->is_function && !parameters[0]->parameters.empty() )
|
||||
{
|
||||
/*
|
||||
* if the first parameter in [let] is a function e.g. [let variable function_name] (here the first parameter is function_name)
|
||||
* then the function cannot have parameters itselt (because it is not evaluated here)
|
||||
* this is only an alias
|
||||
*/
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveLetIfNotSet(Item & item)
|
||||
{
|
||||
item.type = Item::item_let_if_not_set;
|
||||
|
||||
if( ReadFunction(item) )
|
||||
{
|
||||
std::vector<Item::Function*> & parameters = item.function.parameters;
|
||||
|
||||
if( parameters.size() > 1 )
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
else
|
||||
if( parameters.size() == 1 && parameters[0]->is_function && !parameters[0]->parameters.empty() )
|
||||
{
|
||||
/*
|
||||
* if the first parameter in [let] is a function e.g. [let variable function_name] (here the first parameter is function_name)
|
||||
* then the function cannot have parameters itselt (because it is not evaluated here)
|
||||
* this is only an alias
|
||||
*/
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveFilter(Item & item)
|
||||
{
|
||||
item.type = Item::item_filter;
|
||||
@@ -825,11 +900,16 @@ void PatternParser::ReadDirectiveOut(Item & item)
|
||||
void PatternParser::ReadDirectiveBlock(Item & item)
|
||||
{
|
||||
item.type = Item::item_block;
|
||||
ReadFunction(item);
|
||||
|
||||
// only one function without arguments
|
||||
if( !item.function.parameters.empty() )
|
||||
item.type = Item::item_err;
|
||||
if( ReadFunction(item) )
|
||||
{
|
||||
// only one function without arguments
|
||||
if( !item.function.parameters.empty() )
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -859,6 +939,9 @@ std::wstring name;
|
||||
else if( name == L"for" ) ReadDirectiveFor(item);
|
||||
else if( name == L"include" ) ReadDirectiveInclude(item);
|
||||
else if( name == L"def" ) ReadDirectiveDef(item);
|
||||
else if( name == L"def?" ) ReadDirectiveDefIfNotSet(item);
|
||||
else if( name == L"let" ) ReadDirectiveLet(item);
|
||||
else if( name == L"let?" ) ReadDirectiveLetIfNotSet(item);
|
||||
else if( name == L"filter" ) ReadDirectiveFilter(item);
|
||||
else if( name == L"ezc" ) ReadDirectiveEzc(item);
|
||||
else if( name == L"out" ) ReadDirectiveOut(item);
|
||||
|
Reference in New Issue
Block a user