You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求协助:基于给定BNF文法实现C++简单代码随机生成

Got it, let's break down how to build a random C++ code generator based on your BNF grammar. First, let's clarify and complete the truncated parts of your BNF with common C++ semantics (since your if_stat and iter_stat were cut off):

Complete BNF Grammar

<prog> ::= "int main() { " <stat_list> " return 0; }"
<stat_list> ::= <stat> | <stat_list> <stat>
<stat> ::= <cmpd_stat> | <if_stat> | <iter_stat> | <assgn_stat> | <decl_stat>
<cmpd_stat> ::= "{ " <stat_list> " }"
<if_stat> ::= "if ( " <exp> " ) " <stat> | "if ( " <exp> " ) " <stat> " else " <stat>
<iter_stat> ::= "while ( " <exp> " ) " <stat>
<assgn_stat> ::= <id> " = " <exp> ";"
<decl_stat> ::= "int " <id> ";" | "int " <id> " = " <exp> ";"
<exp> ::= <id> | <num> | <exp> " + " <exp> | <exp> " < " <exp>
<id> ::= [a-zA-Z_][a-zA-Z0-9_]*
<num> ::= [0-9]+

Approach: Recursive Generation

Since BNF grammars are inherently recursive, the best way to generate code is to write a set of recursive functions—each function corresponds to a non-terminal symbol in the grammar, and randomly picks one of its production rules to expand.

Here's a complete C++ implementation that does this:

#include <iostream>
#include <random>
#include <string>
#include <vector>

// Global random number generator (initialized once for consistency)
std::mt19937 rng(std::random_device{}());

// Generate a valid C++ identifier (starts with letter/underscore, followed by alnums/underscores)
std::string generate_id() {
    std::vector<char> chars;
    // Pick first character: letter (upper/lower) or underscore
    std::uniform_int_distribution<int> first_char_dist(0, 52);
    int first = first_char_dist(rng);
    if (first < 26) chars.push_back('a' + first);
    else if (first < 52) chars.push_back('A' + (first - 26));
    else chars.push_back('_');

    // Add 0-3 extra characters to keep names short but varied
    std::uniform_int_distribution<int> extra_len_dist(0, 3);
    int extra_chars = extra_len_dist(rng);
    std::uniform_int_distribution<int> rest_char_dist(0, 62);
    for (int i = 0; i < extra_chars; ++i) {
        int c = rest_char_dist(rng);
        if (c < 26) chars.push_back('a' + c);
        else if (c < 52) chars.push_back('A' + (c - 26));
        else if (c < 62) chars.push_back('0' + (c - 52));
        else chars.push_back('_');
    }
    return std::string(chars.begin(), chars.end());
}

// Generate a random integer between 0 and 999
std::string generate_num() {
    std::uniform_int_distribution<int> num_dist(0, 999);
    return std::to_string(num_dist(rng));
}

// Generate an expression based on the BNF
std::string generate_exp() {
    std::uniform_int_distribution<int> exp_type_dist(0, 3);
    switch (exp_type_dist(rng)) {
        case 0: return generate_id();
        case 1: return generate_num();
        case 2: return generate_exp() + " + " + generate_exp();
        case 3: return generate_exp() + " < " + generate_exp();
        default: return generate_num(); // Fallback for safety
    }
}

// Generate a declaration statement
std::string generate_decl_stat() {
    std::uniform_int_distribution<int> decl_type_dist(0, 1);
    if (decl_type_dist(rng)) {
        return "int " + generate_id() + ";";
    } else {
        return "int " + generate_id() + " = " + generate_exp() + ";";
    }
}

// Generate an assignment statement
std::string generate_assgn_stat() {
    return generate_id() + " = " + generate_exp() + ";";
}

// Generate a while loop statement
std::string generate_iter_stat() {
    return "while ( " + generate_exp() + " ) " + generate_stat();
}

// Generate an if statement (with or without else)
std::string generate_if_stat() {
    std::uniform_int_distribution<int> has_else_dist(0, 1);
    std::string if_block = "if ( " + generate_exp() + " ) " + generate_stat();
    if (has_else_dist(rng)) {
        return if_block + " else " + generate_stat();
    } else {
        return if_block;
    }
}

// Generate a compound statement (code block with braces)
std::string generate_cmpd_stat() {
    return "{ " + generate_stat_list() + " }";
}

// Generate a single statement by randomly picking one of the 5 types
std::string generate_stat() {
    std::uniform_int_distribution<int> stat_type_dist(0, 4);
    switch (stat_type_dist(rng)) {
        case 0: return generate_cmpd_stat();
        case 1: return generate_if_stat();
        case 2: return generate_iter_stat();
        case 3: return generate_assgn_stat();
        case 4: return generate_decl_stat();
        default: return generate_decl_stat(); // Fallback
    }
}

// Generate a list of statements (recursively add more 50% of the time)
std::string generate_stat_list() {
    std::uniform_int_distribution<int> add_more_dist(0, 1);
    std::string current_stat = generate_stat();
    if (add_more_dist(rng)) {
        return current_stat + " " + generate_stat_list();
    } else {
        return current_stat;
    }
}

// Generate the full main program
std::string generate_prog() {
    return "int main() { " + generate_stat_list() + " return 0; }";
}

int main() {
    // Output 3 example random programs
    for (int i = 0; i < 3; ++i) {
        std::cout << "// Random Program " << i+1 << "\n";
        std::cout << generate_prog() << "\n\n";
    }
    return 0;
}

Key Notes

  • Recursive Mirroring: Each non-terminal in the BNF has a dedicated function that expands it by randomly selecting a production rule. This keeps the code aligned with your grammar structure.
  • Syntax Validity: All generated code follows basic C++ syntax rules—valid identifiers, proper semicolons, braces, and expression formatting.
  • Extensibility: You can easily add more features (like for loops, logical expressions, or function calls) by extending the relevant functions and updating the BNF.
  • Controlled Randomness: The random number generator uses std::mt19937 for better quality than rand(), and distributions are tuned to keep generated code readable (not too long or complex).

Example output might look like this:

// Random Program 1
int main() { while ( foo < 456 ) { int bar = x + y; } if ( 789 < z ) int q; else { a = b + 123; return 0; } }

内容的提问来源于stack exchange,提问作者kahn nugent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:37:05