C 如何使用变量类型标记此输入行,以便确定保存信息的结构的大小?

C 如何使用变量类型标记此输入行,以便确定保存信息的结构的大小?,c,regex,unix,bison,flex-lexer,C,Regex,Unix,Bison,Flex Lexer,这是一个多部分的问题。首先,我的输入文件如下所示: category Shoes brand:char[50],cost:int category Shirts brand:char[20],cost:int 我的问题是: a、 )如何仅在类别名称之后在:处拆分行鞋或衬衫在这些情况下 b、 )如何编写Bison解析器,以便确定结构的变量(例如,char[30]),从而保存每行的信息 如果这些问题似乎过于本地化,我希望能得到一些资源的指导,帮助我做同样的事情。我不确定我是否正确理解了你的问题。我

这是一个多部分的问题。首先,我的输入文件如下所示:

category Shoes brand:char[50],cost:int
category Shirts brand:char[20],cost:int
我的问题是:

a、 )如何仅在类别名称之后在
处拆分行<代码>鞋或
衬衫
在这些情况下

b、 )如何编写Bison解析器,以便确定结构的变量(例如,
char[30]
),从而保存每行的信息

如果这些问题似乎过于本地化,我希望能得到一些资源的指导,帮助我做同样的事情。我不确定我是否正确理解了你的问题。我假设您希望解析输入文件中的每个条目,并将信息存储在结构中。Category和Brand将是字符串,cost将是int。您需要事先知道字符串的长度,以便可以指定一个变量来保存解析后的值(例如char[20])

<>为什么不使用C++字符串?那么你就不必申报长度了。例子。
如果必须使用C,则只需使用char*并使用malloc在堆上分配字符串。

缺少太多的详细信息。例如,“int”可以用作类别名称吗?您计划如何存储您解析的数据

不过,对于解析器来说,初始草图应该是这样的:

%token CATEGORY "category"
       EQ       "="
       COLON    ":"
       COMMA    ","
       LBRA     "["
       RBRA     "]"
       INT      "int"
       CHAR     "char"
       ID
       NATURAL
;
%%    
categories:
  category
| categories category
;

category:
  "category" ID fields
;

fields:
  field
| fields "," field
;

field:
  ID ":" type
;

type:
  "char"
| "int"
| type "[" NATURAL "]"
;
对于扫描仪,这是:

%%
"category"   return CATEGORY;
"="          return EQ;
":"          return COLON;
","          return COMMA;
"["          return LBRA;
"]"          return RBRA;
"int"        return INT;
"char"       return CHAR;
[a-zA-Z]+    return ID;
[0-9]+       return NATURAL;
[ \n\t]+     continue;
有一个合理、简单的例子,可以作为您尝试做什么的指南。编写flex/bison解析器的完整通用过程是:

  • 决定令牌是什么,编写一个正则表达式并为每个令牌选择一个标识符(正如@akim在他的flex/bison代码中所做的那样)
  • 为您试图解析的“合法”输入编写一个LALR(1)上下文无关语法@阿基姆在这件事上帮了你一把
  • 设计一个目标数据结构来保存解析器结果。这是你的帖子中缺少的关键内容。如果您只是尝试计算单个整数大小,那么您就完成了。如果需要传递更多细节以进行进一步处理,则需要某种记录/枚举/列表结构,这种结构通常称为抽象语法树或AST,尽管它通常不是真正的树
  • 实现AST(如有必要)数据结构,包括构造函数,如
    CATEGORY_节点make_CATEGORY(枚举CATEGORY_e cat)。解析器将调用这些构造函数
  • 在没有操作代码的flex scanner程序文件中实现令牌
  • 在bison解析器程序文件中实现CFG,无需操作代码
  • 构建一个测试框架和一个测试套件,测试扫描器和解析器读取合法输入并拒绝错误输入。到目前为止,该计划没有做其他事情。这就是@akim的代码所在
  • 决定必须与每个令牌关联的数据(如果有)。例如,一个无符号数的值将是它作为
    无符号int
    从扫描仪返回的大小。标识符的值将是字符串。但是括号
    [
    完全没有值。使用这些类型创建bison
    %union
    指令以接受来自扫描仪的值。将这些作为
    标记添加到相应的
    %token
    指令。请参见此处使用的
    @union
    示例,其中有两种token值类型
  • 通过在顶部添加一个
    #include“foo.tab.h”
    并添加操作代码以返回相应令牌的正确令牌值,修复
    flex
    扫描仪。此时,所有内容都应重新编译和运行,但仍然不执行任何操作。再次参考示例
  • 现在在解析器中实现数据处理。您将使用dollar
    $n
    $
    指令,向语法非终结符添加
    类型标记,以便在语法规则之间移动数据,最后调用AST结构的构造函数,在读取输入时构建结构(或者,如果仅此而已,则增加整数)。这就是LALR解析器的经验和更深入的知识非常有用的地方。
    Bison
    文档中后面的示例是本部分的另一个参考。如果遇到障碍,请带着具体问题回来
  • 再次运行测试并以您可以验证的形式打印生成的AST
  • 现在我相信有人会注意到,这种完全通用的方法对于您到目前为止提出的问题来说是过分的。这要看情况而定。您当前的输入非常简单,您可能可以更快地手工编写一个临时解析器,而不必使用flex或bison


    但是,如果您正在编写的程序可能会使用一段时间并随着时间的推移而改变,那么在一开始就准备好通用解析器的所有机制可以让生活变得更加轻松。将程序输入视为一种真正的语言而不仅仅是原始数据可以引导您创建否则永远不会出现的功能欢迎使用。

    请注意正确标记您的问题。Flex标记用于Adobe/Apache框架。Gnu Flex用于词法分析器。感谢您修复此问题。您能否提供一个示例,确切说明您的输入内容(我不确定char[20]的确切含义)。您的目标是提取类别、品牌和成本的值,然后填充结构吗?(a.)请澄清您在“:”处拆分行的意思。这是否意味着在输入文件中,类别名称和成本之间的描述可以跨多行,但类别名称后接类别名称必须在一行?