Skip to content

Commit 6e4cc75

Browse files
committed
语法分析器
1 parent 73f1522 commit 6e4cc75

8 files changed

Lines changed: 333 additions & 0 deletions

File tree

Assets/Grammar.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Grammar/GrammaParser.cs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Xtaieer.Lex;
4+
5+
namespace Xtaieer.Grammar
6+
{
7+
public class GrammaParser
8+
{
9+
/*
10+
* S -> Nonterminal:Right'
11+
* Right' -> Right;Right' | Right
12+
* Right -> Minal Right | Minal
13+
* Minal -> Terminal | Nonterminal
14+
*/
15+
16+
private enum TokenType
17+
{
18+
EMPTY,
19+
SYMBOL,
20+
MINAL,
21+
SINGLE_CHAR_MINAL
22+
}
23+
private class Token
24+
{
25+
public static readonly Token EMPTY = new Token("", TokenType.EMPTY);
26+
27+
public string Name
28+
{
29+
get;
30+
private set;
31+
}
32+
33+
public TokenType Type
34+
{
35+
get;
36+
private set;
37+
}
38+
39+
public Token(string name, TokenType type)
40+
{
41+
Type = type;
42+
Name = name;
43+
}
44+
45+
public override bool Equals(object obj)
46+
{
47+
if (obj is Token)
48+
{
49+
Token t = obj as Token;
50+
if (t.Name != null)
51+
{
52+
return Name.Equals(t.Name) && Type == t.Type;
53+
}
54+
}
55+
return false;
56+
}
57+
58+
public override int GetHashCode()
59+
{
60+
return Name.GetHashCode();
61+
}
62+
63+
public override string ToString()
64+
{
65+
return Name;
66+
}
67+
}
68+
69+
private Dictionary<string, Terminal> terminals = new Dictionary<string, Terminal>();
70+
private Dictionary<string, Nonterminal> nonterminals = new Dictionary<string, Nonterminal>();
71+
private LexicalAnalyzer<Token> lex;
72+
private Token current;
73+
74+
public GrammaParser() {
75+
lex = new LexicalAnalyzer<Token>(
76+
new LexicalAnalyzer<Token>.RegularAndAction[] {
77+
new LexicalAnalyzer<Token>.RegularAndAction("\t| ", (lex, line, column) => { return Token.EMPTY; }),
78+
new LexicalAnalyzer<Token>.RegularAndAction("\".\"", (lex, line, column) => { return new Token(new string(lex[1], 1), TokenType.SINGLE_CHAR_MINAL); }),
79+
new LexicalAnalyzer<Token>.RegularAndAction("([A-Z]|[a-z]|[0-9])+", (lex, line, column) => {return new Token(lex, TokenType.MINAL); }),
80+
new LexicalAnalyzer<Token>.RegularAndAction(":|;|%|", (lex, line, column) => {return new Token(lex, TokenType.SYMBOL); })
81+
}
82+
);
83+
}
84+
85+
public void AddTerminal(string terminal)
86+
{
87+
for (int i = 0; i < terminal.Length; i++)
88+
{
89+
if (!char.IsLetterOrDigit(terminal[i]))
90+
{
91+
throw new ArgumentException("终结符只能使用字母和数字");
92+
}
93+
}
94+
terminals.Add(terminal, new Terminal(terminal));
95+
}
96+
97+
98+
99+
private void RightT()
100+
{
101+
Right();
102+
}
103+
104+
private LinkedList<Minal> Right(LinkedList<Minal> left)
105+
{
106+
Minal minal = Minal();
107+
left.AddBefore(left.First, minal);
108+
if(current.Type == TokenType.MINAL || current.Type == TokenType.SINGLE_CHAR_MINAL)
109+
{
110+
return Right(left);
111+
}
112+
return left;
113+
}
114+
115+
private Minal Minal()
116+
{
117+
Token token = current;
118+
Match(TokenType.MINAL);
119+
if (terminals.ContainsKey(token.Name))
120+
{
121+
Minal minal = terminals[token.Name];
122+
return minal;
123+
}
124+
else
125+
{
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+
}
136+
}
137+
}
138+
139+
private void Terminal()
140+
{
141+
142+
}
143+
144+
private void Nonterminal()
145+
{
146+
147+
}
148+
149+
private void Match(TokenType type)
150+
{
151+
current = lex.NextToken();
152+
}
153+
}
154+
}

