Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 解析器生成器:如何同时使用GPLEX和GPPG?_C#_Parsing_Gppg_Parse_Gplex - Fatal编程技术网

C# 解析器生成器:如何同时使用GPLEX和GPPG?

C# 解析器生成器:如何同时使用GPLEX和GPPG?,c#,parsing,gppg,parse,gplex,C#,Parsing,Gppg,Parse,Gplex,在浏览了好的C#解析器生成器的帖子之后,我偶然发现了GPLEX和GPPG。我想使用GPLEX为GPPG生成令牌来解析和创建树(类似于lex/yacc关系)。然而,我似乎找不到关于这两者如何相互作用的例子。使用lex/yacc,lex返回由yacc定义的令牌,并可以将值存储在yylval中。在GPLEX/GPPG中是如何做到这一点的(他们的文档中没有这一点) 附件是我想转换为GPLEX的lex代码: %{ #include <stdio.h> #include "y.tab.h"

在浏览了好的C#解析器生成器的帖子之后,我偶然发现了GPLEX和GPPG。我想使用GPLEX为GPPG生成令牌来解析和创建树(类似于lex/yacc关系)。然而,我似乎找不到关于这两者如何相互作用的例子。使用lex/yacc,lex返回由yacc定义的令牌,并可以将值存储在yylval中。在GPLEX/GPPG中是如何做到这一点的(他们的文档中没有这一点)

附件是我想转换为GPLEX的lex代码:

%{
 #include <stdio.h>
 #include "y.tab.h"
%}
%%
[Oo][Rr]                return OR;
[Aa][Nn][Dd]            return AND;
[Nn][Oo][Tt]            return NOT;
[A-Za-z][A-Za-z0-9_]*   yylval=yytext; return ID;
%%
%{
#包括
#包括“y.tab.h”
%}
%%
[Oo][Rr]返回或返回;
[Aa][Nn][Dd]返回和返回;
[Nn][Oo][Tt]不返回;
[A-Za-z][A-Za-z0-9)]*yylval=yytext;返回ID;
%%
谢谢!
安德鲁

你考虑过使用吗?(这不是一个正确的答案,但我没有足够的声誉将此作为评论发布)

我有一个类似的问题-由于明显缺乏文档,我不知道如何使用GPLEX和GPPG的输出。我认为这个问题源于这样一个事实,即GPLEX发行版包括gppg.exe和GPLEX.exe,但只包含GPLEX的文档

如果您访问GPPG主页并下载该发行版,您将获得GPPG的文档,其中描述了输入文件的要求、如何构造语法等。哦,您还将再次获得两个二进制文件-GPPG.exe和gplex.exe

似乎将所有内容都包含在一个包中会更简单。这无疑可以消除一些困惑,特别是对于那些可能对词汇分析(标记化)和语法分析(可能还不是100%熟悉两者之间的差异)不熟悉的人来说

不管怎样,对于那些可能是第一次这样做的人:

GPLEX-用于标记化/扫描/词法分析(相同)


GPPG-将标记器的输出作为解析的输入。例如,解析器使用语法,可以做一些简单的标记器无法做的事情,比如检测括号集是否匹配

讽刺的是,当我跳进C#的解析器时,我完全是从这两个工具开始的(大约一年前)。lexer有一个很小的bug(很容易修复):

但是解析器有更严重的问题:

Lexer应该是固定的(发布日期是2013年6月),但是解析器可能仍然存在这个bug(2012年5月)

因此,我编写了自己的套件:-),并从那时起使用和开发它

您的示例(在NLT中)转换为:


整个套件与lex/yacc类似,如果可能,它不依赖于副作用(因此您将返回适当的值)。

首先:在项目中包含引用“QUT.ShiftReduceParser.dll”。它在GPLEX的下载包中提供

主程序的示例代码:

using System;
using ....;
using QUT.Gppg;
using Scanner;
using Parser;

namespace NCParser
{
class Program
{
    static void Main(string[] args)
    {
        string pathTXT = @"C:\temp\testFile.txt";
        FileStream file = new FileStream(pathTXT, FileMode.Open);
        Scanner scanner = new Scanner();
        scanner.SetSource(file, 0);
        Parser parser = new Parser(scanner);            
    }
}
}    
GPLEX的示例代码:

%using Parser;           //include the namespace of the generated Parser-class
%Namespace Scanner       //names the Namespace of the generated Scanner-class
%visibility public       //visibility of the types "Tokens","ScanBase","Scanner"
%scannertype Scanner     //names the Scannerclass to "Scanner"
%scanbasetype ScanBase   //names the Scanbaseclass to "ScanBase"
%tokentype Tokens        //names the Tokenenumeration to "Tokens"

