C# 状态转换表压缩

C# 状态转换表压缩,c#,compiler-optimization,sparse-matrix,transitions,dfa,C#,Compiler Optimization,Sparse Matrix,Transitions,Dfa,我想第一次写编译器,我的参考资料是《编译器原理、技术和工具》。对于词法设计,我编写了语言标记的FA,现在我想从状态转换表中编写C代码,但它是一个40 X 30的矩阵,这个矩阵中只有50个条目!我想压缩这个稀疏矩阵!书中有一种方法说: 有一种更微妙的数据结构,允许我们将 通过压缩具有默认值的列表来加快阵列访问速度。我们 可以将此结构视为四个阵列,如图所示。 3.66.5基本数组用于确定状态s条目的基本位置,这些条目位于下一个和检查数组中。 如果出现以下情况,则使用默认数组来确定替代基准位置: 检查

我想第一次写编译器,我的参考资料是《编译器原理、技术和工具》。对于词法设计,我编写了语言标记的FA,现在我想从状态转换表中编写C代码,但它是一个40 X 30的矩阵,这个矩阵中只有50个条目!我想压缩这个稀疏矩阵!书中有一种方法说:

有一种更微妙的数据结构,允许我们将 通过压缩具有默认值的列表来加快阵列访问速度。我们 可以将此结构视为四个阵列,如图所示。 3.66.5基本数组用于确定状态s条目的基本位置,这些条目位于下一个和检查数组中。 如果出现以下情况,则使用默认数组来确定替代基准位置: 检查数组告诉我们base[s]给出的数组无效。到 计算nextStates,a,输入a上状态s的转换,我们 检查下一个并检查位置l=base[s]+a中的条目,其中 字符a被视为一个整数,大概在0到0之间 127如果检查[l]=s,则此条目有效,输入a上状态s的下一个状态为next[l]。如果选中[l]!=s、 然后我们决定 另一个状态t=默认值[s],并重复该过程,就好像t是 当前状态。更正式地说,函数nextstate定义为 如下:

int nextState(s, a) {
if ( check[base[s] + a] = s ) return next[base[s] + a];
else return nextState(default[s], a);
}

我不明白这四个数组是由什么组成的?谁能给我解释一下吗?你有没有另一个简单的算法来优化我的稀疏压缩代码?我知道CSR压缩,但我不知道如何使用它们来编写我的C代码中的nextStates,a!你知道吗?

假设有六个输入符号:字母a、b、c、d、e和EOF。假设我们希望我们的语言包含七个字符串:ace add bad bed bee cab dad,每个字符串必须以EOF结尾

存储DFA转换表的最简单方法是将其作为二维数组simpleNext。一个轴是状态编号,另一个轴是输入符号编号。当FA处于状态s并看到符号a时,它将移动到状态simpleNext[s][a]

下面是一个识别示例字符串的DFA的simpleNext转换表:

st#   a  b  c  d  e EOF
  0   0  0  0  0  0  0
  1   2  3  4  5  0  0
  2   0  0 16 17  0  0
  3  11  0  0  0 12  0
  4   9  0  0  0  0  0
  5   6  0  0  0  0  0
  6   0  0  0  7  0  0
  7   0  0  0  0  0  8
  8   0  0  0  0  0  0
  9   0 10  0  0  0  0
 10   0  0  0  0  0  8
 11   0  0  0 15  0  0
 12   0  0  0 13 14  0
 13   0  0  0  0  0  8
 14   0  0  0  0  0  8
 15   0  0  0  0  0  8
 16   0  0  0  0 19  0
 17   0  0  0 18  0  0
 18   0  0  0  0  0  8
 19   0  0  0  0  0  8
状态0是错误状态。如果FA到达这里,它会在没有从该状态转换的状态下读取一些符号。状态8唯一其他全零行是唯一接受状态


这里的问题是simpleNext是size | S |×|那么为什么我们需要一个“默认”数组呢?它有什么帮助?我们如何构造它?请看simpleNext表,这是我答案中的第一个表。看看有多少行彼此相似?例如,第5行与第0行几乎完全相同,只是第0列有所不同。默认数组利用了这种相似性。在压缩过程中到达第5行时,只存储第5行的条目,这些条目与第0行的相应条目不同。然后将第5行的默认条目设置为0。解析时,匹配器通过查找默认值知道,如果找不到第5行所需的条目,则使用第0行的条目。更好的是,第10行与第7行相同。因此,压缩程序不必存储任何特定于第10行的条目。它只是将7存储在第10行的默认表中,当匹配器需要第10行的条目时,它将始终使用第7行的条目。这是一个非常有用的解释,谢谢@robmayoff。我不确定我是否理解第3.9.8节最后一段的要点,该段说,虽然我们可能无法选择基准值,以便没有未使用的下一个检查条目,但经验表明,将基准值依次分配给状态并分配每个基准的简单策略值最小的整数,以便状态s的特殊项以前不被占用,占用的空间比最小值略大。这是否意味着,如果状态1和状态2相似,状态1有条目5、6、7,状态2有条目5、8、7,则通过偏移8计算2的基值?。