Assets/Grammar/GrammaParser.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Grammar/GrammarAnalyzer.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.IO;
3+
using System.Collections.Generic;
4+
using Xtaieer.Lex;
5+
using UnityEngine;
6+
7+
namespace Xtaieer.Grammar
8+
{
9+
public class GrammarAnalyzer
10+
{
11+
/*
12+
* S -> Nonterminal:Right'
13+
* Right' -> Right;Right' | Right
14+
* Right -> Minal Right | Minal
15+
* Minal -> Terminal | Nonterminal
16+
*/
17+
private class Token
18+
{
19+
public static readonly Token EMPTY = new Token("");
20+
21+
public string Name
22+
{
23+
get;
24+
private set;
25+
}
26+
27+
public Token(string name)
28+
{
29+
Name = name;
30+
}
31+
32+
public override bool Equals(object obj)
33+
{
34+
if(obj is Token)
35+
{
36+
Token t = obj as Token;
37+
if (t.Name != null)
38+
{
39+
return Name.Equals(t.Name);
40+
}
41+
}
42+
return false;
43+
}
44+
45+
public override int GetHashCode()
46+
{
47+
return Name.GetHashCode();
48+
}
49+
50+
public override string ToString()
51+
{
52+
return Name;
53+
}
54+
}
55+
56+
private List<string> terminals = new List<string>();
57+
private LexicalAnalyzer<Token> lex;
58+
59+
public GrammarAnalyzer()
60+
{
61+
lex = new LexicalAnalyzer<Token>(
62+
new LexicalAnalyzer<Token>.RegularAndAction[] {
63+
new LexicalAnalyzer<Token>.RegularAndAction("\t| ", (lex, line, column) => { return Token.EMPTY; }),
64+
new LexicalAnalyzer<Token>.RegularAndAction("\".\"", (lex, line, column) => { return new Token(new string(lex[1], 1)); }),
65+
new LexicalAnalyzer<Token>.RegularAndAction("([A-Z]|[a-z]|[0-9])+", (lex, line, column) => {return new Token(lex); }),
66+
new LexicalAnalyzer<Token>.RegularAndAction(":|;|%|", (lex, line, column) => {return new Token(lex); })
67+
}
68+
);
69+
}
70+
71+
public void AddTerminal(string terminal)
72+
{
73+
for(int i = 0; i < terminal.Length; i ++)
74+
{
75+
if(!char.IsLetterOrDigit(terminal[i]))
76+
{
77+
throw new ArgumentException("终结符只能使用字母和数字");
78+
}
79+
}
80+
terminals.Add(terminal);
81+
}
82+
83+
public void AddProduction(string production)
84+
{
85+
lex.SetInput(new StringReader(production));
86+
Token token = lex.NextToken();
87+
while(token != null) {
88+
token = lex.NextToken();
89+
}
90+
}
91+
92+
93+
}
94+
}

Assets/Grammar/GrammarAnalyzer.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Grammar/Minal.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System.Collections.Generic;
2+
3+
namespace Xtaieer.Grammar
4+
{
5+
public class Minal
6+
{
7+
public string Name
8+
{
9+
get;
10+
private set;
11+
}
12+
13+
public Minal(string name)
14+
{
15+
Name = name;
16+
}
17+
}
18+
19+
public class Terminal : Minal
20+
{
21+
public Terminal(string name) : base(name) { }
22+
}
23+
24+
public class Nonterminal : Minal
25+
{
26+
public Nonterminal(string name) : base(name) { }
27+
28+
private List<Minal[]> productions = new List<Minal[]>();
29+
public void AddProduction(Minal[] minal)
30+
{
31+
productions.Add(minal);
32+
}
33+
34+
public IEnumerator<Minal[]> ProductionIterator()
35+
{
36+
return productions.GetEnumerator();
37+
}
38+
}
39+
}

Assets/Grammar/Minal.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/Regular/RegularParser.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ private IRegularExpression Factor()
163163
Match(current);
164164
return new SingleCharLeafExpression(c);
165165
}
166+
if(current == '.')
167+
{
168+
Match(current);
169+
return new RangeCharLeafExpression((char)0, (char)255);
170+
}
166171
else
167172
{
168173
if (!IsOperator(current))

0 commit comments

Comments
 (0)