排列基本的BNF样式字符串

时间:2019-03-29 14:51:15

标签: c bnf

我想找到非常简单的类似于BNF的样式字符串的所有排列。

唯一的运算符是()[]|

因此,()表示“必须具有”,[]表示“可选”,而|表示“或”

给定一个字符串(foo | bar) [zop] [flip | flop]

它将给我以下结果:

  • foo flip
  • foo zop flip
  • foo zop翻牌
  • foo翻牌
  • 酒吧翻转
  • 栏杆翻转
  • 酒吧zop翻牌
  • 翻牌圈
  • foo zop
  • bar zop
  • foo
  • 酒吧

我可以使用任何算法来做到这一点吗?我可以编写一个简单的解析器+标记器,但是我的直觉可能是一个更简单的解决方案。我正在用ISO C编写代码。

1 个答案:

答案 0 :(得分:0)

您可以做的是在字符串解析中使用递归。因此,对于每个字符:

  1. 如果它以“ [”开头,则必须处理强制设置
  2. 如果以'('开头,则处理可选集
  3. 否则,只需跳到下一个关闭制动器')'或']'

处理强制和可选集将获取其令牌并对其进行迭代,然后重新执行上述3个步骤。同样,处理可选集有一个空迭代,不包含任何东西作为其可选项。所以:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 1024

void printPermutation(char* result[], int size) {
        for (int i = 0; i < size; ++i) {
                printf("%s ", result[i]);
        }
        printf("\n");
}

void parseDeep(char* s, char* result[], int currIdx) {
    char* mandatory[1024];
    char* optional[1024];
    char *start = 0, *end = 0;
    char* delim = "|";
    int mandatorySize = 0;
    int optionalSize = 0;

    while (*s != 0) {
            //Mandatory
            if ('(' == *s) {
                ++s;
                end = start = s;
                while (*end != ')') {
                        ++end;
                }
                char* mandatorySet = malloc(end - start + 1);
                strncpy(mandatorySet, start, end - start);
                mandatorySet[end - start] = 0;

                char* token = strtok(mandatorySet, delim);
                while (token != 0) {
                        mandatory[mandatorySize] = malloc(strlen(token) + 1);
                        strcpy(mandatory[mandatorySize++], token);
                        token = strtok(0, delim);
                }
                for (int m = 0; m < mandatorySize; ++m) {
                        result[currIdx] = mandatory[m];
                        parseDeep(end, result, currIdx + 1);
                }
                for (int i=0; i < mandatorySize; ++i) {
                    free(mandatory[i]);
                }
                free(mandatorySet);
                s = end;
                return;
            //Optional
            } else if ('[' == *s) {
                ++s;
                end = start = s;
                while (*end != ']') {
                        ++end;
                }
                char* optionalSet = malloc(end - start + 1);
                strncpy(optionalSet, start, end - start);
                optionalSet[end - start] = 0;

                char* token = strtok(optionalSet, delim);
                while (token != 0) {
                        optional[optionalSize] = malloc(strlen(token) + 1);
                        strcpy(optional[optionalSize++], token);
                        token = strtok(0, delim);
                }
                for (int m = -1; m < optionalSize; ++m) {
                        //Optional when it is not added
                        if (m == -1) {
                            continue;
                        } else {
                            result[currIdx] = optional[m];
                            parseDeep(end, result, currIdx + 1);
                        }

                }
                for (int i=0; i < optionalSize; ++i) {
                    free(optional[i]);
                }
                free(optionalSet);
                s = end;
            }
            mandatorySize = optionalSize = 0;
            ++s;
        }
    printPermutation(result, currIdx);
}

void parse(char* s) {
        char* result[MAX_SIZE];
        parseDeep(s, result, 0);
}


int main() {
    char *s = "(foo | bar) [zop] [flip | flop]";
    parse(s);
}

这不检查字符串的有效性。