SLR1 文法分析器构造错误:ComputeFirst() 和 ComputeFollow() 函数中无法从 'string' 转换为 'char' 错误修复

在构建 SLR1 文法分析器时, ComputeFirst()ComputeFollow() 函数中经常会出现“无法从 'string' 转换为 'char'”的错误。该错误通常发生在使用 string 类型来表示产生式右部的符号时,而函数需要使用 char 类型来进行操作。

为了解决这个问题,需要对代码进行以下修改:

  1. 将产生式右部的字符串拆分成单个字符:ComputeFirst()ComputeFollow() 函数中,遍历产生式右部时,需要将字符串拆分成单个字符进行操作。例如,可以使用 foreach (char c in node.Right) 循环来遍历每个字符。

  2. 使用 char 类型进行比较: 在判断字符类型(例如终结符或非终结符)时,需要使用 char 类型进行比较。例如,使用 Echar.Contains(c)Nchar.Contains(c) 来判断字符是否是终结符或非终结符。

以下是一个示例代码,展示了如何修改 ComputeFirst()ComputeFollow() 函数以解决该错误。

public class SLRNode
{
    public string Left;
    public string Right;
    public HashSet<char> First;
    public HashSet<char> Follow;
    public SLRNode(string Left, string Right)
    {
        this.Left = Left;
        this.Right = Right;
        First = new HashSet<char>();
        Follow = new HashSet<char>();
    }
}
//项目集类
public class SLRitemsets
{
    public List<int> Container
        = new List<int>(100);
    //记录项目在项目集合中的序号
    public HashSet<char> LookAhead
        = new HashSet<char>();
    //记录展望符
}

//DFA结点
public struct DFA
{
    public int from;
    public char symbol;
    public int to;
    public HashSet<char> LookAhead;
    public DFA(int from, char symbol, int to, HashSet<char> LookAhead)
    {
        this.from = from;
        this.symbol = symbol;
        this.to = to;
        this.LookAhead = LookAhead;
    }
}

//分析表 结点
public class Table
{
    public bool error;//是否为ERROR
    public char type;//结点类型
    public int id;//数值
    public Table()
    {
        this.error = true;
    }
    public Table(char type, int id)
    {
        this.type = type;
        this.id = id;
        this.error = false;
    }
}

public DFA[] dfa = new DFA[100];
public int Pindex = 0; //dfa数组指针
public Table[][] SLRAna;//分析表
public Analyze Jz;
public bool Success = false;
public List<SLRNode> SLRproNum = new List<SLRNode>(50);//产生式 列表
public List<SLRNode> SLRobjNum = new List<SLRNode>(50);//项目 列表
public List<SLRitemsets> proitemset = new List<SLRitemsets>(100);//项目集合
public List<int> Gy_obj = new List<int>(50);//归约项目序号集合
public List<int> Gy_itemset = new List<int>(50);//含有归约项目的集合的序号 的集合
public List<char> Nchar = new List<char>(50);//非终结符集合
public List<char> Echar = new List<char>(50);//终结符集合

Dictionary<char, HashSet<char>> first = new Dictionary<char, HashSet<char>>();//非终结符的First集
Dictionary<char, HashSet<char>> follow = new Dictionary<char, HashSet<char>>();//非终结符的Follow集

public string RStr = '';
public string RStr_obitemset = '';//输出返回
public string RStr_DFA = '';
public string RStr_ANA = '';

public Table[][] GET_ANA()
{
    SLRAnaly();
    RStr_ANA += '
SLR1分析表:
    ';
    int i;
    for (i = 0; i < Echar.Count; i++)
    {
        RStr_ANA += Echar[i].ToString() + '     ';
    }
    for (i = 0; i < Nchar.Count; i++)
    {
        RStr_ANA += Nchar[i].ToString() + '     ';
    }
    RStr_ANA += '
';
    for (i = 0; i < proitemset.Count; i++)
    {
        RStr_ANA += i.ToString() + '  ';
        for (int j = 0; j < Echar.Count + Nchar.Count; j++)
        {

            if (SLRAna[i][j].error)
            {
                RStr_ANA += '  ' + '    ';
            }
            else if (SLRAna[i][j].type != 'N')
            {
                RStr_ANA += SLRAna[i][j].type.ToString() + SLRAna[i][j].id.ToString() + '    ';
            }
            else
                RStr_ANA += SLRAna[i][j].id.ToString() + '    ';
        }
        RStr_ANA += '
';
    }

    return SLRAna;

}

public void SLRAnaly()
{
    //计算First集和Follow集
    ComputeFirst();
    ComputeFollow();

    //构造项目集
    CreateItemsets();

    //构造DFA
    CreateDFA();

    //构造分析表
    CreateSLRTable();
}

