引用部分与本问题无关
Lua 的 BNF 定义本人是在 Lua 官网上找到的:The Complete Syntax of Lua
其中一些结构简单点的类型定义还好,都写出对应的正则表达式了,例如:
funcname ::= Name {`.´ Name} [`:´ Name]
namelist ::= Name {`,´ Name}
但是碰上有“循环引用”的部分,本人就懵了,到底该咋写。这问题其实在一个月以前就困扰着本人。例如:
prefixexp ::= var | functioncall | `(´ exp `)´ functioncall ::= prefixexp args | prefixexp `:´ Name args
prefixexp 里面有 functioncall, 而 functioncall 里面又有 prefixexp。
结果还是得把一大堆代码贴出来。
首先本人定义了一种格式来存储这些 BNF Token:

然后用一个方法来将包含其他 Token 定义的 Token 变为最原始的正则表达式字符串:
public class RegexBuilder
{
private static Dictionary<string, string> tokenMap = new Dictionary<string, string>();
private static Regex tokenReg = new Regex(@"\{[a-zA-Z]+?\}");
public static void Build(BNF bnfData)
{
try
{
foreach (var item in bnfData.TokenList)
{
if (RegexBuilder.tokenMap.ContainsKey(item.Name))
{
DataException.Throw<Exception>("There is already an item exists with same name: {0}", item.Name);
}
RegexBuilder.tokenMap.Add(string.Format("{{{0}}}", item.Name), item.Value);
}
foreach (var item in bnfData.TokenList)
{
RegexBuilder.UpdateToken(item);
}
bnfData.TokenList.ForEach(item => item.BuildRegex());
tokenMap.Clear();
}
catch
{
throw;
}
}
private static void UpdateToken(Token token)
{
StringBuilder newToken = new StringBuilder();
MatchCollection matches = tokenReg.Matches(token.Value);
if (matches.Count > 0)
{
int lastMatchPos = 0;
foreach (Match match in matches)
{
string regexStr = match.Groups[0].Value;
newToken.Append(token.Value.Substring(lastMatchPos, match.Groups[0].Index - lastMatchPos));
lastMatchPos = match.Groups[0].Index + match.Groups[0].Length;
if (RegexBuilder.tokenMap.ContainsKey(regexStr))
{
newToken.Append(tokenMap[regexStr]);
}
else
{
DataException.Throw<Exception>("There is no token exists with name: {0}", token);
}
}
newToken.Append(token.Value.Substring(lastMatchPos));
token.Value = newToken.ToString();
RegexBuilder.UpdateToken(token);
}
}
}
很显然碰上有“循环引用”的部分就无限递归了。
所以本人想知道这种问题该怎么解决。
不知道说清楚了没,上次提的问题很失败所以直接结贴了
解决方案
30
Lua,不会
35
直接看llex.c不就行了
都是一个个字符读进来,再根据状态进行分析的
反正顶层的元素是chunk,只要他不被嵌套就行了
至于后面的元素,原因是是按顺序来的,不管prefixexp 还是functioncall 总有先来后到
都是一个个字符读进来,再根据状态进行分析的
反正顶层的元素是chunk,只要他不被嵌套就行了
至于后面的元素,原因是是按顺序来的,不管prefixexp 还是functioncall 总有先来后到
35
也可以看c#的实现,nlua,moon之类的