我正在尝试通过读取字符串每个符号来识别字符串文字。 我的扫描仪骨架的示例:
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]
我的目标是解析类似pascal的字符串:“{所有内容,但”,仅“”对是允许}”。
答案 0 :(得分:4)
首先,您显然正在使用某种解析库,如果您修改了代码,则会有更好的机会,例如:像我一样,所以任何人都可以复制,粘贴,运行你的代码。
答案很简单,你的(字符串文字) - 分析区域不会解析所有输入。以下是您修改的代码,无需任何其他库即可使用:
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;
}
}
运行此程序会产生输出:
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;.,|+_)
因此它适用于您的测试,但算法不正确,请尝试运行:
//literal with "", should produce ", but it does not
test(@"""""""""");
你会错误地得到:
testing literal with 4 chars: """" Parsed 0 chars:
问题是,如果你遇到“在你的状态下你的角色,你不会检查下一个角色,如果是的话”:
while (ChCurrent != '"') //bug
当然,我为您创建了正确的版本:-) 它是(它使用你的风格,只是你的编辑版本):
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();
}
快乐编码: - )