// Parse a cell Cell* Parser::Parse_Cell(Cell* cell, bool topLevel) { // Parse the cells and check for errors along the way. if (cell->IsPair()) { // Parse the pair if (cell->IsNull()) { // Empty list return cell; } else if (cell->Car()->GetType() & Cell::SymbolType) { const Sym* symbol = cell->Car()->GetSymbol(); if (symbol == Sym::Symbol("_quote")) { return Parse_Quote(cell); } else if (symbol == Sym::Symbol("_if")) { return Parse_If(cell); } else if (symbol == Sym::Symbol("_set!")) { return Parse_Set(cell); } else if (symbol == Sym::Symbol("_begin")) { return Parse_Begin(cell, topLevel); } else if (symbol == Sym::Symbol("_define")) { return Parse_Define(cell,topLevel); } else if (symbol == Sym::Symbol("_lambda")) { return Parse_Lambda(cell); } else if (symbol == Sym::Symbol("_quasiquote")) { THROW_ERROR_IF(cell->Length() != 2, cell, "Quasiquote does not take " << cell->Length() << " arguments"); return Parse_Quasiquote(cell->Cdr()); } } } // Not a list, just return it. return cell; }
FUNCTION_PTR Parser::Parse_Function(void) { FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID"); ExprNode *expression = NULL; FunctionCode function; Parse_Begin(); FNCode f(this, &function, false, NULL); expression = FNSyntax_ParseExpression(); f.Compile(expression); FNSyntax_DeleteExpression(expression); Parse_End(); *ptr = sceneData->functionVM->AddFunction(&function); return ptr; }
FUNCTION_PTR Parser::Parse_DeclareFunction(int *token_id, const char *fn_name, bool is_local) { FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID"); ExprNode *expression = NULL; 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(Token.Token_Id == INTERNAL_TOKEN) { GET(LEFT_PAREN_TOKEN); Get_Token(); if(Token.Function_Id != FLOAT_TOKEN) Expectation_Error("internal function identifier"); expression = FNSyntax_GetTrapExpression((unsigned int)(Token.Token_Float)); function.flags = FN_INLINE_FLAG; GET(RIGHT_PAREN_TOKEN); } else if(Token.Token_Id == 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<void *>(Parse_Transform_Block()); function.return_size = 3; // returns a 3d vector!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(Token.Token_Id == SPLINE_TOKEN) { if(function.parameter_cnt != 0) Error("Function parameters for spline functions are not allowed."); Experimental_Flag |= EF_SPLINE; 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<void *>(Parse_Spline()); Parse_End(); function.return_size = (reinterpret_cast<SPLINE *>(function.private_data))->Terms; // returns a 2d, 3d, 4d or 5d vector!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(Token.Token_Id == 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<void *>(Create_Pigment()); Parse_Pigment(reinterpret_cast<PIGMENT **>(&function.private_data)); Parse_End(); Post_Pigment(reinterpret_cast<PIGMENT *>(function.private_data)); function.return_size = 5; // returns a color!!! // function type is vector function *token_id = VECTFUNCT_ID_TOKEN; } else if(Token.Token_Id == 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<void *>(Create_Pigment()); // Yes, this is a pigment! [trf] Parse_PatternFunction(reinterpret_cast<TPATTERN *>(function.private_data)); Parse_End(); Post_Pigment(reinterpret_cast<PIGMENT *>(function.private_data)); } else if(Token.Token_Id == STRING_LITERAL_TOKEN) { f.SetFlag(2, Token.Token_String); Get_Token(); if(Token.Token_Id == COMMA_TOKEN) { Get_Token(); if(Token.Token_Id != STRING_LITERAL_TOKEN) Expectation_Error("valid function expression"); f.SetFlag(1, Token.Token_String); } else { Unget_Token(); expression = FNSyntax_ParseExpression(); } } else { Unget_Token(); expression = FNSyntax_ParseExpression(); } f.Compile(expression); FNSyntax_DeleteExpression(expression); Parse_End(); *ptr = sceneData->functionVM->AddFunction(&function); return ptr; }