changed: the way how functions' arguments are parsed
now this [fun1 fun2 "something" fun3] will call fun1 with three arguments: fun2, "something" and fun3 and this [fun1 [fun2 "something"] fun3] will call fun1 with two arguments: [fun2 "something] and fun3 "something" is an argument for fun2 function removed: statements: [if-one] [if-any] [if-no] [if-any-no] [if-one-no] git-svn-id: svn://ttmath.org/publicrep/ezc/trunk@1004 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2014, Tomasz Sowa
|
||||
* Copyright (c) 2007-2015, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -425,6 +425,22 @@ void PatternParser::SkipWhite()
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::SkipOneStatement()
|
||||
{
|
||||
size_t count = 1;
|
||||
|
||||
while( *itext != 0 && count > 0 )
|
||||
{
|
||||
if( *itext == '[' )
|
||||
count += 1;
|
||||
else
|
||||
if( *itext == ']' )
|
||||
count -= 1;
|
||||
|
||||
itext += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::CheckWhiteAndDelete(std::wstring & s)
|
||||
{
|
||||
@@ -440,6 +456,12 @@ size_t i;
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::CheckFunctionIsNumber(Item::Function & function)
|
||||
{
|
||||
if( IsPositiveNumber(function.name) )
|
||||
function.arg = wcstol(function.name.c_str(), 0, 10);
|
||||
}
|
||||
|
||||
|
||||
bool PatternParser::IsNameChar(wchar_t c)
|
||||
{
|
||||
@@ -522,103 +544,176 @@ bool PatternParser::ReadString(std::wstring & str)
|
||||
}
|
||||
|
||||
if( *itext == '\"' )
|
||||
{
|
||||
++itext;
|
||||
|
||||
// if there was not a quote at the end we do not report an error
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool PatternParser::ReadNestedFunction(Item::Function & function)
|
||||
{
|
||||
++itext; // skipping '['
|
||||
|
||||
bool res = ReadFunction(function.AddNewParam(), true);
|
||||
|
||||
if( !res )
|
||||
{
|
||||
SkipOneStatement();
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhite();
|
||||
|
||||
if( *itext == ']' )
|
||||
{
|
||||
++itext;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SkipOneStatement();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PatternParser::ReadParamString(Item::Function & function)
|
||||
{
|
||||
Item::Function & fun = function.AddNewParam();
|
||||
fun.is_function = false;
|
||||
|
||||
return ReadString(fun.name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
returns true if it correctly reads all parameters
|
||||
*/
|
||||
bool PatternParser::ReadParams(Item::Function & function)
|
||||
{
|
||||
while( true )
|
||||
bool res;
|
||||
|
||||
do
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
if( *itext == '[' )
|
||||
{
|
||||
++itext; // skipping '['
|
||||
ReadFunction(function.AddNewParam());
|
||||
|
||||
SkipWhite();
|
||||
if( *itext == ']' )
|
||||
++itext;
|
||||
res = ReadNestedFunction(function);
|
||||
}
|
||||
else
|
||||
if( *itext == '\"' )
|
||||
{
|
||||
if( ReadString(temp_param) )
|
||||
{
|
||||
Item::Function & fun = function.AddNewParam();
|
||||
fun.par = temp_param;
|
||||
// fun.name is empty so it is treated as a text parameter
|
||||
}
|
||||
|
||||
temp_param.clear();
|
||||
res = ReadParamString(function);
|
||||
}
|
||||
else
|
||||
if( *itext != ']' && *itext != 0 )
|
||||
{
|
||||
res = ReadFunction(function.AddNewParam(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// *itext is equal to ']'
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while( res );
|
||||
|
||||
return !function.parameters.empty();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PatternParser::ReadFunction(Item::Function & function)
|
||||
/*
|
||||
returns true if it correctly reads all parameters
|
||||
*/
|
||||
bool PatternParser::ReadFunction(Item::Function & function, bool with_params)
|
||||
{
|
||||
SkipWhite();
|
||||
function.Clear();
|
||||
function.is_function = true;
|
||||
|
||||
if( !ReadName(function.name) )
|
||||
return false;
|
||||
|
||||
// !! IMPROVE ME add skiping some white characters (at the beginning and at the end)
|
||||
if( IsPositiveNumber(function.name) )
|
||||
function.arg = wcstol(function.name.c_str(), 0, 10);
|
||||
CheckFunctionIsNumber(function);
|
||||
|
||||
ReadParams(function);
|
||||
if( with_params )
|
||||
return ReadParams(function);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool PatternParser::ReadFunctions(Item & item)
|
||||
/*
|
||||
returns true if it correctly reads all parameters
|
||||
*/
|
||||
bool PatternParser::ReadFunction(Item & item)
|
||||
{
|
||||
item.functions.clear();
|
||||
SkipWhite();
|
||||
|
||||
while( ReadFunction(temp_function) )
|
||||
item.functions.push_back(temp_function);
|
||||
if( *itext == ']' )
|
||||
{
|
||||
item.has_function = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.has_function = true;
|
||||
|
||||
temp_function.Clear();
|
||||
if( !ReadFunction(item.function, true) )
|
||||
{
|
||||
item.function.Clear();
|
||||
item.type = Item::item_err;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !item.functions.empty();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void PatternParser::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
||||
{
|
||||
SkipWhite();
|
||||
|
||||
if( *itext != ']' )
|
||||
if( *itext == ']' )
|
||||
{
|
||||
itext += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
|
||||
while( *itext!=0 && *itext!=']' )
|
||||
++itext;
|
||||
item.function.Clear();
|
||||
SkipOneStatement();
|
||||
}
|
||||
}
|
||||
|
||||
if( *itext == ']' )
|
||||
++itext;
|
||||
|
||||
// user defined directive
|
||||
void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||
{
|
||||
item.type = Item::item_function;
|
||||
item.has_function = true;
|
||||
|
||||
item.function.Clear();
|
||||
item.function.name = name;
|
||||
item.function.is_function = true;
|
||||
CheckFunctionIsNumber(item.function);
|
||||
|
||||
if( !ReadParams(item.function) )
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
item.function.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,64 +721,11 @@ void PatternParser::CreateTreeReadItemDirectiveCheckEnding(Item & item)
|
||||
void PatternParser::ReadDirectiveIf(Item & item)
|
||||
{
|
||||
item.type = Item::item_if;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveIfno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifno;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveIfany(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifany;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveIfone(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifone;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveIfanyno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifanyno;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveIfoneno(Item & item)
|
||||
{
|
||||
item.type = Item::item_ifoneno;
|
||||
|
||||
if( !ReadFunctions(item) )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveEnd(Item & item)
|
||||
{
|
||||
@@ -702,10 +744,7 @@ void PatternParser::ReadDirectiveElse(Item & item)
|
||||
void PatternParser::ReadDirectiveFor(Item & item)
|
||||
{
|
||||
item.type = Item::item_for;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
@@ -733,54 +772,32 @@ void PatternParser::ReadDirectiveInclude(Item & item)
|
||||
|
||||
void PatternParser::ReadDirectiveDef(Item & item)
|
||||
{
|
||||
item.type = Item::item_err;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() == 1 && item.functions[0].parameters.size() == 1 )
|
||||
{
|
||||
// it is [def name "value"]
|
||||
// or [def name [otherfunction]]
|
||||
// or [def name [otherfunction "argument"]] etc.
|
||||
|
||||
item.type = Item::item_def;
|
||||
}
|
||||
else
|
||||
if( item.functions.size() == 2 &&
|
||||
item.functions[0].parameters.empty() )
|
||||
{
|
||||
// it is:
|
||||
// [def name function]
|
||||
// or [def name function "funpar1" "funpar2"] etc.
|
||||
|
||||
item.type = Item::item_def;
|
||||
}
|
||||
item.type = Item::item_def;
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveFilter(Item & item)
|
||||
{
|
||||
item.type = Item::item_filter;
|
||||
ReadFunctions(item);
|
||||
|
||||
if( item.functions.size() != 1 )
|
||||
item.type = Item::item_err;
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveEzc(Item & item)
|
||||
{
|
||||
item.type = Item::item_ezc;
|
||||
ReadFunctions(item);
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
void PatternParser::ReadDirectiveBlock(Item & item)
|
||||
{
|
||||
item.type = Item::item_block;
|
||||
ReadFunctions(item);
|
||||
ReadFunction(item);
|
||||
|
||||
// only one function without arguments
|
||||
if( item.functions.size() != 1 || !item.functions[0].parameters.empty() )
|
||||
if( !item.function.parameters.empty() )
|
||||
item.type = Item::item_err;
|
||||
}
|
||||
|
||||
@@ -788,29 +805,10 @@ void PatternParser::ReadDirectiveBlock(Item & item)
|
||||
void PatternParser::ReadDirectiveReturn(Item & item)
|
||||
{
|
||||
item.type = Item::item_return;
|
||||
ReadFunctions(item);
|
||||
|
||||
// max one function
|
||||
if( item.functions.size() > 1 )
|
||||
item.type = Item::item_err;
|
||||
ReadFunction(item);
|
||||
}
|
||||
|
||||
|
||||
// user defined directive
|
||||
void PatternParser::ReadDirectiveNormal(const std::wstring & name, Item & item)
|
||||
{
|
||||
temp_function.Clear();
|
||||
ReadParams(temp_function);
|
||||
temp_function.name = name;
|
||||
|
||||
if( IsPositiveNumber(name) )
|
||||
temp_function.arg = wcstol(name.c_str(), 0, 10);
|
||||
|
||||
item.functions.clear();
|
||||
|
||||
item.functions.push_back(temp_function);
|
||||
item.type = Item::item_normal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -822,11 +820,6 @@ std::wstring name;
|
||||
ReadName(name);
|
||||
|
||||
if ( name == L"if" ) ReadDirectiveIf(item);
|
||||
else if( name == L"if-no" ) ReadDirectiveIfno(item);
|
||||
else if( name == L"if-any" ) ReadDirectiveIfany(item);
|
||||
else if( name == L"if-one" ) ReadDirectiveIfone(item);
|
||||
else if( name == L"if-any-no" ) ReadDirectiveIfanyno(item);
|
||||
else if( name == L"if-one-no" ) ReadDirectiveIfoneno(item);
|
||||
else if( name == L"end" ) ReadDirectiveEnd(item);
|
||||
else if( name == L"else" ) ReadDirectiveElse(item);
|
||||
else if( name == L"for" ) ReadDirectiveFor(item);
|
||||
@@ -837,8 +830,7 @@ std::wstring name;
|
||||
else if( name == L"block" ) ReadDirectiveBlock(item);
|
||||
else if( name == L"return" ) ReadDirectiveReturn(item);
|
||||
else if( name == L"#" ) ReadDirectiveComment(item);
|
||||
else
|
||||
ReadDirectiveNormal(name, item);
|
||||
else if( !name.empty() ) ReadDirectiveNormal(name, item);
|
||||
|
||||
CreateTreeReadItemDirectiveCheckEnding(item);
|
||||
}
|
||||
@@ -950,8 +942,9 @@ Item item_block;
|
||||
if( item_block.LastItemType() == Item::item_end )
|
||||
item_block.DeleteLastItem();
|
||||
|
||||
if( pblocks && item.functions.size()==1 )
|
||||
pblocks->Insert(item.functions[0].name, item_block);
|
||||
//if( pblocks && item.functions.size()==1 )
|
||||
if( pblocks )
|
||||
pblocks->Insert(item.function.name, item_block);
|
||||
}
|
||||
|
||||
|
||||
@@ -993,13 +986,8 @@ void PatternParser::CreateTree(Item & item)
|
||||
if( pitem->type == Item::item_end || pitem->type == Item::item_else )
|
||||
return;
|
||||
|
||||
if( pitem->type == Item::item_if ||
|
||||
pitem->type == Item::item_ifno ||
|
||||
pitem->type == Item::item_ifany ||
|
||||
pitem->type == Item::item_ifone ||
|
||||
pitem->type == Item::item_ifanyno ||
|
||||
pitem->type == Item::item_ifoneno )
|
||||
CreateTreeReadIf(*pitem);
|
||||
if( pitem->type == Item::item_if )
|
||||
CreateTreeReadIf(*pitem);
|
||||
|
||||
if( pitem->type == Item::item_for ||
|
||||
pitem->type == Item::item_filter )
|
||||
|
Reference in New Issue
Block a user