⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cminusspec.htm

📁 一个c语言的编译器的源代码
💻 HTM
字号:
<HTML>
<HEAD>
<TITLE>
CMinus编译器设计方案 最后修改:2005-01-15
</TITLE>
</HEAD>
<BODY>
<H2 ALIGN = CENTER>CMinus编译器设计方案 最后修改:2005-03-13</H2>


  这里定义了一个编程语言称作C-Minus(或简称为C-),这是一种适合编译器设计方案的语言,它比TINY语言更复杂,包括函数和数组。本质上它是C的一个子集,但省去了一些重要的部分,因此得名。
  
<H3>A.1 C-惯用的语法</H3>
1.下面是语言的关键字:<br>
   else if int return void while<br>
所有的关键字都是保留字,并且必须是小写。<br>
2.下面是专用符号:<br>
   + - * / < <= > >= == != =  ; , ( ) [ ] { } /* */<br>
3.其他标记是ID和NUM,通过下列正则表达式定义:<br>
   ID = letter letter*<br>
   NUM = digit digit*<br>
   letter = a | .. | z | A | .. | Z<br>
   digit = 0 | .. | 9<br>
小写和大写字母是有区别的。<br>
4.空白由空格、换行符和制表符组成。空白通常被忽略,除了它必须分开ID、NUM关键字。<br>
5.注释用通常的C语言符号/*...*/围起来。注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。注释不能嵌套。
<H3>A.2 C-的语法和语义</H3>
  C-的BNF语法如下:(带*表示在原来基础上修改过)<br>
  1.program -> declaration-list<br>
  2.declaration-list -> declaration-list declaration | declaration<br>
  *3.declaration -> var-declaration | func-declaration | func-definition<br>
  *4.var-declaration -> type-specifier init-declarator-list <B>;</B><br>
  *4.1 init-declarator-list -> init-declarator-list <B>,</B> init-declarator | init-declarator<br>
  *4.2 init-declarator -> <B>ID</B>  | <B>ID</B>=simple-expression | <B>ID</B> <B>[</B> <B>NUM</B> <B>]</B><br>
  5.type-specifier -> <B>int</B> | <B>void</B><br>
  *6.func-declaration -> type-specifier <B>ID</B> <B>(</B> params-type <B>);</B><br>
  *6.1 func-definition -> type-specifier <B>ID</B> <B>(</B> params <B>)</B> compound-stmt<br>
  *6.2 params-type -> param-type-list | <B>void</B><br>
  *6.3 params-type-list -> param-type-list <B>,</B> param-type | param-type<br>
  *6.4 param-type -> type-specifier | type-specifier <B>[</B> <B>]</B> | type-specifier <B>ID</B> | <br>
           type-specifier <B>ID</B> <B>[</B> <B>]</B><br>
  7.params -> param-list | <B>void</B><br>
  8.param-list -> param-list <B>,</B> param | param<br>
  9.param -> type-specifier <B>ID</B> | type-specifier <B>ID</B> <B>[</B> <B>]</B><br>
  10.compound-stmt -> <B>{</B> local-declarations statement-list <B>}</B>| empty<br>
  11.local-declarations - > local-declarations var-declaration | empty<br>
  12.statement-list - > statement->list statement | empty<br>
  13.statement - > expression-stmt | compound-stmt | selection-stmt |<br>
           iteration-stmt | return-stmt<br>
  14.expression-stmt -> expression <B>;</B> | <B>;</B> <br>
  15.selection-stmt -> <B>if</B> <B>(</B> expression <B>)</B> statement |<br>
             <B>if</B> <B>(</B> expression <B>)</B> statement <B>else</B> statement<br>
  16.iteration-stmt -> <B>while</B> <B>(</B> expression <B>)</B> statement <br>
  17.return-stmt -> <B>return</B> <B>;</B> | <B>return</B> expression <B>;</B> <br>
  18.expression -> var <B>=</B> expression | simple-expression<br>
  19.var -> <B>ID</B> | <B>ID</B> <B>[</B> expression <B>]</B><br>
  20.simple-expression -> additvie-expression relop addtive-expression | additive-expression<br>
  21.relop -> <B><=</B> | <B><</B> | <B>></B> | <B>>=</B> | <B>==</B> | <B>!=</B> <br>
  22.additive-expression -> additive-expression addop term | term<br>
  23.addop -> <B>+</B> | <B>-</B> <br>
  24.term ->term mulop factor | factor<br>
  25.mulop -> <B>*</B> | <B>/</B> <br>
  26.factor -> <B>(</B> expression <B>)</B> | var | call | <B>NUM</B> <br>
  27.call -> <B>ID</B> <B>(</B> args <B>)</B> <br>
  28.args -> arg-list | empty<br>
  29.arglist -> arglist <B>,</B> expression | expression<br>
