Frage

Ich versuche, Stringliteral zu erkennen, indem Zeichenfolge Lesen pro Symbol . Beispiel meines Scanner Skelett :

public sealed class Scanner
{        
    // some class inner implementations        
    /// <summary>
    /// 
    /// </summary>
    /// <param name="Line"></param>
    /// <param name="LineNumber"></param>
    public void Run(String Line, Int32 LineNumber)
    {
        var ChPosition = default(Int32);
        var ChCurrent  = default(Char);
        var Value      = new StringBuilder();

        while (default(Char) != Line.ElementAtOrDefault<Char>(ChPosition))
        {
            ChCurrent = Line.ElementAtOrDefault<Char>(ChPosition);

            #region [Whitespace]
            if (Char.IsWhiteSpace(ChCurrent))
            {
                ChPosition++;
            }
            #endregion
            else
            {
                switch (ChCurrent)
                {                        
                    #region [String Literal (")]
                    case '"':
                        {
                            // skipping " sign, include only string inner value
                            ChCurrent = Line.ElementAtOrDefault<Char>(++ChPosition);

                            // ...? Problematic place!!!

                            this.Tokens.Enqueue(new SharedEntities.Token
                            {
                                Class = SharedEntities.Token.TokenClass.StringLiteral,
                                Value = Value.ToString()
                            }
                            );
                            Value.Clear();
                            ChPosition++;
                            break;
                        }
                    #endregion                        
                        {
                            throw new ScanningException(
                            "<syntax_error#" + ChCurrent.ToString() + ">\n"
                            + "Unsupported character appeared at: {ln: "
                            + LineNumber.ToString()
                            + "; pos: "
                            + (ChPosition + 1).ToString()
                            + "}"
                            );
                        }
                } // [switch(ChCurrent)]                   
            } // [if(Char.IsWhiteSpace(ChCurrent))...else]
        } // [while(default(Char) != Line.ElementAtOrDefault<Char>(ChPosition))]
    } // [public void Run(String Line, Int32 LineNumber)]
} // [public sealed class Scanner]

Mein Ziel ist pascal artige Zeichenfolge zu analysieren: "{ alles eingeschlossen und ", nur "" Paar ist erlaubt }“.

War es hilfreich?

Lösung

Zuerst Sie sind offensichtlich eine Art von Parsing-Bibliothek verwenden, würden Sie bessere Chance haben, wenn Sie Ihren Code geändert hat, beispielsweise um so etwas wie tat ich, kann, so dass jemand kopieren, einfügen, führen Sie Ihren Code.

Antwort ist einfach, Ihre (Stringliteral) Region -parsing nicht alle Eingaben analysiert. Hier wird modifiziert Code ohne zusätzliche Bibliothek verwendet werden:

public class Test
{
    static char ElementAtOrDefault(string value, int position)
    {
        return position >= value.Length ? default(char) : value[position];
    }
    static string parseStringLiteral(string value, ref int ChPosition)
    {
        StringBuilder Value = new StringBuilder();
        char ChCurrent = ElementAtOrDefault(value, ++ChPosition);
        while (ChCurrent != '"')
        {
            Value.Append(ChCurrent);
            ChCurrent = ElementAtOrDefault(value, ++ChPosition);
            if (ChCurrent == '"')
            {
                // "" sequence only acceptable
                if (ElementAtOrDefault(value, ChPosition + 1) == '"')
                {
                    Value.Append(ChCurrent);
                    // skip 2nd double quote
                    ChPosition++;
                    // move position next
                    ChCurrent = ElementAtOrDefault(value, ++ChPosition);
                }
            }
            else if (default(Char) == ChCurrent)
            {
                // message: unterminated string
                throw new Exception("ScanningException");
            }
        }
        ChPosition++;
        return Value.ToString();
    }

    public static void test(string literal)
    {
        Console.WriteLine("testing literal with " + literal.Length + 
            " chars:\n" + literal);
        try
        {
            int pos = 0;
            string res = parseStringLiteral(literal, ref pos);
            Console.WriteLine("Parsed " + res.Length + " chars:\n" + res);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: " + ex.Message);
        }
        Console.WriteLine();
    }

    public static int Main(string[] args)
    {
        test(@"""Hello Language Design""");
        test(@"""Is there any problems with the """"strings""""?""");
        test(@"""v#:';?325;.<>,|+_)""(*&^%$#@![]{}\|-_=""");
        return 0;
    }
}

Das Ausführen dieses Programms erzeugt eine Ausgabe:

testing literal with 23 chars:
"Hello Language Design"
Parsed 21 chars:
Hello Language Design

testing literal with 45 chars:
"Is there any problems with the ""strings""?"
Parsed 41 chars:
Is there any problems with the "strings"?

testing literal with 39 chars:
"v#:';?325;.,|+_)"(*&^%$#@![]{}\|-_="
Parsed 18 chars:
v#:';?325;.,|+_)

So ist es für Ihre Tests funktioniert, aber Algorithmus nicht korrekt ist, versuchen ausführen:

//literal with "", should produce ", but it does not
test(@"""""""""");

Und Sie werden falsch erhalten:

testing literal with 4 chars:
""""
Parsed 0 chars:

Das Problem ist, wenn Sie Zeichen begegnen „in Ihrem während Zustand, nicht wahr nächste Zeichen überprüfen, wenn es“ oder nicht:

while (ChCurrent != '"') //bug

Natürlich habe ich richtige Version für Sie :-) Hier wird (es verwendet Stil, gerade bearbeitete Version von Ihnen):

static string parseStringLiteral(string value, ref int ChPosition)
{
    StringBuilder Value = new StringBuilder();
    char ChCurrent = ElementAtOrDefault(value, ++ChPosition);
    bool goon = true;
    while (goon)
    {
        if (ChCurrent == '"')
        {
            // "" sequence only acceptable
            if (ElementAtOrDefault(value, ChPosition + 1) == '"')
            {
                Value.Append(ChCurrent);
                // skip 2nd double quote
                ChPosition++;
                // move position next
                ChCurrent = ElementAtOrDefault(value, ++ChPosition);
            }
            else goon = false; //break;
        }
        else if (default(Char) == ChCurrent)
        {
            // message: unterminated string
            throw new Exception("ScanningException");
        }
        else
        {
            Value.Append(ChCurrent);
            ChCurrent = ElementAtOrDefault(value, ++ChPosition);
        }
    }
    ChPosition++;
    return Value.ToString();
}

Happy Codierung: -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top