public void ComputeFirst()
{
    //初始化 First 集
    foreach (char c in Nchar)
    {
        first.Add(c, new HashSet<char>());
    }
    foreach (char c in Echar)
    {
        first.Add(c, new HashSet<char>() { c });
    }
    //计算 First 集
    bool flag = true;
    while (flag)
    {
        flag = false;
        foreach (SLRNode node in SLRproNum)
        {
            HashSet<char> temp = new HashSet<char>();
            bool canEpsilon = true;
            foreach (char c in node.Right)
            {
                if (Echar.Contains(c))
                {
                    temp.UnionWith(first[c]);
                    if (!first[c].Contains('ε'))
                    {
                        canEpsilon = false;
                        break;
                    }
                }
                else
                {
                    canEpsilon = false;
                    temp.UnionWith(first[c]);
                    break;
                }
            }
            if (canEpsilon)
            {
                temp.Add('ε');
            }
            if (!temp.SetEquals(first[node.Left]))
            {
                first[node.Left].UnionWith(temp);
                flag = true;
            }
        }
    }
}

public void ComputeFollow()
{
    //初始化 Follow 集
    foreach (char c in Nchar)
    {
        follow.Add(c, new HashSet<char>());
    }
    follow[SLRproNum[0].Left].Add('#');
    //计算 Follow 集
    bool flag = true;
    while (flag)
    {
        flag = false;
        foreach (SLRNode node in SLRproNum)
        {
            for (int i = 0; i < node.Right.Length; i++)
            {
                if (Nchar.Contains(node.Right[i]))
                {
                    HashSet<char> temp = new HashSet<char>();
                    bool canEpsilon = true;
                    for (int j = i + 1; j < node.Right.Length; j++)
                    {
                        if (Echar.Contains(node.Right[j]))
                        {
                            temp.UnionWith(first[node.Right[j]]);
                            if (!first[node.Right[j]].Contains('ε'))
                            {
                                canEpsilon = false;
                                break;
                            }
                        }
                        else
                        {
                            canEpsilon = false;
                            temp.UnionWith(first[node.Right[j]]);
                            break;
                        }
                    }
                    if (canEpsilon)
                    {
                        temp.UnionWith(follow[node.Left]);
                    }
                    if (!temp.SetEquals(follow[node.Right[i]]))
                    {
                        follow[node.Right[i]].UnionWith(temp);
                        flag = true;
                    }
                }
            }
            if (node.Right.EndsWith(Nchar.ToString()))
            {
                if (!follow[node.Left].SetEquals(follow[node.Right[node.Right.Length - 1]]))
                {
                    follow[node.Right[node.Right.Length - 1]].UnionWith(follow[node.Left]);
                    flag = true;
                }
            }
        }
    }
}

public void CreateItemsets()
{
    //初始化第一个项目集
    SLRitemsets itemset0 = new SLRitemsets();
    itemset0.Container.Add(0);
    itemset0.LookAhead.Add('#');
    itemset0 = Closure(itemset0);
    proitemset.Add(itemset0);
    //构造所有项目集
    bool flag = true;
    while (flag)
    {
        flag = false;
        for (int i = 0; i < proitemset.Count; i++)
        {
            for (int j = 0; j < Echar.Count + Nchar.Count; j++)
            {
                char symbol = j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count];
                HashSet<char> lookAhead = new HashSet<char>();
                foreach (int index in proitemset[i].Container)
                {
                    if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
                    {
                        if (SLRobjNum[index].Right.Length - 1 == SLRobjNum[index].Right.IndexOf('.') + 1)
                        {
                            lookAhead.UnionWith(proitemset[i].LookAhead);
                        }
                        else
                        {
                            bool canEpsilon = true;
                            for (int k = SLRobjNum[index].Right.IndexOf('.') + 2; k < SLRobjNum[index].Right.Length; k++)
                            {
                                if (Echar.Contains(SLRobjNum[index].Right[k]))
                                {
                                    lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
                                    if (!first[SLRobjNum[index].Right[k]].Contains('ε'))
                                    {
                                        canEpsilon = false;
                                        break;
                                    }
                                }
                                else
                                {
                                    canEpsilon = false;
                                    lookAhead.UnionWith(first[SLRobjNum[index].Right[k]]);
                                    break;
                                }
                            }
                            if (canEpsilon)
                            {
                                lookAhead.UnionWith(proitemset[i].LookAhead);
                            }
                        }
                    }
                }
                if (lookAhead.Count > 0)
                {
                    SLRitemsets newItemset = new SLRitemsets();
                    foreach (int index in proitemset[i].Container)
                    {
                        if (SLRobjNum[index].Right.Contains('.') && SLRobjNum[index].Right.IndexOf('.') < SLRobjNum[index].Right.Length - 1 && SLRobjNum[index].Right[SLRobjNum[index].Right.IndexOf('.') + 1] == symbol)
                        {
                            SLRNode newNode = new SLRNode(SLRobjNum[index].Left, SLRobjNum[index].Right.Insert(SLRobjNum[index].Right.IndexOf('.') + 2, '$'));
                            if (!SLRobjNum.Contains(newNode))
                            {
                                SLRobjNum.Add(newNode);
                                newItemset.Container.Add(SLRobjNum.Count - 1);
                                newItemset.LookAhead.Add(symbol);
                            }
                            else
                            {
                                int index2 = SLRobjNum.IndexOf(newNode);
                                newItemset.Container.Add(index2);
                                newItemset.LookAhead.Add(symbol);
                            }
                        }
                    }
                    newItemset = Closure(newItemset);
                    if (!proitemset.Contains(newItemset))
                    {
                        proitemset.Add(newItemset);
                        flag = true;
                    }
                    dfa[Pindex++] = new DFA(i, symbol, proitemset.IndexOf(newItemset), lookAhead);
                }
            }
        }
    }
}