对以上每条文法规则,给出了相关语义的简短解释。<br>
  1.program -> declaration-list<br>
  2.declaration-list -> declaration-list declaration | declaration<br>
  3.declaration -> var-declaration | fun-declaration<br>
  程序由声明的列表(或序列)组成,声明可以是函数或变量声明,顺序是任意的。至少必须有一个声明。接下来是语义限制(这些在C中不会出现)。所有的变量和函数在使用前必须声明(这避免了向后backpatching引用)。程序中最后的声明必须是一个函数声明,名字为main。注意,C-缺乏原型,因此声明和定义之间没有区别(象C一样)。<br>
  4.var-declaration -> type-specifier <B>ID</B> <B>;</B> | type-specifier <B>ID</B> <B>[</B> <B>NUM</B> <B>]</B> <B>;</B><br>
  5.type-specifier -> <B>int</B> | <B>void</B><br>
  变量声明或者声明了简单的整数类型变量,或者是基类型为整数的数组变量,索引范围从0到NUM-1。注意,在C-中仅有的基本类型是整数和空类型。在一个变量声明中,只能使用类型指示符int。void用于函数声明(参见下面)。也要注意,每个声明只能声明一个变量。<br>
  6.func-declaration -> type-specifier <B>ID</B> <B>(</B> params <B>)</B> compound-stmt<br>
  7.params -> params-list | <B>void</B><br>
  8.param-list -> param-list <B>,</B> param | param<br>
  9.param -> type-specifier <B>ID</B> | type-specifier <B>ID</B> <B>[</B> <B>]</B> <br>
  函数声明由返回类型指示符、标识符以及在圆括号内的用逗号分开的参数列表组成。后面跟着一个复合语句,是函数的代码。如果函数的返回类型是void,那么函数不返回任何值(即是一个过程)。函数的参数可以是void(即没有参数),或者一列描述函数的参数。参数后面跟着方括号是数组参数,其大小是可变的。简单的整数参数由值传递。数组参数由引用来传递(也就是指针),在调用时必须通过数组变量来匹配。注意,类型“函数”没有参数。一个函数参数的作用域等于函数声明的复合语句,函数的每次请求都有一个独立的参数集。函数可以是递归的(对于使用声明允许的范围)。<br>
  10.compound-stmt -> <B>{</B> local-declarations statement-list <B>}</B> | empty<br>
  复合语句由用花括号围起来的一组声明和语句组成。复合语句通过用给定的顺序执行语句序列来执行。局部声明的作用域等于复合语句的语句列表,并代替任何全局声明。<br>
  11.local-declarations - > local-declarations var-declaration | empty<br>
  12.statement-list - > statement->list statement | empty<br>
  注意声明和语句列表都可以是空的(非终结符empty表示空字符串,有时写作ε)。<br>
  13.statement - > expression-stmt | compound-stmt | selection-stmt |<br>
           iteration-stmt | return-stmt<br>
  14.expression-stmt -> expression <B>;</B> | <B>;</B> <br>
  表达式语句有一个可选的且后面跟着分号的表达式。这样的表达式通常求出它们一方的结果。因此,这个语句用于赋值和函数调用。<br>
  15.selection-stmt -> <B>if</B> <B>(</B> expression <B>)</B> statement |<br>
             <B>if</B> <B>(</B> expression <B>)</B> statement <B>else</B> statement<br>
  if语句有通常的语义:表达式进行计算;非0值引起第一条语句的执行;0值引起第二条语句的执行,如果它存在的话。这个规则导致了典型的悬挂else二义性,可以用一种标准的方法解决:else部分通常作为当前if的一个子结构立即分析(“最近嵌套”非二义性规则)。<br>
  16.iteration-stmt -> <B>while</B> <B>(</B> expression <B>)</B> statement <br>
  while语句是C-中唯一的重复语句。它重复执行表达式,并且如果表达式的求值为非0,则执行语句,当表达式的值为0时结束。<br<
  17.return-stmt -> <B>return</B> <B>;</B> | <B>return</B> expression <B>;</B> <br>
  返回语句可以返回一个值也可无值返回。函数没有说明为void就必须返回一个值。函数声明为void就没有返回值。return引起控制返回给调用者(如果它在main中,则程序结束)。<br>
  18.expression -> var <B>=</B> expression | simple-expression<br>
  19.var -> <B>ID</B> | <B>ID</B> <B>[</B> expression <B>]</B><br>
  表达式是一个变量引用,后面跟着赋值符号(等号)和一个表达式,或者就是一个简单的表达式。赋值有通常的存储语义:找到由var表示的变量的地址,然后由赋值符右边的子表达式进行求值,子表达式的值存储到给定的地址。这个值也作为整个表达式的值返回。var是简单的(整型)变量或数组下标变量。负的下标将引起程序停止(与C不同)。然而,不进行下标越界检查。<br>
  var表示C-比C的进一步限制。在C中赋值的目标必须是左值(l-value),左值是可以由许多操作获得的地址。在C-中唯一的左值是由var语法给定的,因此这个种类按照句法进行检查,代替象C中那样的类型检查。故在C-中指针运算是禁止的。<br>
  20.simple-expression -> additvie-expression relop addtive-expression | additive-expression<br>
  21.relop -> <B><=</B> | <B><</B> | <B>></B> | <B>>=</B> | <B>==</B> | <B>!=</B> <br>
  简单表达式由无结合的关系运算符组成(即无括号的表达式仅有一个关系运算符)。简单表达式在它不包含关系运算符时,其值是加法表达式的值,或者如果关系算式求值为true,其值为1,求值为false时值为0。<br>
  22.additive-expression -> additive-expression addop term | term<br>
  23.addop -> <B>+</B> | <B>-</B> <br>
  24.term ->term mulop factor | factor<br>
  25.mulop -> <B>*</B> | <B>/</B> <br>
  加法表达式和项表示了算术运算符结合性和优先级。符号/表示整数除;既任何余数都被截去。<br>
  26.factor -> <B>(</B> expression <B>)</B> | var | call | <B>NUM</B> <br>
  因子是围在括号内的表达式;或一个变量,求出其变量的值;或者一个函数调用,求出函数的返回值;或者一个NUM,其值由扫描器计算。数组变量必须是下标变量,除非表达式由单个ID组成,并且以数组为参数在函数调用中使用(如下所示)。<br>
  27.call -> <B>ID</B> <B>(</B> args <B>)</B> <br>
  28.args -> arg-list | empty<br>
  29.arglist -> arglist <B>,</B> expression | expression<br>
  函数调用的组成是一个ID(函数名),后面是用括号围起来的参数.参数或者为空,或者由逗号分割的表达式列表组成,表示在一次调用期间分配的参数的值.函数在调用之前必须声明,声明中参数的数目必须等于调用中参数的数目。函数声明中的数组参数必须和一个表达式匹配,这个表达式由一个标识符组成表示一个数组变量。<br>
  最后,上面的规则没有给出输入和输出语句。在C-的定义中必须包含这样的函数,因为与C不同,C-没有独立的编译和链接工具;因此,考虑两个在全局环境中预定义的函数,好向它们已经进行了声明:<br>
  int input(void) {...}<br>
  void output(int x) {...}<br>
  input函数没有参数,从标准输入设备(通常是键盘)返回一个整数值。output函数接受一个整型参数,其值和一个换行符一起打印到标准输出设备(通常是屏幕)。

<H3>A.3 预处理</H3>
  目前仅支持两种简单的预处理:inlcude和define<br>
  include语法:<行首><B>#include</B> <可选空白字符串> <B>"</B> <文件名> <B>"</B> <可选空白字符串> <行末><br>
  define语法:<行首><B>#define</B> <空白字符串> <B>ID</B> <空白字符串> <文件名> <可选空白字符串> <行末><br>
</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -