• C预编译实现


    [废话]
        其实写C语言的解释器也是出于偶然的原因,本来只是想给自己的编辑器添加脚本解析的功能,或者简单的宏调用的功能。结果就想实现简单的C语言的脚本解析,后来干脆就想支持C的全部语法。至今还未完成...前几天实现了C的预编译的部分功能,主要是#define预编译宏。

        可以下载使用,呵呵:)

    [预编译]
    1. C的预编译主要是由代码中的预编译行实现,以#开始的行是预处理命令行,#前后可出现空白符,一行中可以只有#, 称为空白行。命令行后面可以有注释,可以\换行
    2. C的预编译命令有很多,包括:
       #define
       #ifdef
       #ifndef
       #if
       #elif
       define
       #endif
       #
       ##
       等等...
       现在我仅仅是实现了#define, 包括函数形式的宏调用。

    3. #define 宏的特点:
       a.  定义式宏,#define后面不是紧跟着(
           #define :
              "#define" name (sequence-of-tokens)?
              
       b.   函数式好宏,#define后紧跟(
            参数不能重名,宏体重可以不用提及所有的参数
            调用  1) ( 前可以有空格
                  2) 参数以 ","来分隔参数列表,但是:macro( fun1(a,b), fun2() );
                  中的fun1的参数列表不影响参数的解析!!
                     3) 宏中不会对自己的宏名做进一步扩展: marco( marco(a), b );
                  这样子,宏名可以以函数名重复。
            #define :
              "#define" name"(" (identifier-list)? ")"

    [实现方法]
    1.  创建一个栈,用于记录所有的预编译行,暂时仅仅记录#define行。
    2.  从头扫描脚本文件,查找符合的预编译行,将其入栈,并作处理。例如:
        脚本: #define  MARCO(a,b) ((a)+(b))
        那么,查找到该行时,必须按照下面的步骤处理:
        1) 得到#define 后面的宏名字 MARCO
        2) 判断MARCO后面是否紧跟着 ( 左括号。如果紧跟着,说明是函数式的宏调用,必须做进一步的解析,否则只要将后面的字符序列保存到栈中即可。
        3) 函数式宏的解析问题。 必须找到调用的参树,即上述例子中的a、b,并将其也保存到栈中。然后再将后面的序列((a)+(b))也保存下来。
    3.  宏扩展问题,当扫描文件是,如果得到的字符是一个标识名,那么我们必须判断它是否被定义成宏。如果是,我们必须对它进行宏扩展。例如,我们现在扫描到一个串文本: MARCO( fun(a,b), b );
        那么我们搜索栈,知道MARCO被定义成函数式的宏,参数列表是a、b。所以继续往后解析,得到fun(a,b)和b, 替换掉((a)+(b))中的a和b,得到:((fun(a,b))+(b))。
        这时,其实事情还没结束,我们必须对((fun(a,b))+(b))做进一步的宏替换,如果fun又是被定义的一个宏,那么我们继续替换它,直至重复检查,没有可以替换的宏。
       
    [举例]
    #define  MAX  120
    #define  MARCO(a,b) ((a)+(b))

    MARCO( MAX, MARCO(a,b) );

    1. 栈的内容:
    宏名     参数个数      参数列表    字串序列
    MAX      0                        120
    MARCO    2            a b         ((a)+(b))

    2. 宏调用MARCO( MAX, MARCO(a,b) );的展开过程:
       第一步:  ((MAX)+(MARCO(a,b)));
       第二步:  ((120)+(MARCO(a,b)));
       第三步:  继续替换,发现MARCO和自己同名,不会继续替换,不然将导致死循环。而且,这样子,宏名可以以函数名重复。
      
       最终结果:((120)+(MARCO(a,b)));

  • 相关阅读:
    项目经理手记
    自动填写版权信息
    在批处理中实现等待/延迟/暂停
    使用 PowerDesigner 设计数据库
    如何让PowerDesigner支持自动生成含SQL Server 2000的表和列注释的角本
    管理人员的招聘始末谈
    PowerDesign 6简易介绍
    PowerDesigner11.0使用总结
    用表单字段加亮的方式为用户提供友好的界面
    择才有道——企业招聘方式比较
  • 原文地址:https://www.cnblogs.com/linxr/p/1992644.html
Copyright © 2020-2023  润新知