Skip to content

Commit 7f47a2c

Browse files
committed
简单解析上下文无关文法
1 parent 6e4cc75 commit 7f47a2c

2 files changed

Lines changed: 87 additions & 25 deletions

File tree

Assets/Grammar/GrammaParser.cs

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using Xtaieer.Lex;
45

56
namespace Xtaieer.Grammar
@@ -20,6 +21,7 @@ private enum TokenType
2021
MINAL,
2122
SINGLE_CHAR_MINAL
2223
}
24+
2325
private class Token
2426
{
2527
public static readonly Token EMPTY = new Token("", TokenType.EMPTY);
@@ -94,18 +96,61 @@ public void AddTerminal(string terminal)
9496
terminals.Add(terminal, new Terminal(terminal));
9597
}
9698

99+
public void AddProduction(string production)
100+
{
101+
lex.SetInput(new StringReader(production));
102+
current = lex.NextToken();
103+
Nonterminal nonterminal = Nonterminal();
104+
Match(TokenType.SYMBOL);
105+
List<Minal[]> productions = RightT(null);
106+
foreach(Minal[] pro in productions)
107+
{
108+
nonterminal.AddProduction(pro);
109+
}
110+
}
97111

112+
public Nonterminal[] GetResult()
113+
{
114+
List<Nonterminal> result = new List<Nonterminal>(nonterminals.Count);
115+
foreach(Nonterminal nonterminal in nonterminals.Values)
116+
{
117+
result.Add(nonterminal);
118+
}
119+
return result.ToArray();
120+
}
98121

99-
private void RightT()
122+
private List<Minal[]> RightT(List<Minal[]> productions)
100123
{
101-
Right();
124+
List<Minal[]> result = productions;
125+
if(result == null)
126+
{
127+
result = new List<Minal[]>();
128+
}
129+
LinkedList<Minal> minalLinkedList = new LinkedList<Minal>();
130+
minalLinkedList = Right(minalLinkedList);
131+
Minal[] minals = new Minal[minalLinkedList.Count];
132+
LinkedListNode<Minal> head = minalLinkedList.First;
133+
int index = 0;
134+
while(head != null)
135+
{
136+
minals[index] = head.Value;
137+
index++;
138+
head = head.Next;
139+
}
140+
result.Add(minals);
141+
if (current != null && current.Type == TokenType.SYMBOL && current.Name == ";")
142+
{
143+
Match(TokenType.SYMBOL);
144+
return RightT(result);
145+
}
146+
return result;
102147
}
103148

104149
private LinkedList<Minal> Right(LinkedList<Minal> left)
105150
{
106151
Minal minal = Minal();
107-
left.AddBefore(left.First, minal);
108-
if(current.Type == TokenType.MINAL || current.Type == TokenType.SINGLE_CHAR_MINAL)
152+
left.AddFirst(minal);
153+
if(current != null && (current.Type == TokenType.MINAL || current.Type == TokenType.SINGLE_CHAR_MINAL))
109154
{
110155
return Right(left);
111156
}
@@ -114,41 +159,58 @@ private LinkedList<Minal> Right(LinkedList<Minal> left)
114159

115160
private Minal Minal()
116161
{
117-
Token token = current;
118-
Match(TokenType.MINAL);
119-
if (terminals.ContainsKey(token.Name))
162+
if (terminals.ContainsKey(current.Name) || current.Type == TokenType.SINGLE_CHAR_MINAL)
120163
{
121-
Minal minal = terminals[token.Name];
122-
return minal;
164+
return Terminal();
123165
}
124166
else
125167
{
126-
if(nonterminals.ContainsKey(token.Name))
127-
{
128-
return nonterminals[token.Name];
129-
}
130-
else
131-
{
132-
Nonterminal nonterminal = new Nonterminal(token.Name);
133-
nonterminals.Add(token.Name, nonterminal);
134-
return nonterminal;
135-
}
168+
return Nonterminal();
136169
}
137170
}
138171

139-
private void Terminal()
172+
private Terminal Terminal()
140173
{
141-
174+
Token token = current;
175+
if (current.Type == TokenType.SINGLE_CHAR_MINAL)
176+
{
177+
Match(TokenType.SINGLE_CHAR_MINAL);
178+
if (!terminals.ContainsKey(token.Name))
179+
{
180+
Terminal minal = new Terminal(token.Name);
181+
terminals.Add(token.Name, minal);
182+
}
183+
}
184+
else
185+
{
186+
Match(TokenType.MINAL);
187+
}
188+
return terminals[token.Name];
142189
}
143190

144-
private void Nonterminal()
191+
private Nonterminal Nonterminal()
145192
{
146-
193+
Token token = current;
194+
Match(TokenType.MINAL);
195+
if (nonterminals.ContainsKey(token.Name))
196+
{
197+
return nonterminals[token.Name];
198+
}
199+
else
200+
{
201+
Nonterminal nonterminal = new Nonterminal(token.Name);
202+
nonterminals.Add(token.Name, nonterminal);
203+
return nonterminal;
204+
}
147205
}
148206

149207
private void Match(TokenType type)
150208
{
151209
current = lex.NextToken();
210+
while (current != null && current.Type == TokenType.EMPTY)
211+
{
212+
current = lex.NextToken();
213+
}
152214
}
153215
}
154216
}

Assets/Grammar/Minal.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public void AddProduction(Minal[] minal)
3131
productions.Add(minal);
3232
}
3333

34-
public IEnumerator<Minal[]> ProductionIterator()
34+
public IEnumerable<Minal[]> ProductionIterator()
3535
{
36-
return productions.GetEnumerator();
36+
return productions;
3737
}
3838
}
3939
}

0 commit comments

Comments
 (0)