引用部分与本问题无关
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之类的