《自己手动写一个编译器、连接器》一(2)

文法的分类概括,文法的分类大概有4类,关系就非常类似于之前的权限级别,从0到3个级别以此包涵(0最大,然后是1,然后是2.。。)

0类:

这个类型的文法其实就是一个总括的推导:a->b
a属于V*,b属于V+

1类:

这个类型其实就是在0类的基础上加上了一个条件就是b的长度要长于a来确保递归(递归的解释后面有一个例子的)

2类:

这个类又在1类的基础上加了一个约束就是要求左边的a必须为终结符也就是说a就只能是最小的单位类似于:Aa->Bab此时左边就是A和a,其中A不是终结符,所以不符合,只有为:a->Bab才是第二类。

3类:

这个类其实就是正则文法,在2的基础上满足了:a->a|aB这个样子(或是a->a|Ba)通常我们的程序设计语言就属于这一类,由于可递归,这使得写起编译器来会比较轻松


现在来说一个什么事上下文有关和无关,上下文有关的意思就是其中任何产生规则的左手端和右手端都可以被终结符和非终结符的上下文所围绕的形式文法,无关呢就是可以通过下文 V∈N ,w∈(N∪Σ)* 。上下文无关文法取名为”上下文无关”的原因就是因为字符 V 总可以被字串 w 自由替换,而无需考虑字符 V 出现的上下文。


现在来说说递归的大概的看法:
<有符号整数>::=<无符号整数>|<正负号><无符号整数>
<无符号整数>::=<数字>|<无符号数><数字>
<数字>::=0|1|2|3|4|5|6|7|8|9
<正负号>::=+|-
通过这个例子我们就可以看出上下文无关和递归的含义了。
(这些符号的意思下面要说)


在一开始的BNF中(巴科斯范式)有以下三个元符号:
::=(->;:=)定义为
括号内的两个形式是等价可替换的。
|或者
<>用于括起非终结符
把这三个定义带入上面的例子我们就可以轻松的解读出有符号整数的具体含义是什么了。
但是由于BNF的缺陷:对于重复和可选的无法直接表达,比如上面的无符号数的定义,我们的无符号整数可以是很多个数字组合出来的一个大数,此时<无符号数><数字>的定义形式就让人觉得有点诧异(一个自我递归的表达表示无数多个)
那么就出现了一个EBNF(BNF的扩展版)这个扩展板就很厉害了,先看上面的改良的例子:
<有符号整数>::=[<正负号>]<无符号整数>
<无符号整数>::=<数字>{<数字>}
<数字>::=”0”|”1”|”2”|”3”|”4”|”5”|”6”|”7”|”8”|”9”
<正负号>::=”+”|”-”
然后我们来看看这些符号的定义:
{}包含0次的任意多次重复
[]0次或1次
()看做一项
.一条生成规则的结束
“”终结符
此时就很清晰的表示出来了有符号整数的定义了。

如果您需要在C++代码中添加UI界面来输入行数和列数,并计算不同路径问题,可以考虑使用以下方法: 1. 选择一个UI库或工具,例如Qt、wxWidgets等,来设计UI界面。您可以使用UI设计来设计界面,并添加输入框和按钮等控件。 2. 将UI界面与C++代码进行连接,使用信号和槽机制来实现用户输入和计算结果的交互。您可以在按钮的槽函数中读取输入框的值,并将其传递给C++代码进行计算,然后在界面上显示计算结果。 3. 在C++代码中实现不同路径问题的计算。您可以使用动态分配的二维数组来保存状态,使用状态转移方程`dp[i][j] = dp[i-1][j] + dp[i][j-1]`,计算出每个位置的不同路径数。最后,返回右下角的值,即为从左上角到右下角的不同路径数。 下面是一个使用Qt库设计UI界面,并计算不同路径问题的C++代码示例: ```cpp #include <QApplication> #include <QWidget> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QVBoxLayout> #include <vector> using namespace std; class UniquePathsWindow : public QWidget { public: UniquePathsWindow(QWidget *parent = 0); private slots: void calculate(); // 计算槽函数 private: QLabel *m_label1; QLabel *m_label2; QLineEdit *m_lineEdit1; QLineEdit *m_lineEdit2; QPushButton *m_button; QLabel *m_resultLabel; }; UniquePathsWindow::UniquePathsWindow(QWidget *parent) : QWidget(parent) { m_label1 = new QLabel("行数:"); m_label2 = new QLabel("列数:"); m_lineEdit1 = new QLineEdit; m_lineEdit2 = new QLineEdit; m_button = new QPushButton("计算"); m_resultLabel = new QLabel; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(m_label1); layout->addWidget(m_lineEdit1); layout->addWidget(m_label2); layout->addWidget(m_lineEdit2); layout->addWidget(m_button); layout->addWidget(m_resultLabel); setLayout(layout); connect(m_button, SIGNAL(clicked()), this, SLOT(calculate())); // 连接信号和槽函数 } void UniquePathsWindow::calculate() { int m = m_lineEdit1->text().toInt(); // 读取输入框的值 int n = m_lineEdit2->text().toInt(); vector<vector<int>> dp(m, vector<int>(n, 1)); // 初始化 for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { dp[i][j] = dp[i-1][j] + dp[i][j-1]; // 状态转移方程 } } m_resultLabel->setText("从左上角到右下角的不同路径数为:" + QString::number(dp[m-1][n-1])); // 显示计算结果 } int main(int argc, char *argv[]) { QApplication app(argc, argv); UniquePathsWindow window; window.setWindowTitle("不同路径问题"); window.show(); return app.exec(); } ``` 上述代码使用Qt库来设计UI界面,包括输入框、按钮和结果显示标签等控件。在`calculate`槽函数中,读取输入框的值,并使用动态分配的二维数组来保存状态,计算出不同路径数。最后,在结果显示标签中显示计算结果。 在`main`函数中,创建`UniquePathsWindow`窗口实例,并显示窗口。您可以根据需要修改UI界面的样式和布局,以及计算的算法和UI交互方式。 这是一种使用Qt库设计UI界面,并计算不同路径问题的C++代码实现方式,它可以方便地进行UI设计和交互,但需要您熟悉Qt库和C++编程知识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值