分析器生成器:如何一起使用GPLEX和GPPG?

时间:2012-05-30 00:32:38

标签: c# parsing gppg

在查看好的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;
%%

谢谢! 安德鲁

5 个答案:

答案 0 :(得分:2)

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

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

将所有内容都包含在一个包中似乎更简单。它肯定可以消除一些混乱,特别是那些可能不熟悉词法分析(标记化)和解析的人(并且可能不是100%熟悉两者之间的差异)。

无论如何,对于那些可能第一次这样做的人来说:

GPLEX http://gplex.codeplex.com - 用于标记化/扫描/词法分析(同样的事情)

GPPG http://gppg.codeplex.com/ - 将标记化程序的输出作为输入解析。例如,解析器使用语法并且可以执行简单的标记器无法完成的操作,例如检测括号组是否匹配。

答案 1 :(得分:2)

首先:在项目中包含引用“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) { }

答案 2 :(得分:0)

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

答案 3 :(得分:0)

讽刺的是,因为当我跳进C#中的解析器时,我开始使用这两个工具(大约一年前)。然后lexer有一个小bug(易于修复):

但解析器更严重:

应该修复Lexer(发布日期是2013年6月),但解析器可能仍然存在此错误(2012年5月)。

所以我写了自己的套件:-) https://sourceforge.net/projects/naivelangtools/并从那时开始使用和开发它。

您的示例将(在NLT中)翻译为:

/[Oo][Rr]/                -> OR;
/[Aa][Nn][Dd]/            -> AND;
/[Nn][Oo][Tt]/            -> NOT;
// by default text is returned as value
/[A-Za-z][A-Za-z0-9_]*/   -> ID;

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

答案 4 :(得分:0)

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

您可以在这里找到它: https://www.nuget.org/packages/YaccLexTools/

这是博客文章的链接,该博客文章解释了如何使用它: http://ecianciotta-en.abriom.com/2013/08/yacclex-tools-v02.html