我正在尝试创建一个将常规sql语句转换为c#对象的方法,所以我决定使用Irony来解析sql语句然后我将该语句作为Action返回,其中包含语句的类型及其值取决于类型
这是我未完成的代码[因为我感到沮丧因为我不知道该怎么办]
private List<Action> ParseStatement(string statement)
{
var parser = new Parser(new SqlGrammar());
var parsed = parser.Parse(statement);
var status = parsed.Status;
while (parsed.Status == ParseTreeStatus.Parsing)
{
Task.Yield();
}
if (status == ParseTreeStatus.Error)
throw new ArgumentException("The statement cannot be parsed.");
ParseTreeNode parsedStmt = parsed.Root.ChildNodes[0];
switch (parsedStmt.Term.Name)
{
case "insertStmt":
var table = parsedStmt.ChildNodes.Find(x => x.Term.Name == "Id").ChildNodes[0].Token.ValueString;
var valuesCount =
parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
x => x.Term.Name == "exprList").ChildNodes.Count;
var values = parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
x => x.Term.Name …Run Code Online (Sandbox Code Playgroud) Irony语法的相关部分:
var VARIABLE = new RegexBasedTerminal("variable", @"(?-i)\$?\w+");
variable.Rule = VARIABLE;
tag_blk.Rule = html_tag_kw + attr_args_opt + block;
term_simple.Rule = NUMBER | STRING | variable | boolean | "null" | term_list;
term.Rule = term_simple | term_filter;
block.Rule = statement_list | statement | ";";
statement.Rule = tag_blk | directive_blk | term;
Run Code Online (Sandbox Code Playgroud)
问题是"标签"和"变量"都可以出现在同一个地方.我希望我的解析器更喜欢变量上的标记,但它总是更喜欢变量.我怎么能改变呢?
我试图改变tag_blk.Rule以PreferShiftHere() + html_tag_kw + attr_args_opt + block;和ImplyPrecedenceHere(-100) + html_tag_kw + attr_args_opt + block;,但它并不能帮助任何.解析器甚至没有抱怨含糊不清.
有谁知道R是否存在现有的ANTLR或IRONY语法?
非常感谢.
我有一个语法可以在Irony控制台中正常工作和解析,但我在AST树视图中没有得到任何东西.我跟随在这里找到的BASIC-> Javascript文章:http://www.codeproject.com/Articles/25069/JSBasic-A-BASIC-to-JavaScript-Compiler,但似乎Ast的东西都是移动/删除.我找到了Irony.Interpreter .dll,里面有一些Ast内容,但它似乎都在Expression示例实现中.
我在这里错过了什么?我想走我的树并生成源代码,我不知道从哪里开始.
我已经看到一些提到使用访问者模式,我很好,但我不知道如何实现它并以Irony喜欢的方式运行它.
我在Irony中定义了一个简单的语法,并生成了一个很好的紧凑型AST.

现在我想弄清楚如何评估它.问题是,我找不到任何关于如何做到这一点的教程.
我只定义了2个AST节点:
class TagListNode : AstNode
{
public override void Init(ParsingContext context, ParseTreeNode treeNode)
{
base.Init(context, treeNode);
AsString = "TagList";
foreach (var node in treeNode.ChildNodes)
AddChild(null, node);
}
public override void EvaluateNode(Irony.Interpreter.EvaluationContext context, AstMode mode)
{
foreach (var node in ChildNodes)
node.EvaluateNode(context, AstMode.Read);
}
}
class TagBlockNode : AstNode
{
public AstNode Content;
public override void Init(ParsingContext context,ParseTreeNode treeNode)
{
base.Init(context, treeNode);
AsString = treeNode.ChildNodes[0].FindTokenAndGetText();
Content = AddChild(null, treeNode.ChildNodes[1]);
}
public override void EvaluateNode(EvaluationContext context, AstMode mode) …Run Code Online (Sandbox Code Playgroud) 我正在尝试用Irony编写一个小解析器.不幸的是,我得到了"轮班减少冲突".语法不是我的强项,我只需要完成这一小事.这是产生错误的简化语法:
ExpressionTerm := "asd"
LogicalExpression :=
ExpressionTerm |
LogicalExpression "AND" LogicalExpression |
LogicalExpression "OR" LogicalExpression
Run Code Online (Sandbox Code Playgroud)
"转移 - 减少冲突"是什么意思,我该如何解决?我认为这意味着我的语法含糊不清,但我不能充分扭曲我的逻辑,看看如何.
补充:澄清 - "asd"只是一个文字字符串"asd".所以我希望这个语法解析下面的表达式:
asd
asd AND asd
asd AND asd OR asd
asd OR asd AND asd OR asd
Run Code Online (Sandbox Code Playgroud)
补充2:忘了说,语法的根是LogicalExpression.
补充3:啊,我明白了!模棱两可是因为表达式如此
asd AND asd OR asd
Run Code Online (Sandbox Code Playgroud)
可以用两种不同的方式解释:
(asd AND asd) OR asd
asd AND (asd OR asd)
Run Code Online (Sandbox Code Playgroud)
但是我该如何解决这个问题呢?好吧,我可以把AND或OR中的一个强于另一个(无论如何我都打算).但是现在我看到即使只有一个操作员也会出现错误.换句话说,这也会产生相同的错误:
LogicalExpression := "asd" | LogicalExpression "OR" LogicalExpression
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我想要这个:
asd OR asd OR asd
Run Code Online (Sandbox Code Playgroud)
要解析为:
(asd OR asd) …Run Code Online (Sandbox Code Playgroud) 我试图在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中完成的方式我认为有点奇怪...... …
我是Irony和整个语言实现shebang的新手,所以我一直在玩Irony源附带的ExpressionEvaluator示例,这似乎(几乎)适合我正在进行的项目的需求.
但是,我希望它也支持布尔值,所以我将比较运算符添加到二元运算符列表中,如下所示:
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**"
| "==" | "<=" | ">=" | "<" | ">" | "!=" | "<>"; // added comparison operators
Run Code Online (Sandbox Code Playgroud)
这是我想要实现的一个例子:
x = 1
y = 2
eval = x < 2
eval2 = y < x
bool = true
bool2 = (eval == eval2)
Run Code Online (Sandbox Code Playgroud)
由于添加了二元运算符,它成功解析了上述内容.但是,在编译和运行代码时,它在最后两行失败.
bool = true行失败并显示以下消息:错误:变量true未定义.在(5:8).如何将true和false定义为常量?bool2 = (eval == eval2) …我按照一篇非常有用的文章编写你的第一个Visual Studio语言服务的指示,为我的软件工作室的内部脚本语言编写了一个新的Visual Studio语言服务.我的语法很棒,一些简单的goto案例正在运行,还有文本着色.我已经在Irony GrammarExplorer和Visual Studio Experimental Hive中完成了我的测试,我觉得我已经准备好在visual studio中正常使用它并将其部署到其他一些程序员那里进行早期测试和反馈.
问题是我不知道如何安装语言服务.我有这个漂亮的小DLL,可以在Experimental Hive中运行,但是无论如何在我启动visual studio时都能运行它.我在互联网上看了一眼,发现在我看的每个地方都有特别的步骤.也许我只是盲目,或者比我想象的要容易得多,但如果有人能给我详细介绍如何安装我的语言服务,我真的很感激.
提前致谢!