//****************************************************************************** /// /// @file parser/parser_functions_utilities.cpp /// /// This module implements the the function type used by iso surfaces and the /// function pattern. /// /// This module is based on code by D. Skarda, T. Bily and R. Suzuki. /// /// @copyright /// @parblock /// /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8. /// Copyright 1991-2019 Persistence of Vision Raytracer Pty. Ltd. /// /// POV-Ray is free software: you can redistribute it and/or modify /// it under the terms of the GNU Affero General Public License as /// published by the Free Software Foundation, either version 3 of the /// License, or (at your option) any later version. /// /// POV-Ray is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU Affero General Public License for more details. /// /// You should have received a copy of the GNU Affero General Public License /// along with this program. If not, see . /// /// ---------------------------------------------------------------------------- /// /// POV-Ray is based on the popular DKB raytracer version 2.12. /// DKBTrace was originally written by David K. Buck. /// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. /// /// @endparblock /// //****************************************************************************** // Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config) #include "parser/parser.h" // C++ variants of C standard header files // C++ standard header files // (none at the moment) // POV-Ray header files (base module) // (none at the moment) // POV-Ray header files (core module) #include "core/material/pigment.h" #include "core/math/matrix.h" #include "core/math/spline.h" #include "core/scene/scenedata.h" // POV-Ray header files (VM module) #include "vm/fnpovfpu.h" // POV-Ray header files (parser module) // (none at the moment) // this must be the last file included #include "base/povdebug.h" namespace pov_parser { using namespace pov; /***************************************************************************** * * FUNCTION * * Parse_Function * * INPUT * * OUTPUT * * RETURNS * * FUNCTION - parsed and compiled function reference number * * AUTHOR * * Thorsten Froehlich * * DESCRIPTION * * Parse and compile a function and add it to the global function table. * * CHANGES * * - * ******************************************************************************/ FUNCTION_PTR Parser::Parse_Function(void) { FUNCTION_PTR ptr = new FUNCTION; ExprNode *expression = nullptr; FunctionCode function; Parse_Begin(); FNCode f(this, &function, false, nullptr); expression = FNSyntax_ParseExpression(); f.Compile(expression); FNSyntax_DeleteExpression(expression); Parse_End(); *ptr = mpFunctionVM->AddFunction(&function); return ptr; } /***************************************************************************** * * FUNCTION * * Parse_FunctionContent * * INPUT * * OUTPUT * * RETURNS * * FUNCTION - parsed and compiled function reference number * * AUTHOR * * Thorsten Froehlich * * DESCRIPTION * * Parse and compile a function and add it to the global function table. * * CHANGES * * - * ******************************************************************************/ FUNCTION_PTR Parser::Parse_FunctionContent(void) { FUNCTION_PTR ptr = new FUNCTION; ExprNode *expression = nullptr; FunctionCode function; FNCode f(this, &function, false, nullptr); expression = FNSyntax_ParseExpression(); f.Compile(expression); FNSyntax_DeleteExpression(expression); *ptr = mpFunctionVM->AddFunction(&function); return ptr; } FUNCTION_PTR Parser::Parse_FunctionOrContent(void) { FUNCTION_PTR result; if (AllowToken(FUNCTION_TOKEN)) result = Parse_Function(); else result = Parse_FunctionContent(); return result; } void Parser::Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count, bool mandatory) { for (unsigned int i = 0; i < count; ++i) { if (!mandatory && (Peek_Token(RIGHT_CURLY_TOKEN) || Parse_Comma())) { apFn[i] = nullptr; continue; } apFn[i] = new FunctionVM::CustomFunction(fnVMContext->functionvm.get(), Parse_FunctionOrContent()); if (i < count-1) Parse_Comma(); } } /***************************************************************************** * * FUNCTION * * Parse_DeclareFunction * * INPUT * * OUTPUT * * RETURNS * * FUNCTION - parsed and compiled function reference number * * AUTHOR * * Thorsten Froehlich * * DESCRIPTION * * Parse and compile a function and add it to the global function table. * Additionally, this function takes an optional list of parameter names. * * CHANGES * * - * ******************************************************************************/ FUNCTION_PTR Parser::Parse_DeclareFunction(TokenId *token_id, const char *fn_name, bool is_local) { FUNCTION_PTR ptr = new FUNCTION; ExprNode *expression = nullptr; FunctionCode function; // default type is float function *token_id = FUNCT_ID_TOKEN; FNCode f(this, &function, is_local, fn_name); f.Parameter(); Parse_Begin(); Get_Token(); if(CurrentTrueTokenId() == INTERNAL_TOKEN) { Parse_Paren_Begin(); Get_Token(); if(CurrentTrueTokenId() != FLOAT_TOKEN) Expectation_Error("internal function identifier"); expression = FNSyntax_GetTrapExpression((unsigned int)(mToken.Token_Float)); function.flags = FN_INLINE_FLAG; Parse_Paren_End(); } else if(CurrentTrueTokenId() == TRANSFORM_TOKEN) { if(function.parameter_cnt != 0) Error("Function parameters for transform functions are not allowed."); expression = FNSyntax_GetTrapExpression(1); // 1 refers to POVFPU_TrapSTable[1] = f_transform [trf] function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Transform; function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Transform; function.private_data = reinterpret_cast(Parse_Transform_Block()); function.return_size = 3; // returns a 3d vector!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(CurrentTrueTokenId() == SPLINE_TOKEN) { if(function.parameter_cnt != 0) Error("Function parameters for spline functions are not allowed."); mExperimentalFlags.spline = true; expression = FNSyntax_GetTrapExpression(2); // 2 refers to POVFPU_TrapSTable[2] = f_spline [trf] function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Spline; function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Spline; Parse_Begin(); function.private_data = reinterpret_cast(Parse_Spline()); Parse_End(); function.return_size = (reinterpret_cast(function.private_data))->Terms; // returns a 2d, 3d, 4d or 5d vector!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(CurrentTrueTokenId() == PIGMENT_TOKEN) { if(function.parameter_cnt != 0) Error("Function parameters for pigment functions are not allowed."); expression = FNSyntax_GetTrapExpression(0); // 0 refers to POVFPU_TrapSTable[0] = f_pigment [trf] function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Pigment; function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Pigment; Parse_Begin(); function.private_data = reinterpret_cast(Create_Pigment()); Parse_Pigment(reinterpret_cast(&function.private_data)); Parse_End(); Post_Pigment(reinterpret_cast(function.private_data)); function.return_size = 5; // returns a color!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(CurrentTrueTokenId() == PATTERN_TOKEN) { if(function.parameter_cnt != 0) Error("Function parameters for pattern functions are not allowed."); expression = FNSyntax_GetTrapExpression(77); // 77 refers to POVFPU_TrapTable[77] = f_pattern [trf] function.private_copy_method = (FNCODE_PRIVATE_COPY_METHOD)Copy_Pigment; function.private_destroy_method = (FNCODE_PRIVATE_DESTROY_METHOD)Destroy_Pigment; Parse_Begin(); function.private_data = reinterpret_cast(Create_Pigment()); // Yes, this is a pigment! [trf] Parse_PatternFunction(reinterpret_cast(function.private_data)); Parse_End(); Post_Pigment(reinterpret_cast(function.private_data)); } else if(CurrentTrueTokenId() == STRING_LITERAL_TOKEN) { #if (DEBUG_FLOATFUNCTION == 1) f.SetFlag(2, CurrentTokenText().c_str()); #endif Get_Token(); if(CurrentTrueTokenId() == COMMA_TOKEN) { Get_Token(); if(CurrentTrueTokenId() != STRING_LITERAL_TOKEN) Expectation_Error("valid function expression"); #if (DEBUG_FLOATFUNCTION == 1) f.SetFlag(1, CurrentTokenText().c_str()); #endif } else { Unget_Token(); expression = FNSyntax_ParseExpression(); } } else { Unget_Token(); expression = FNSyntax_ParseExpression(); } f.Compile(expression); FNSyntax_DeleteExpression(expression); Parse_End(); *ptr = mpFunctionVM->AddFunction(&function); return ptr; } boost::intrusive_ptr Parser::GetFunctionVM() const { return mpFunctionVM; } } // end of namespace pov_parser