0

次のような SCPI 文字列を解析しています。

HEADER:HEADER:HEADER:CMD NUMBER MULTIPLIER UNIT;

トークン NUMBER、MULTIPLIER、および UNIT の間のスペースは、必ずしも存在するとは限りません。また、固定長のトークンでもありません。NUMBER の終わりまで (L から R まで) 解析できました。ただし、MULTIPLIER トークンと UNIT トークンはそれぞれオプションであり、同じ文字を使用できます。

たとえば、サフィックスは 'P' です (P はピコ [マルチ] またはポイズ [単位] を意味します)。

または 'MA' (メガ [マルチ] またはミリアンプ [マルチユニット] の可能性があります)

そのような構文を解析した経験がある人、または実際に他の誰かが、これらを正しいトークンに解析する方法についてアイデアを持っていますか?

編集:衒学者にとって、これは構文解析よりも字句解析だと思います。

4

1 に答える 1

1

おそらくあなたの単純な例では、いくつかのネストされたifs を使用して実行する方が、より強力な方法を試すよりも簡単ですが、手動で実行したくない場合、または実際の問題が少し大きい場合は、あなたの正規表現による入力 (標準的なレクサーのもの)。

POSIX システムでは、 を使用できますregexec

if編集:(およびselect)でそれを行う方法:

あなたの入力が入っtextていて、すでに NUMBER の終わりまで読んでいると仮定します。したがって、あなたの indexiはそれを示しています!

// helper function: find next non-whitespace character
char get_prev(char *text, int *end, int i)
{
    for (; *end > i; --*end)
        if (text[*end] != ' ' && text[*end] != '\t'
            && text[*end] != '\n' && text[*end] != '\r')
        // or `if (text[*end] > ' ')` if ASCII
            break;
    return text[(*end)--];
}

... your function...
    // read up to i
    int end = strlen(text);
    int power_of_10 = 0;  // for MULT
    enum unit unit = UNKNOWN; // for UNIT
    switch (get_prev(text, &end, i))
    {
        case 'P':
            unit = POISE;
            break;
        case 'A':
            unit = AMP;
            break;
        ...
        default: // unforeseen character
        case '\0':
            // neither UNIT nor MULT exist
            break;
    }
    if (unit != UNKNOWN)
        switch (get_prev(text, &end, i))
        {
            case 'M':
                power_of_ten = -3;  // milli
                break;
            case 'A':
                switch (get_prev(text, &end, i))
                {
                    case 'M':
                        power_of_ten = 6;  // mega
                        break;
                    ...
                }
                break;
            ...
            default: // unforeseen character
            case '\0':
                // MULT doesn't exist
                break;
        }

この場合、UNIT が必須であると仮定したことに注意してください。MULT と UNIT の両方がオプションの場合、10MA でメガとミリアンペアをどのように区別できるかわかりません。ただし、最初の にさらにケースを追加して、 のswitch値に対応し、そこにMULT変更するpower_of_10ことができます。たとえば、最初に が表示された場合、switchは存在せず、 3kであることがわかります。UNITpower_of_10

于 2012-07-23T16:15:25.733 に答える