如何制作语法操纵器?

时间:2014-07-25 14:59:18

标签: syntax

首先,对不起这个问题,我知道我听到了一些可能有用的东西,但我记不起来了。

基本上我想为编程语言创建自己的语法。例如这段代码:

WRITE OUT 'Hello World!' 
NEW LINE

将变成这个Java代码:

System.out.print("Hello World!");
System.out.println();

我怎么能实现这个目标?有方法吗?

2 个答案:

答案 0 :(得分:2)

OLA。

有一些技术和适当的算法可以做到这一点。 搜索“编译器技术”和“解释器模式”。

初始方法可以是基本模式解释器。 假设简单的句子和每行只有一个句子,你可以逐行读取输入文件并搜索定义的模式(正则表达式)。 模式描述了您发明语言中命令的结构。 如果你得到一个匹配,那么你进行翻译。

特别是,我们使用c中的regex.h库来执行正则表达式搜索。 当然,regex也可以在java中使用。

实施例。 NEW LINE匹配模式" *NEW +LINE *"

  • *表示前面的字符出现0次或更多次。
  • +表示前面的字符出现1次或更多次。
  • 因此,此模式可以将命令" NEW LINE "与单词之间的任意空格匹配。

实施例。 WRITE OUT 'Hello World!'匹配模式"WRITE OUT '([[:print:]]*)'"

  • 或者如果您想允许空格" *WRITE +OUT +'([[:print:]]*)' *"
  • [[:print:]]表示:匹配一个可打印字符(例如'a'或'Z'或'0'或'+')
  • 因此,[[:print:]] *匹配0,1个或更多可打印字符的序列

如果输入文件的某一行与某个命令的模式匹配,那么您可以进行翻译,但在大多数情况下,您需要先检索一些信息, 恩。 WRITE OUT后的任意文本。这就是为什么你需要在[[:print:]] *周围加上括号。这将指示执行搜索的函数,您希望检索模式的特定部分。

一个很好的巧合是,我最近帮助了一个朋友,他的大学项目类似于你想要解决的问题:从c到基础的翻译。我重复使用该代码为您做一个例子。

我测试了代码并且它有效。 它可以翻译:

  • 写出“一些文字”
  • WRITE OUT变量
  • NEW LINE

    #include <stdio.h>
    #include <stdlib.h>
    #include <regex.h>
    #include <string.h>

    #define STR_SHORT 100

    #define MATCHES_SIZE 10

    /**************************************************************
        Returns the string of a match
    **************************************************************/
    char * GetExp(char *Source, char *Destination, regmatch_t Matches) {

        //Source        The string that was searched
        //Destination   Will contains the matched string
        //Matches       One element of the vector passed to regexec

        int Length = Matches.rm_eo - Matches.rm_so;

        strncpy(Destination, Source+Matches.rm_so, Length);
        Destination[Length]=0;

        return Destination;
    }

    /**************************************************************
        MAIN
    **************************************************************/
    int main(int argc, char *argv[]) {

        //Usage
        if (argc==1) {
            printf("Usage:\n");
            printf("interpreter source_file\n");
            printf("\n");
            printf("Implements a very basic interpreter\n");

            return 0;
        }

        //Open the source file
        FILE *SourceFile;
        if ( (SourceFile=fopen(argv[1], "r"))==NULL )
            return 1;

        //This variable is used to get the strings that matched the pattern
        //Matches[0] -> the whole string being searched
        //Matches[1] -> first parenthetical
        //Matches[2] -> second parenthetical
        regmatch_t Matches[MATCHES_SIZE];
        char MatchedStr[STR_SHORT];

        //Regular expression for NEW LINE
        regex_t Regex_NewLine;
        regcomp(&Regex_NewLine, " *NEW +LINE *", REG_EXTENDED);

        //Regular expression for WRITE OUT 'some text'
        regex_t Regex_WriteOutStr;
        regcomp(&Regex_WriteOutStr, " *WRITE +OUT +'([[:print:]]*)' *", REG_EXTENDED);

        //Regular expresion for WRITE OUT variable
        regex_t Regex_WriteOutVar;
        regcomp(&Regex_WriteOutVar, " *WRITE +OUT +([_[:alpha:]][[:alnum:]]*) *", REG_EXTENDED);

        //Regular expression for an empty line'
        regex_t Regex_EmptyLine;
        regcomp(&Regex_EmptyLine, "^([[:space:]]+)$", REG_EXTENDED);

        //Now we read the file line by line
        char Buffer[STR_SHORT];
        while( fgets(Buffer, STR_SHORT, SourceFile)!=NULL ) {

            //printf("%s", Buffer);

            //Shorcut for an empty line
            if ( regexec(&Regex_EmptyLine, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
                printf("\n");
                continue;
            }

            //NEW LINE
            if ( regexec(&Regex_NewLine, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
                printf("System.out.println();\n");
                continue;
            }

            //WRITE OUT 'some text'
            if ( regexec(&Regex_WriteOutStr, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
                printf("System.out.print(\"%s\");\n", GetExp(Buffer, MatchedStr, Matches[1]));
                continue;
            }

            //WRITE OUT variable
            //Assumes variable is a string variable
            if ( regexec(&Regex_WriteOutVar, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
                printf("System.out.print(\"%%s\", %s);\n", GetExp(Buffer, MatchedStr, Matches[1]));
                continue;
            }

            //Unknown command
            printf("Unknown command: %s", Buffer);
        }

        return 0;

}

答案 1 :(得分:1)

此问题的正确解决方案需要执行以下步骤:

  1. 解析原始语法代码并创建syntax tree 这通常使用ANTLR等工具完成。

  2. 浏览语法树并将其转换为Java代码或Java语法树。

  3. 这两个步骤都有其自身的复杂性,因此最好在实施时遇到有关您遇到的具体问题的单独问题。

    严格地说,您可以跳过第2步并在解析时直接生成Java,但除非您的语言非常简单地重命名Java概念,否则您将无法轻松完成。