public void CreateDFA()
{
    RStr_DFA += '
SLR1分析器DFA:
';
    RStr_DFA += '状态|';
    foreach (char c in Echar)
    {
        RStr_DFA += c + '|';
    }
    foreach (char c in Nchar)
    {
        RStr_DFA += c + '|';
    }
    RStr_DFA += '
';
    for (int i = 0; i < Pindex; i++)
    {
        RStr_DFA += i + '    |';
        for (int j = 0; j < Echar.Count + Nchar.Count; j++)
        {
            if (dfa[i].to == -1)
            {
                RStr_DFA += '     |';
            }
            else
            {
                if (dfa[i].symbol == (j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count]))
                {
                    RStr_DFA += dfa[i].to + ',' + string.Join('', dfa[i].LookAhead) + '|';
                }
                else
                {
                    RStr_DFA += '     |';
                }
            }
        }
        RStr_DFA += '
';
    }
}

public void CreateSLRTable()
{
    CreateItemsets();
    CreateDFA();
    SLRAna = new Table[proitemset.Count][];
    for (int i = 0; i < proitemset.Count; i++)
    {
        SLRAna[i] = new Table[Echar.Count + Nchar.Count];
        for (int j = 0; j < Echar.Count + Nchar.Count; j++)
        {
            char symbol = j < Echar.Count ? Echar[j] : Nchar[j - Echar.Count];
            int nextState = -1;
            HashSet<char> lookAhead = new HashSet<char>();
            foreach (DFA d in dfa)
            {
                if (d.from == i && d.symbol == symbol)
                {
                    nextState = d.to;
                    lookAhead.UnionWith(d.LookAhead);
                    break;
                }
            }
            if (nextState == -1)
            {
                SLRAna[i][j] = new Table();
            }
            else if (Gy_obj.Contains(nextState))
            {
                SLRAna[i][j] = new Table('R', Gy_obj.IndexOf(nextState) + 1);
            }
            else if (proitemset[nextState].LookAhead.Contains('#'))
            {
                SLRAna[i][j] = new Table('A', 0);
            }
            else
            {
                SLRAna[i][j] = new Table('S', nextState);
            }
        }
        foreach (int index in Gy_itemset)
        {
            if (proitemset[index].Container.Contains(i))
            {
                foreach (char c in proitemset[index].LookAhead)
                {
                    if (Echar.IndexOf(c) >= 0)
                    {
                        SLRAna[i][Echar.IndexOf(c)] = new Table('R', Gy_obj.IndexOf(index) + 1);
                    }
                    else if (c == '#')
                    {
                        SLRAna[i][Nchar.Count - 1] = new Table('R', Gy_obj.IndexOf(index) + 1);
                    }
                }
            }
        }
    }
    Success = true;
}

通过以上修改,可以有效解决 ComputeFirst()ComputeFollow() 函数中的“无法从 'string' 转换为 'char'”错误,并确保 SLR1 文法分析器的正常构建。

注意: 以上代码只是示例,具体的修改方法可能需要根据实际代码进行调整。

SLR1 文法分析器构造错误:ComputeFirst() 和 ComputeFollow() 函数中无法从 'string' 转换为 'char' 错误修复

原文地址: https://www.cveoy.top/t/topic/f0Ok 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录