我试图在Irony中定义PHP样式的变量,如下所示:
variable.Rule = "$" + identifier;
Run Code Online (Sandbox Code Playgroud)
效果很好,除了你被允许在$和之间放置空格identifier.我想防止这种情况.怎么样?
我是否必须创建一个新的定制终端?如果是这样,我还能利用IdentifierTerminal魔法吗?
在IdentifierTerminal我看来,实际上有一个"NameIncludesPrefix"的标志,但它只在一个地方使用.看起来前缀存储在这个CompoundTokenDetails对象中...我不知道如何使用.编辑:没关系,这是一个死胡同.这些标志用于为变量的行为添加修饰符.
这有点......
class VariableTerminal : Terminal
{
public VariableTerminal(string name) : base(name)
{
}
public override IList<string> GetFirsts()
{
return new[] { "$" };
}
public override Token TryMatch(ParsingContext context, ISourceStream source)
{
if (source.PreviewChar != '$') return null;
do
{
source.PreviewPosition++;
} while (!source.EOF() && char.IsLetter(source.PreviewChar));
var token = source.CreateToken(OutputTerminal);
return token;
}
}
Run Code Online (Sandbox Code Playgroud)
我不太确定它是什么OuputTerminal..我猜这是基于当前预览位置的某种动态属性?解析在Irony中完成的方式我认为有点奇怪......
无论如何,这个问题就是当我使用它时VariableTerminal,而不是我之前使用它时"$" + IdentifierTerminal",当出现语法错误时,例如在此代码中:
p cat
Run Code Online (Sandbox Code Playgroud)
标识符终端用来说
语法错误,预期:{real string $ true false ...
但变量给了我这个错误:
字符无效:'c'
我认为前一个错误更有用.我真的不明白为什么它会吐出一个不同的错误......我怎么能这样说呢?
对我来说,看起来很清楚,你想要的东西目前不受支持(在消息来源中查看).请参阅关于pascal字符(非常botoom)的讨论,它被标识为'#number',不允许空格.
与非终端一起去并不是我相信的方式.语法本质上是你可以在令牌之间有空格.所以你真正需要的是遵循项目维基上给出的建议- 页面底部的自定义终端部分,并扩展终端类以满足您的需求.
或者最简单的选择是引入可以使前缀成为必需的标志.扩展IdentifierTerminal类和重写TryMatch方法.
如果你在CompoundTerminalBase课堂上看这个方法TryMatch基本上是什么方法:
如果找到前缀,该ReadPrefix方法设置details.Prefix标志.因此,在调用之后,ReadPrefix您可能需要检查新引入的标志是否为强制性前缀,如果已设置,您可以检查该details.Prefix标志是否也已设置,否则您将发出错误.
祝好运 :)
不确定这是否有帮助:
http://irony.codeplex.com/discussions/70460
因此,分享两行:
var identifier = new IdentifierTerminal("Identifier", IdFlags.NameIncludesPrefix);
identifier.AddPrefix(Strings.AllLatinLetters, IdFlags.None); //[a-zA-Z]([a-zA-Z0-9])
Run Code Online (Sandbox Code Playgroud)
我认为您不会以完全相同的方式使用它们,但可能会类似。