%option codePage:65001 out:Scanner.cs /*see the documentation of GPLEX for further Options you can use */

%{ //user-specified code will be copied in the Output-file
%}

OR [Oo][Rr]
AND [Aa][Nn][Dd]
Identifier [A-Za-z][A-Za-z0-9_]*

%% //Rules Section
%{ //user-code that will be executed before getting the next token
%}

{OR}           {return (int)Tokens.kwAND;}
{AND}          {return (int)Tokens.kwAND;}
{Identifier}   {yylval = yytext; return (int)Tokens.ID;}

%% //User-code Section
GPPG输入文件的示例代码:

%using Scanner      //include the Namespace of the scanner-class
%output=Parser.cs   //names the output-file
%namespace Parser  //names the namespace of the Parser-class

%parsertype Parser      //names the Parserclass to "Parser"
%scanbasetype ScanBase  //names the ScanBaseclass to "ScanBase"
%tokentype Tokens       //names the Tokensenumeration to "Tokens"

%token kwAND "AND", kwOR "OR" //the received Tokens from GPLEX
%token ID

%% //Grammar Rules Section

program  : /* nothing */
         | Statements
         ;

Statements : EXPR "AND" EXPR
           | EXPR "OR" EXPR
           ;

EXPR : ID
     ;

%% User-code Section
// Don't forget to declare the Parser-Constructor
public Parser(Scanner scnr) : base(scnr) { }

不久前,我同样需要同时使用GPLEX和GPPG,为了使工作更轻松,我创建了一个nuget软件包,用于在Visual Studio中同时使用GPPG和GPLEX。
此软件包可以安装在基于.Net Framework的C#项目中,并向Visual Studio中的软件包管理器控制台添加一些命令let。此命令可帮助您配置C#项目,以便在构建过程中集成GPPG和GPLEX。基本上,在您的项目中,您将编辑YACC和LEX文件作为源代码,并且在项目构建期间,将生成解析器和扫描程序。此外,该命令允许将自定义解析器和扫描仪所需的文件添加到项目中

你可以在这里找到它:

下面是一个博客帖子的链接,解释了如何使用它:

您是否有任何代码可以开始?我已经好几年没有玩过它了,但我很确定你需要做些什么才能让他们一起工作。IIRC,这只是确保您在范围中有正确的名称空间(或者在同一名称空间中定义两个yacc/lex文件)和可能的令牌类名,并假设所有内容都是在另一个名称空间中生成的。GPLEX没有代码,但我在lex中有等效的语法,如果这有帮助的话?在yacc/lex中,您所要做的就是在yacc文件中定义一个令牌,并将yacc生成的头文件简单地包含在lex文件中。我不确定GPPG在定义令牌时实际创建了哪些类…@AndrewSmith:我过去经常使用它。很简单。他们有一个简单的样品。还有人看看我在IronScheme@(那里有两套lexer/parser)。@leppie:我从这里得到的只是.y和.lex文件?这太棒了!可能比我需要的复杂,但它肯定回答了我的问题。@AndrewSmith:是的。我不记得做过任何修改会影响这两个文件的语法。欢迎链接到可能的解决方案,但请让您的其他用户知道它是什么以及为什么会出现。始终引用重要链接中最相关的部分,以防无法访问目标站点或永久脱机。考虑到仅仅是一个指向外部站点的链接是一个可能的原因。如果答案不清楚,这个工具(YaccLexTools)会为您生成
.y
.lex
文件,以便它们一起工作。您只需编写扫描器和解析器规则,其余的由工具处理。在主程序中,您不需要调用
parser.Parse()
%using Scanner      //include the Namespace of the scanner-class
%output=Parser.cs   //names the output-file
%namespace Parser  //names the namespace of the Parser-class

%parsertype Parser      //names the Parserclass to "Parser"
%scanbasetype ScanBase  //names the ScanBaseclass to "ScanBase"
%tokentype Tokens       //names the Tokensenumeration to "Tokens"

%token kwAND "AND", kwOR "OR" //the received Tokens from GPLEX
%token ID

%% //Grammar Rules Section

program  : /* nothing */
         | Statements
         ;

Statements : EXPR "AND" EXPR
           | EXPR "OR" EXPR
           ;

EXPR : ID
     ;

%% User-code Section
// Don't forget to declare the Parser-Constructor
public Parser(Scanner scnr) : base(scnr) { }