已知课本P93拓广文法,要求用C语句编写LL(1)语法分析器程序,实现以下功能: (1)显示文法; (2)显示所有的SELECT运算和FOLLOW运算; (3)显示LL(1)分析表; (4)设计LL(1)分析器并验证语句。
时间: 2023-06-08 19:06:09 浏览: 214
很高兴能为您解答问题。根据您的需求,我可以提供以下答案:
1. 对于显示文法,您需要先将P93拓广文法用符号串等方式定义出来。然后再利用C语言中的变量、数组等方式将其打印出来。
2. 对于SELECT和FOLLOW运算,您需要先利用算法计算出它们的值,然后将其打印出来。具体实现可以用C语言的函数或结构体等方式完成。
3. 对于LL(1)分析表,您需要对文法进行FIRST和FOLLOW集的计算,然后利用算法计算表格中每个单元格的内容。最后将结果打印出来即可。
4. 对于设计LL(1)分析器,并验证语句,您可以设计一个C函数,实现对输入字符串的语法分析。具体实现可以参考算法设计,将文法、SELECT、FOLLOW集和LL(1)分析表作为输入参数。最后,您只需要调用该函数,并输入需要验证的字符串即可。
希望以上答案能够帮到您,如果您有任何疑问或需要进一步的帮助,请随时联系我。
相关问题
设计ll(1)语法分析程序。ll(1)预测分析程序的流程可参考课本p93页图4.11的框图进
LL(1)语法分析程序是一种自顶向下的语法分析器,它可以通过一个预测分析表来判断输入串是否符合文法规则。LL(1)语法分析程序的设计流程如下:
1. 设计文法
首先需要设计一个符合 LL(1)文法的文法,具体要求是:
- 消除左递归
- 消除直接左递归
- 消除间接左递归
- 消除公共左因子
2. 构造预测分析表
根据文法设计预测分析表,预测分析表的行表示非终结符,列表示终结符,每个表格中填写产生式的编号。
- 对于每个产生式 A -> α,找到 FIRST(α) 中的终结符号,将这些终结符号对应的表格填写为该产生式的编号。
- 如果 α 可以推导出 ε,那么对 FOLLOW(A) 中的终结符号也进行相同的填表操作。
3. 进行语法分析
读入输入串并进行语法分析,具体流程如下:
- 初始化栈,将文法开始符号放入栈顶。
- 读入输入串的第一个符号 a。
- 从栈顶取出符号 X。
- 如果 X 是终结符:
- 如果 X = a,弹出栈顶,读入下一个输入符号 a。
- 如果 X ≠ a,则报错。
- 如果 X 是非终结符:
- 查找预测分析表中 X 行 a 列的产生式编号,如果找到,则用该产生式的右部替换栈顶的 X,把右部的符号按照倒序依次压入栈中。
- 如果找不到,则报错。
- 重复步骤 3 和 4,直到栈为空或者输入串为空。
如果栈为空且输入串为空,则输入符号串符合文法规则;否则报错。
这就是 LL(1)语法分析程序的设计流程。
用小脚丫STEP FPGA开发板的数码管、三色灯、sw实现:1.Sw4来控制启停,当Sw4往下拨开始计数;2.从0开始用两个数码管计数,每隔3s加一个数;3.加到15后,三色灯循环闪烁,按照红色1秒,蓝色1秒,黄色1s这个循环闪烁持续10s;4.重复步骤2和3,直到Sw4往上拨的时候停止的Quarter代码和FPGA管脚设置
这里给出了基于Verilog的Quarter代码和基于小脚丫STEP FPGA开发板的管脚设置。请注意,由于每个开发板的管脚分配可能不同,您需要根据您的开发板手册进行适当的调整。
```
// Quarter代码
module counter(
input clk,
input reset,
input sw4,
output reg [7:0] digit1,
output reg [7:0] digit2,
output reg [2:0] led
);
reg [3:0] count;
reg [19:0] timer;
reg start;
always @(posedge clk) begin
if (reset) begin
count <= 0;
timer <= 0;
start <= 0;
digit1 <= 8'b00000000;
digit2 <= 8'b00000000;
led <= 3'b000;
end else begin
if (sw4 && !start) begin
start <= 1;
timer <= 0;
count <= 0;
digit1 <= 8'b00000000;
digit2 <= 8'b00000000;
led <= 3'b000;
end else if (start) begin
timer <= timer + 1;
if (timer == 20000000) begin
timer <= 0;
count <= count + 1;
if (count == 16) begin
count <= 0;
led <= 3'b001;
timer <= 0;
for (int i = 0; i < 10; i = i + 1) begin
#20000000 led <= 3'b100;
#20000000 led <= 3'b010;
#20000000 led <= 3'b001;
end
end else begin
if (count % 2 == 0) begin
digit1 <= 8'b01111110;
end else begin
digit1 <= 8'b00000110;
end
digit2 <= {4'b0000, count};
end
end
end else begin
digit1 <= 8'b00000000;
digit2 <= 8'b00000000;
led <= 3'b000;
end
end
end
endmodule
```
接下来是FPGA管脚的设置:
```
// FPGA管脚设置
NET "digit1<0>" LOC = "P85" | IOSTANDARD = "LVCMOS33"; // 数码管1 a
NET "digit1<1>" LOC = "P86" | IOSTANDARD = "LVCMOS33"; // 数码管1 b
NET "digit1<2>" LOC = "P87" | IOSTANDARD = "LVCMOS33"; // 数码管1 c
NET "digit1<3>" LOC = "P88" | IOSTANDARD = "LVCMOS33"; // 数码管1 d
NET "digit1<4>" LOC = "P89" | IOSTANDARD = "LVCMOS33"; // 数码管1 e
NET "digit1<5>" LOC = "P90" | IOSTANDARD = "LVCMOS33"; // 数码管1 f
NET "digit1<6>" LOC = "P91" | IOSTANDARD = "LVCMOS33"; // 数码管1 g
NET "digit1<7>" LOC = "P92" | IOSTANDARD = "LVCMOS33"; // 数码管1 dp
NET "digit2<0>" LOC = "P93" | IOSTANDARD = "LVCMOS33"; // 数码管2 a
NET "digit2<1>" LOC = "P94" | IOSTANDARD = "LVCMOS33"; // 数码管2 b
NET "digit2<2>" LOC = "P97" | IOSTANDARD = "LVCMOS33"; // 数码管2 c
NET "digit2<3>" LOC = "P98" | IOSTANDARD = "LVCMOS33"; // 数码管2 d
NET "digit2<4>" LOC = "P99" | IOSTANDARD = "LVCMOS33"; // 数码管2 e
NET "digit2<5>" LOC = "P100" | IOSTANDARD = "LVCMOS33"; // 数码管2 f
NET "digit2<6>" LOC = "P101" | IOSTANDARD = "LVCMOS33"; // 数码管2 g
NET "digit2<7>" LOC = "P102" | IOSTANDARD = "LVCMOS33"; // 数码管2 dp
NET "led<0>" LOC = "P104" | IOSTANDARD = "LVCMOS33"; // 三色灯红
NET "led<1>" LOC = "P105" | IOSTANDARD = "LVCMOS33"; // 三色灯蓝
NET "led<2>" LOC = "P106" | IOSTANDARD = "LVCMOS33"; // 三色灯黄
NET "sw4" LOC = "P109" | IOSTANDARD = "LVCMOS33"; // 按钮
NET "clk" LOC = "P89" | IOSTANDARD = "LVCMOS33"; // 时钟
NET "reset" LOC = "P109" | IOSTANDARD = "LVCMOS33"; // 复位
```
阅读全文