使用C+&#x2B中的“ constexpr`库”来调用`constexpr`库
我正处于学期的结尾,需要进入这个学期,在过去的几天里,我一直在努力将功能呼叫实施到我的语言中。我正在使用 ctpg 在C ++中实现constexpr lr1 parser的库编译时间,这很重要,因为主要问题是,无论我做什么,我最终都会在编译时以无限的解析循环(GCC告诉我一些constexpr的东西都达到了最大的深度,并且有一个编译器选项可以使它成为更深入)。如果您不熟悉CTPG,而是对编译器有所了解,我希望您能获得此代码的“ JIST”,例如
non_terminal_term< ToReduceToHere >( non_terminal_term< Some > term< Pattern >, term< Here >, term< MyRegex >, term< MyString >, term< MyChar > )
>= []( auto some, auto pattern, auto fed_here, auto my_regex, auto my_string, auto my_char ) {
// Do something ...
return MyDataTypeCorrespondingTo<ToReduceToHere> {};
}
//Simple list parser using raw library.//
ctpg::nterm< std::vector< int > > list;
ctpg::regex_term< "[1-9][0-9]*" > number;
ctpg::parser list_parser(
list, // What to reduce too
ctpg::terms( number, ',' ),
ctpg::nterms( list ),
ctpg::rules(
list( number, ',' )
>= []( auto number, auto comma )
std::vector< int > new_list;
new_list.push_back( to_int( number ) );
return new_list;
},
list( list, number, ',' )
>= []( auto current_list, auto num, auto comma )
current_list.push_back( to_int( num ) );
return current_list;
}
)
);
我希望函数调用是“因素”,并且在数学表达式中可用(功能只是我语言中简单的算术表达式 具有比较和逻辑运算符
)
//////////////////////////////// "Literals" ////////////////////////////////
non_terminal_term< Factor >( term< FunctionResult > ) //`@` is a special variable used for a contracts, nothing really to do with call syntax. //
>= []( auto token ) {
return std::move( Warp::Utilities::allocate_node< FunctionResult >() );
},
non_terminal_term< Factor >( term< Identifier > )
>= []( auto token ) {
return std::move( Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( token ) ) );
},
non_terminal_term< Factor >( term< NaturalNumber > )
>= []( auto token )
{
return std::move( Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( token ) );
},
//////////////////////////////// Multiplication/Division ////////////////////////////////
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< NaturalNumber > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
current_factor,
Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( next_token )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, term< NaturalNumber > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorDivide >(
current_factor,
Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( next_token )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< Identifier > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
current_factor,
Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( next_token ) )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, term< Identifier > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorDivide >(
current_factor,
Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( next_token ) )
);
},
//////////////////////////////// Parenthesis ////////////////////////////////
non_terminal_term< ParenthesisScope >( term< OpenParenthesis >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= [] ( auto, auto factor, auto ) { return factor; },
non_terminal_term< Factor >( non_terminal_term< ParenthesisScope > )
>= []( auto parenthesis_scope ) { return parenthesis_scope; },
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, non_terminal_term< ParenthesisScope > )
>= []( auto factor, auto, auto parenthesis_scope )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
factor,
parenthesis_scope
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, non_terminal_term< ParenthesisScope > )
>= []( auto factor, auto, auto parenthesis_scope )
{
return Warp::Utilities::allocate_node< FactorDivide >(
factor,
parenthesis_scope
);
},
//////////////////////////////// Addition/Subtraction ////////////////////////////////
non_terminal_term< Factor >( non_terminal_term< Sum > )
>= []( auto sum ) {
return sum;
},
non_terminal_term< Sum >( non_terminal_term< Factor >, term< SumAdd >, non_terminal_term< Factor > )
>= []( auto current_sum, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< SumAdd >(
current_sum,
next_token
);
},
non_terminal_term< Sum >( non_terminal_term< Factor >, term< SumSubtract >, non_terminal_term< Factor > )
>= []( auto current_sum, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< SumSubtract >(
current_sum,
next_token
);
},
non_terminal_term< Expression >( non_terminal_term< Factor > )
>= []( auto factor ) {
return factor;
},
//...
(
non_terminal_term< Call >( term< Identifier >, term< OpenParenthesis > )
>= []( auto identifier, auto ) // function, auto identifier, auto )
{
std::cout << "Call found!\n";
return Warp::CompilerRuntime::CallType{
Warp::Utilities::hash_string( identifier ),
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
};
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto )
{
std::cout << "Argument buffered!\n";
return Warp::CompilerRuntime::CallType{
call.identifier,
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{
call.arguments,
argument
}
};
},
non_terminal_term< Factor >( non_terminal_term< Call >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
std::cout << "Call end 0!\n";
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{
call.arguments,
argument
}
);
},
non_terminal_term< Factor >( non_terminal_term< Call >, term< CloseParenthesis > )
>= []( auto call, auto )
{
std::cout << "Call end 1!\n";
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
}
。
static TestSuiteType factor_calls{
WarpTest{ true, "test( 1 )" },
WarpTest{ true, "test( a )" },
WarpTest{ true, "20 * test( a )" },
WarpTest{ true, "20 + test( a )" },
WarpTest{ true, "test( a ) * 20" },
WarpTest{ true, "test( a ) + 10" },
WarpTest{ true, "test( a * a )" },
WarpTest{ true, "test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 )" },
WarpTest{ true, "test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 )" },
WarpTest{ true, "test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 )" }
};
在参数列表中 降低编译器的函数的上下文似乎进入了无限的循环并不会编译解析器,以了解我正在为整个功能而使用的测试用例:
static TestSuiteType function_alternative_calls{
WarpTest{ true, "let test( a : a < 64 ) :: test( 1 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: 20 * test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: 20 + test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a ) * 20;" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a ) + 10;" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a * a );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );" }
};
它的至关重要 我可以使用
递归
Pass: let test( a : a < 64 ) :: test( 1 );
Pass: let test( a : a < 64 ) :: test( a );
[1:36] PARSE: Syntax error: Unexpected '('
Fail: let test( a : a < 64 ) :: 20 * test( a );
[1:38] PARSE: Syntax error: Unexpected 'Identifier'
Fail: let test( a : a < 64 ) :: 20 + test( a );
Pass: let test( a : a < 64 ) :: test( a ) * 20;
[1:37] PARSE: Syntax error: Unexpected '+'
Fail: let test( a : a < 64 ) :: test( a ) + 10;
Pass: let test( a : a < 64 ) :: test( a * a );
Pass: let test( a : a < 64 ) :: test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 );
Pass: let test( a : a < 64 ) :: test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );
Pass: let test( a : a < 64 ) :: test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );
完成,
//... code that analyzes function parameters tries to buffer the expression after the `::` operator
non_terminal_term< ExpressionEater >( non_terminal_term< ExpressionEater >, term< FactorMultiply >, non_terminal_term< Expression > )
>= []( auto function, auto, auto factor ) {
return subsume_function_alternative_expression< FactorMultiply >( function, factor );
},
non_terminal_term< ExpressionEater >( non_terminal_term< ExpressionEater >, term< FactorDivide >, non_terminal_term< Expression > )
>= []( auto function, auto, auto factor ) {
return subsume_function_alternative_expression< FactorDivide >( function, factor );
},
non_terminal_term< Call >( term< Identifier >, term< OpenParenthesis > )
>= []( auto identifier, auto )
{
return Warp::CompilerRuntime::CallType{
Warp::Utilities::hash_string( identifier ),
std::vector< Warp::AbstractSyntaxTree::NodeVariantType >{}
//Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
};
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto ) {
call.arguments.push_back( argument );
return call;
},
non_terminal_term< CallNode >( non_terminal_term< Call >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
call.arguments.push_back( argument );
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< CallNode >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto ) {
call.arguments.push_back( argument );
return call;
},
non_terminal_term< CallNode >( non_terminal_term< Call >, non_terminal_term< CallNode >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< CallNode >( non_terminal_term< Call >, term< CloseParenthesis > )
>= []( auto call, auto )
{
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< Expression >( non_terminal_term< CallNode > )
>= []( auto call ) {
return call;
}
。 “部分重新实施因素,朝着那里的顶部重新实现。 它不能总和,并且在功能调用之前不能考虑任何产品。
我已经尝试了所有您可以详细进行的更改 >但总而言之,主要问题是,如果我尝试将其循环回到一个因素或等效的任何意义上,并且将呼叫视为一个因素(我也是我想要的),则编译器无限地循环,即使在减少一个因素时效果很好。我将终端项,非终端处理等放置似乎很重要。
我也尝试过的一件事是从来没有“离开”因子评估。
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< Identifier >, term< OpenParenthesis > )
>= []( auto factor, auto, auto identifier, auto )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
factor,
Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
Warp::Utilities::hash_string( identifier ),
std::vector< Warp::AbstractSyntaxTree::NodeVariantType >{}
// Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
)
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= []( auto operation_call, auto argument, auto )
{
if( Warp::Utilities::is_bi_node( operation_call ) == false )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "Bi-Node not found where expected (Factor, Factor, NextParmaeterToken(Comma))! "
<< "Returning first factor.\n";
}
auto proxy = Warp::Utilities::bi_node_proxy( operation_call ).value();
if( Warp::Utilities::tag_is< Warp::AbstractSyntaxTree::NodeType::FunctionCall >( proxy.right ) == true )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "FunctionCall not found where expected (Factor (left: Factor, right: FunctionCall), "
<< "Factor, NextParmaeterToken(Comma))! Returning first factor.\n";
}
auto call = static_cast< Warp::CompilerRuntime::CallType* >( proxy.right->get_data() );
call->arguments.push_back( argument );
return operation_call;
},
non_terminal_term< Factor >( non_terminal_term< Factor >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto operation_call, auto argument, auto )
{
if( Warp::Utilities::is_bi_node( operation_call ) == false )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "Bi-Node not found where expected (Factor, Factor, CloseParenthesis)! "
<< "Returning first factor.\n";
}
auto proxy = Warp::Utilities::bi_node_proxy( operation_call ).value();
if( Warp::Utilities::tag_is< Warp::AbstractSyntaxTree::NodeType::FunctionCall >( proxy.right ) == true )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "FunctionCall not found where expected (Factor (left: Factor, right: FunctionCall), "
<< "Factor, CloseParenthesis)! Returning first factor.\n";
}
auto call = static_cast< Warp::CompilerRuntime::CallType* >( proxy.right->get_data() );
call->arguments.push_back( argument );
return operation_call;
}
不幸的是,它的结果相同:(
尝试某些伪 - bnf的尝试 - 我已经
call :=
| <identifier > (
| <call> <factor> ,
| <complete-call> ,
complete-call =
| <call> < factor > )
| <call> )
factor/expression = complete-call
call :=
| <identifier > (
| <call> <argument-list> )
| <call> )
argument-list =
| <factor> ,
| <argument-list> <factor>,
factor :=
| <factor> * <literal>
| <factor> / <literal>
| <factor> * <identifier> (
| <factor>,
| <factor> )
在各种排列和版本中尝试了所有这些(再次您可以查看我的更改在此分支上
如何制作此终端,以便编译器不会永远流失,我可以拨打函数?
我 感谢
您的阅读!
I'm at the end of the semester and need to get this in, I have been struggling for the last few days to implement function calls into my language. I am using the ctpg library which implements a constexpr LR1 parser in C++17 so everything is compile time, this is important because the main problem is it seems no matter what I do I end up with an infinite parsing loop at compile-time (gcc tells me some constexpr thing hits the maximum depth and there is a compiler option to make it go deeper). If your not familiar with ctpg specifically but know something about compilers, I hope you can get the "jist" of this code e.g.
non_terminal_term< ToReduceToHere >( non_terminal_term< Some > term< Pattern >, term< Here >, term< MyRegex >, term< MyString >, term< MyChar > )
>= []( auto some, auto pattern, auto fed_here, auto my_regex, auto my_string, auto my_char ) {
// Do something ...
return MyDataTypeCorrespondingTo<ToReduceToHere> {};
}
//Simple list parser using raw library.//
ctpg::nterm< std::vector< int > > list;
ctpg::regex_term< "[1-9][0-9]*" > number;
ctpg::parser list_parser(
list, // What to reduce too
ctpg::terms( number, ',' ),
ctpg::nterms( list ),
ctpg::rules(
list( number, ',' )
>= []( auto number, auto comma )
std::vector< int > new_list;
new_list.push_back( to_int( number ) );
return new_list;
},
list( list, number, ',' )
>= []( auto current_list, auto num, auto comma )
current_list.push_back( to_int( num ) );
return current_list;
}
)
);
I want functions calls to be "factors" and usable in mathematical expressions (functions are just simple arithmetic expressions in my language with, argument lists (which have comparisons and logical operators).
The way I get factors right now is something like this:
//////////////////////////////// "Literals" ////////////////////////////////
non_terminal_term< Factor >( term< FunctionResult > ) //`@` is a special variable used for a contracts, nothing really to do with call syntax. //
>= []( auto token ) {
return std::move( Warp::Utilities::allocate_node< FunctionResult >() );
},
non_terminal_term< Factor >( term< Identifier > )
>= []( auto token ) {
return std::move( Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( token ) ) );
},
non_terminal_term< Factor >( term< NaturalNumber > )
>= []( auto token )
{
return std::move( Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( token ) );
},
//////////////////////////////// Multiplication/Division ////////////////////////////////
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< NaturalNumber > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
current_factor,
Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( next_token )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, term< NaturalNumber > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorDivide >(
current_factor,
Warp::Utilities::allocate_integral_literal_node<
ResolvedType< NaturalNumber >
>( next_token )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< Identifier > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
current_factor,
Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( next_token ) )
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, term< Identifier > )
>= []( auto current_factor, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< FactorDivide >(
current_factor,
Warp::Utilities::allocate_node<
Warp::AbstractSyntaxTree::NodeType::Identifier
>( Warp::Utilities::hash_string( next_token ) )
);
},
//////////////////////////////// Parenthesis ////////////////////////////////
non_terminal_term< ParenthesisScope >( term< OpenParenthesis >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= [] ( auto, auto factor, auto ) { return factor; },
non_terminal_term< Factor >( non_terminal_term< ParenthesisScope > )
>= []( auto parenthesis_scope ) { return parenthesis_scope; },
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, non_terminal_term< ParenthesisScope > )
>= []( auto factor, auto, auto parenthesis_scope )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
factor,
parenthesis_scope
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorDivide >, non_terminal_term< ParenthesisScope > )
>= []( auto factor, auto, auto parenthesis_scope )
{
return Warp::Utilities::allocate_node< FactorDivide >(
factor,
parenthesis_scope
);
},
//////////////////////////////// Addition/Subtraction ////////////////////////////////
non_terminal_term< Factor >( non_terminal_term< Sum > )
>= []( auto sum ) {
return sum;
},
non_terminal_term< Sum >( non_terminal_term< Factor >, term< SumAdd >, non_terminal_term< Factor > )
>= []( auto current_sum, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< SumAdd >(
current_sum,
next_token
);
},
non_terminal_term< Sum >( non_terminal_term< Factor >, term< SumSubtract >, non_terminal_term< Factor > )
>= []( auto current_sum, auto, const auto& next_token )
{
return Warp::Utilities::allocate_node< SumSubtract >(
current_sum,
next_token
);
},
non_terminal_term< Expression >( non_terminal_term< Factor > )
>= []( auto factor ) {
return factor;
},
//...
If I am just trying to reduce factors the following works perfectly
non_terminal_term< Call >( term< Identifier >, term< OpenParenthesis > )
>= []( auto identifier, auto ) // function, auto identifier, auto )
{
std::cout << "Call found!\n";
return Warp::CompilerRuntime::CallType{
Warp::Utilities::hash_string( identifier ),
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
};
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto )
{
std::cout << "Argument buffered!\n";
return Warp::CompilerRuntime::CallType{
call.identifier,
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{
call.arguments,
argument
}
};
},
non_terminal_term< Factor >( non_terminal_term< Call >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
std::cout << "Call end 0!\n";
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{
call.arguments,
argument
}
);
},
non_terminal_term< Factor >( non_terminal_term< Call >, term< CloseParenthesis > )
>= []( auto call, auto )
{
std::cout << "Call end 1!\n";
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
}
Here are the test cases
static TestSuiteType factor_calls{
WarpTest{ true, "test( 1 )" },
WarpTest{ true, "test( a )" },
WarpTest{ true, "20 * test( a )" },
WarpTest{ true, "20 + test( a )" },
WarpTest{ true, "test( a ) * 20" },
WarpTest{ true, "test( a ) + 10" },
WarpTest{ true, "test( a * a )" },
WarpTest{ true, "test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 )" },
WarpTest{ true, "test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 )" },
WarpTest{ true, "test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 )" }
};
But when I try to put it in the context of reducing a function the compiler seems to get into an infinite loop and wont compile the parser. To get an idea of the test cases I am working with for a whole function:
static TestSuiteType function_alternative_calls{
WarpTest{ true, "let test( a : a < 64 ) :: test( 1 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: 20 * test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: 20 + test( a );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a ) * 20;" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a ) + 10;" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a * a );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );" },
WarpTest{ true, "let test( a : a < 64 ) :: test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );" }
};
Its crucial I make this work so my language can be Turing complete and I can use recursion.
I am able to get all these tests with the exception of 3, here are those results:
Pass: let test( a : a < 64 ) :: test( 1 );
Pass: let test( a : a < 64 ) :: test( a );
[1:36] PARSE: Syntax error: Unexpected '('
Fail: let test( a : a < 64 ) :: 20 * test( a );
[1:38] PARSE: Syntax error: Unexpected 'Identifier'
Fail: let test( a : a < 64 ) :: 20 + test( a );
Pass: let test( a : a < 64 ) :: test( a ) * 20;
[1:37] PARSE: Syntax error: Unexpected '+'
Fail: let test( a : a < 64 ) :: test( a ) + 10;
Pass: let test( a : a < 64 ) :: test( a * a );
Pass: let test( a : a < 64 ) :: test( a(), b( q, 4, 5646, 345345 * 445656 + 34 ), rdfg * 34534 );
Pass: let test( a : a < 64 ) :: test( a, q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );
Pass: let test( a : a < 64 ) :: test( ttt(), q, 4, 5646, 345345 * 445656 + 34, rdfg * 34534 );
Here is the code that makes that work:
//... code that analyzes function parameters tries to buffer the expression after the `::` operator
non_terminal_term< ExpressionEater >( non_terminal_term< ExpressionEater >, term< FactorMultiply >, non_terminal_term< Expression > )
>= []( auto function, auto, auto factor ) {
return subsume_function_alternative_expression< FactorMultiply >( function, factor );
},
non_terminal_term< ExpressionEater >( non_terminal_term< ExpressionEater >, term< FactorDivide >, non_terminal_term< Expression > )
>= []( auto function, auto, auto factor ) {
return subsume_function_alternative_expression< FactorDivide >( function, factor );
},
non_terminal_term< Call >( term< Identifier >, term< OpenParenthesis > )
>= []( auto identifier, auto )
{
return Warp::CompilerRuntime::CallType{
Warp::Utilities::hash_string( identifier ),
std::vector< Warp::AbstractSyntaxTree::NodeVariantType >{}
//Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
};
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto ) {
call.arguments.push_back( argument );
return call;
},
non_terminal_term< CallNode >( non_terminal_term< Call >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
call.arguments.push_back( argument );
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< Call >( non_terminal_term< Call >, non_terminal_term< CallNode >, term< FunctionParameterNextParameter > )
>= [](auto call, auto argument, auto ) {
call.arguments.push_back( argument );
return call;
},
non_terminal_term< CallNode >( non_terminal_term< Call >, non_terminal_term< CallNode >, term< CloseParenthesis > )
>= []( auto call, auto argument, auto )
{
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< CallNode >( non_terminal_term< Call >, term< CloseParenthesis > )
>= []( auto call, auto )
{
return Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
call.identifier,
call.arguments
);
},
non_terminal_term< Expression >( non_terminal_term< CallNode > )
>= []( auto call ) {
return call;
}
As you may be able to see this is a bit of a "hack" partially re-implementing factors towards the top there.
It cant do sums and it cant take into account any products before the function call.
I have tried everything you can see some of the changes I have made in detail on this branch but to summarize, the main problem is though if I try to make this "complete" in any sense where it loops back to a factor or its equivalent and treats the call like a factor (as I want it too) the compiler infinitely loops, even though it works just fine when reducing just a factor. It doesent seem to matter where I put the terminal terms, non-terminal-terms, etc.
One thing I have also tried is never "leaving" factor evaluation.
non_terminal_term< Factor >( non_terminal_term< Factor >, term< FactorMultiply >, term< Identifier >, term< OpenParenthesis > )
>= []( auto factor, auto, auto identifier, auto )
{
return Warp::Utilities::allocate_node< FactorMultiply >(
factor,
Warp::Utilities::allocate_node< Warp::AbstractSyntaxTree::NodeType::FunctionCall >(
Warp::Utilities::hash_string( identifier ),
std::vector< Warp::AbstractSyntaxTree::NodeVariantType >{}
// Warp::Utilities::VectorType< Warp::AbstractSyntaxTree::NodeVariantType >{}
)
);
},
non_terminal_term< Factor >( non_terminal_term< Factor >, non_terminal_term< Factor >, term< FunctionParameterNextParameter > )
>= []( auto operation_call, auto argument, auto )
{
if( Warp::Utilities::is_bi_node( operation_call ) == false )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "Bi-Node not found where expected (Factor, Factor, NextParmaeterToken(Comma))! "
<< "Returning first factor.\n";
}
auto proxy = Warp::Utilities::bi_node_proxy( operation_call ).value();
if( Warp::Utilities::tag_is< Warp::AbstractSyntaxTree::NodeType::FunctionCall >( proxy.right ) == true )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "FunctionCall not found where expected (Factor (left: Factor, right: FunctionCall), "
<< "Factor, NextParmaeterToken(Comma))! Returning first factor.\n";
}
auto call = static_cast< Warp::CompilerRuntime::CallType* >( proxy.right->get_data() );
call->arguments.push_back( argument );
return operation_call;
},
non_terminal_term< Factor >( non_terminal_term< Factor >, non_terminal_term< Factor >, term< CloseParenthesis > )
>= []( auto operation_call, auto argument, auto )
{
if( Warp::Utilities::is_bi_node( operation_call ) == false )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "Bi-Node not found where expected (Factor, Factor, CloseParenthesis)! "
<< "Returning first factor.\n";
}
auto proxy = Warp::Utilities::bi_node_proxy( operation_call ).value();
if( Warp::Utilities::tag_is< Warp::AbstractSyntaxTree::NodeType::FunctionCall >( proxy.right ) == true )
{
std::cerr << "ERROR!!!: Attempt to parse function call failed! "
<< "FunctionCall not found where expected (Factor (left: Factor, right: FunctionCall), "
<< "Factor, CloseParenthesis)! Returning first factor.\n";
}
auto call = static_cast< Warp::CompilerRuntime::CallType* >( proxy.right->get_data() );
call->arguments.push_back( argument );
return operation_call;
}
Unfortunately its the same result :(
An attempt at some pseudo - BNF's I have tried
call :=
| <identifier > (
| <call> <factor> ,
| <complete-call> ,
complete-call =
| <call> < factor > )
| <call> )
factor/expression = complete-call
call :=
| <identifier > (
| <call> <argument-list> )
| <call> )
argument-list =
| <factor> ,
| <argument-list> <factor>,
factor :=
| <factor> * <literal>
| <factor> / <literal>
| <factor> * <identifier> (
| <factor>,
| <factor> )
All these in various permutations and versions (again you can look at my changes on this branch
How do I make this terminal so the compiler does not churn forever and I can parse function calls?
I'm really under the wire, any help would really be appreciated!
Thank you so much for reading!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论