例,文法G[<无符号数>],若把非终结符号<无符号数>、<余留无符号数>、<十进小数>、<小数部分>、<指数部分>、<整指数>及<余留整指数>分别用编号0,1,2,……6代表,并用1,2和6代表终态,则按上述方法所构造的状态转换图如图1所示。
对于文法G[<无符号数>]的状态图1,可按表1的形式来存放其状态矩阵。表中,第一列为各状态的编号,第二列分别列出了在每一状态下可扫视到的输入字符(其中“other”是一个集合符号,用来表示在相应状态所属的那一栏中,除其前所列字符之外的全部其它字符),第三列指出当(Si,ai)出现时应执行的语义动作(通常用若干个语句来实现,若其为空,则表示不进行任何处理),最后一栏用来指明下一状态的编号(若其为NULL或“结束”则表示无后继状态)。
表1 识别无符号数的状态矩阵
当前状态 0 扫视字符 d · other d · E other d E Other d Other d + - other d other d other 语义处理操作或接受动作 {n=0;p=0;e=1;w=d} { W=0;n=0;p=0;e=1} 识别失败 {w=w*10+d} {回送整常数ICON=w} {n++;w=w*10+d} {回送实常数FCON=w-pow(10,e-p-n)} {n++;w=w*10+d;} 识别失败 {p=p*10+d} {e=-1;} 识别失败 {p=p*10+d;} 识别失败 {p=p*10+d;} {回送实常数FCON=w*pow (10,e*p-n)} 1
图 1文法G[<无符号数>]的状态转换图
后继状态 1 3 NULL 1 2 4 结束 2 4 结束 2 NULL 6 5 5 NULL 6 NULL 6 结束 1 2 3 4 5 6
在状态矩阵(表3-1)中所嵌入的语义动作,其功能是在扫描源程序字符串的过程中,把识别出的字符串形式的无符号数,逐步转换为相应的二进制整数(ICON)或二进制实数(FCON)的内部形式,方法如下。
设无符号数有如下的一般形式
dmdm-1…d1d0·d-11d-2…d-nE±dd…d
或改写为
dmdm-1…d1d0·d-11d-2…d-n×10±dd…d-n
并引入下面的变量:
w —尾数累加器(初值为0)
p —指数累加器(初值为0)
n —十进制小数位数计数器(初值为0,当扫视到小数点后的数字时开始计数);
e —用来记录十进制指数的符号(初值为1,当遇到E后的负号时再改为-1)。
利用上述变量,可将一个无符号数写成
N=w*10e*p-n
其中
w=(…((dm*10+dm-1)*10+dm+2)*10+…)10+d-n
p=(…(d*10+d)*10+d…)*10+d
于是,语义加工可按如下的步骤进行:
1.处理整数部分 当遇到小数后的每一位数字d时,做
w=w*10+d
2.处理十进制小数部分 当遇到小数后的每一位数字d时,做
w=w*10+d n=n+1
3.处理指数部分
(1)若扫视到E之后的负号,做
e=-1
2
(2)当扫视到十进制指数中的每一位数字时,做
p=p*10+d
4.在识别程序的出口(即下一状态为终态时),按公式
ICON=w
或
FCON=w *10e*p-n
分别计算和回送无符号数的二进制整数和二进制浮点数的内部表示,然后退出识别程序。
据此,可写出识别无符号数的程序如程序3-3所示。
程序3-3 无符号数的识别程序
1 #include<stdio. h> 2 #include<ctype. h> 3 #include<math. h> 4 #define LETTER 0 5 #define DIGIT 1 6 #define POINT 2 7 #define OTHER 3 8 #define POWER 4 9 #definePLUS 5 10 #defineMINUS 6
11 #defineClassNo100 //Suppose the class of number is 100 12 #define ClassOther 200 13 #define EndState -1 14 int w, n, p, e, d;
15 int Class; //Used to indicate class of the word 16 int ICON; 17 float FCON;
18 static int CurrentState; //Used to present current state, the initial value:0 19
3