【问题标题】:Flex, Bison, and C: Looking for a very basic introductionFlex、Bison 和 C:寻找一个非常基本的介绍
【发布时间】:2011-04-28 19:20:48
【问题描述】:

我正在寻找一个非常简短的 flex 和 bison 工作示例,并附带一个使用内置规则的 Makefile。我已经尝试了几个杂乱无章、无法构建或使用 C++ 的谷歌结果,这是不可接受的。良好的在线资源和简短的示例代码表示赞赏。


附加

     # Makefile example -- scanner and parser.
     # Creates "myprogram" from "scan.l", "parse.y", and "myprogram.c"
     #
     LEX     = flex
     YACC    = bison -y
     YFLAGS  = -d
     objects = scan.o parse.o myprogram.o

     myprogram: $(objects)
     scan.o: scan.l parse.c
     parse.o: parse.y
     myprogram.o: myprogram.c

我想要一个看起来大致像这样的 Makefile,附带的源文件可以做一些任意简单的事情。

【问题讨论】:

    标签: c parsing bison


    【解决方案1】:

    flex 项目本身带有一组不错的示例,包括 make 文件和 bison 文件。

    https://github.com/westes/flex/releases

    对于该主题的精彩介绍,我建议使用 lex 和 yacc 第 2 版:

    http://oreilly.com/catalog/9781565920002

    最后,到这里快速入门:

    http://ds9a.nl/lex-yacc/cvs/lex-yacc-howto.html

    编辑:

    正如 Bart 所说,另一个来源是:http://oreilly.com/catalog/9780596155988/

    以下是我用来启动 flex 项目的骨架文件。它使用 gnu getopts 来解析命令行选项并获取文件名。我对便携性或易用性不做任何声明! :)

    /*
     * This file is part of flex.
     * 
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     * 
     * Neither the name of the University nor the names of its contributors
     * may be used to endorse or promote products derived from this software
     * without specific prior written permission.
     * 
     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE.
     */
    
        /************************************************** 
            start of definitions section
    
        ***************************************************/
    
    %{
    /* A template scanner file to build "scanner.c". */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <getopt.h>
    /*#include "parser.h" */
    
    //put your variables here
    char FileName[256];
    FILE *outfile;
    char **myOut;
    char inputName[256];
    
    
    
    
    // flags for command line options
    static int specificFile_flag = 0;
    static int output_flag = 0;
    static int help_flag = 0;
    
    %}
    
    
    %option 8bit outfile="scanner.c"
    %option nounput nomain noyywrap 
    %option warn
    
    %x header
    %x fileType
    %x final
    
    %%
        /************************************************ 
            start of rules section
    
        *************************************************/
    
    
        /* these flex patterns will eat all input */ 
    . { }
    \n { }
    
    
    %%
        /**************************************************** 
            start of code section
    
    
        *****************************************************/
    
    int main(int argc, char **argv);
    
    int main (argc,argv)
    int argc;
    char **argv;
    {
        /****************************************************
            The main method drives the program. It gets the filename from the
            command line, and opens the initial files to write to. Then it calls the lexer.
            After the lexer returns, the main method finishes out the report file,
            closes all of the open files, and prints out to the command line to let the
            user know it is finished.
        ****************************************************/
    
        int c;
    
        // the gnu getopt library is used to parse the command line for flags
        // afterwards, the final option is assumed to be the input file
    
        while (1) {
            static struct option long_options[] = {
                /* These options set a flag. */
                {"specific-file", no_argument,       &specificFile_flag, 1},
                {"help",   no_argument,     &help_flag, 1},
                /* These options don't set a flag. We distinguish them by their indices. */
    
                {"debug", no_argument,       0, 'd'},
                {"specificFile", no_argument,       0, 's'},
                {"useStdOut", no_argument,       0, 'o'},
                {0, 0, 0, 0}
            };
               /* getopt_long stores the option index here. */
            int option_index = 0;
            c = getopt_long (argc, argv, "dso",
                long_options, &option_index);
    
            /* Detect the end of the options. */
            if (c == -1)
                break;
    
            switch (c) {
                case 0:
                   /* If this option set a flag, do nothing else now. */
                   if (long_options[option_index].flag != 0)
                     break;
                   printf ("option %s", long_options[option_index].name);
                   if (optarg)
                     printf (" with arg %s", optarg);
                   printf ("\n");
                   break;
    
                case 'd':
                    break;
    
                case 's':
                   specificFile_flag = 1;
                   break;
    
                case 'o':
                   output_flag = 1;
                   break;
    
    
                case '?':
                   /* getopt_long already printed an error message. */
                   break;
    
                default:
                   abort ();
                }
        }
    
        if (help_flag == 1) {
            printf("proper syntax is: addressGrabber.exe [OPTIONS]... INFILE OUTFILE\n");
            printf("grabs address from prn files\n\n");
            printf("Option list: \n");
            printf("-s    --specific-file   changes INFILE from a prn list to a specific prn\n");
            printf("-d              turns on debug information\n");
            printf("-o                      sets output to stdout\n");
            printf("--help                  print help to screen\n");
            printf("\n");
            printf("list example: addressGrabber.exe list.csv\n");
            printf("prn example: addressGrabber.exe -s 01110500.prn\n\n");
            printf("If infile is left out, then stdin is used for input.\n");
            printf("If outfile is a filename, then that file is used.\n");
            printf("If there is no outfile, then infile-EDIT.tab is used.\n");
            printf("There cannot be an outfile without an infile.\n");
            return 0;
        }
    
        //get the filename off the command line and redirect it to input
        //if there is no filename or it is a - then use stdin
    
    
        if (optind < argc) {
            FILE *file;
    
            file = fopen(argv[optind], "rb");
            if (!file) {
                fprintf(stderr, "Flex could not open %s\n",argv[optind]);
                exit(1);
            }
            yyin = file;
            strcpy(inputName, argv[optind]);
        }
        else {
            printf("no input file set, using stdin. Press ctrl-c to quit");
            yyin = stdin;
            strcpy(inputName, "\b\b\b\b\bagainst stdin");
        }
    
        //increment current place in argument list
        optind++;
    
    
        /********************************************
            if no input name, then output set to stdout
            if no output name then copy input name and add -EDIT.csv
            if input name is '-' then output set to stdout
            otherwise use output name
    
        *********************************************/
        if (optind > argc) {
            yyout = stdout;
        }   
        else if (output_flag == 1) {
            yyout = stdout;
        }
        else if (optind < argc){
            outfile = fopen(argv[optind], "wb");
            if (!outfile) {
                    fprintf(stderr, "Flex could not open %s\n",FileName);
                    exit(1);
                }
            yyout = outfile;
        }
        else {
            strncpy(FileName, argv[optind-1], strlen(argv[optind-1])-4);
            FileName[strlen(argv[optind-1])-4] = '\0';
            strcat(FileName, "-EDIT.tab");
            outfile = fopen(FileName, "wb");
            if (!outfile) {
                    fprintf(stderr, "Flex could not open %s\n",FileName);
                    exit(1);
                }
            yyout = outfile;
        }
    
    
        yylex();
        if (output_flag == 0) {
            fclose(yyout);
        }
        printf("Flex program finished running file %s\n", inputName);
        return 0;
    }
    

    最后,由于人们一直在检查这个,我在 github 上还有一个带有 makefile 的 example lexer and parser

    【讨论】:

    • @Bart Kiers 我已经添加了你的链接和我的骨架 flex 文件的源代码。
    【解决方案2】:

    您可以先查看维基百科bison page。 它有一个用野牛编写的可重入解析器的完整示例代码。它使用 flex 作为词法分析器,它还有一个示例代码说明如何使用它。

    如果您有任何更正,我提前感谢您:)

    稍后:维基百科上的代码已经在 linux (gcc) 和 windows (visual studio) 上进行了测试,并且应该也可以与其他编译器一起使用。

    【讨论】:

    • 这是一个不错的例子,尽管它缺少 Makefile。本质上,我正在寻找一个 Hello World 类型的示例。我对其他东西的 make 很熟悉,但没有成功为 flex/bison 编写简洁的 Makefile。
    • 对不起,我没有在 wiki 页面中提供,但正如您在文件的第一部分中看到的,您有用于获取所需文件的命令,以便使用 c 进行编译编译器。您需要做的就是在 flex 文件和 bison 文件上运行这些命令
    • 如果您知道如何为 flex 文件的 C 文件编写 makefile,则您有以下内容(在这种特殊情况下): Parser.c: Parser.y bison --defines= Parser.h Parser.y Lexer.c: Lexer.l flex --outfile=Lexer.c --header-file=Lexer.h Lexer.l
    【解决方案3】:

    GNU Manual 呢?

    【讨论】:

      【解决方案4】:

      Bison documentation 是一个非常好的计算器示例。我用它从野牛开始。 C++ 示例使用 flex 扫描器。用C语言很容易。

      【讨论】:

        【解决方案5】:

        Compilers: Principles, Techniques, and Tools、Alfred V. Aho、Ravi Sethi、Jeffrey D. Ullman

        【讨论】:

        • 第二版有 15 页关于 yacc/lex 工具链(快速浏览)。您只回答本书的链接,那么这与问题有什么关系?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-27
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 2012-01-12
        • 1970-01-01
        相关资源
        最近更新 更多