-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.cs
120 lines (109 loc) · 2.57 KB
/
Parser.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;
namespace Scallop
{
class Parser
{
public Parser() { }
public SExp[] Parse(IEnumerable<LexerToken> tokens)
{
IEnumerator<LexerToken> itor = tokens.GetEnumerator();
if (itor.MoveNext())
{
return CreateExpressions(tokens);
}
const string MSG = "Empty S-Expression.";
throw new ParserException(MSG);
}
SExp CreateAtom(LexerToken token)
{
SExp atom = null;
if (token is TokenLeftParen)
{
atom = new __LeftParen();
}
else if (token is TokenInteger)
{
int n = 0;
int.TryParse(token.Value, out n);
atom = new Integer(n);
}
else if (token is TokenString)
{
atom = new String(token.Value);
}
else if (token is TokenIdentifier)
{
atom = new Identifier(token.Value);
}
else
{
string msg =
string.Format("failed to create atom from token '{0}'.", token.Value);
throw new ParserException(msg);
}
return atom;
}
public SExp[] CreateExpressions(IEnumerable<LexerToken> tokens)
{
IEnumerator<LexerToken> itor = tokens.GetEnumerator();
// confirm
if (!itor.MoveNext())
{
const string MSG = "Empty S-Expression.";
throw new ParserException(MSG);
}
itor = tokens.GetEnumerator();
Stack<SExp> stkExp = new Stack<SExp>();
SExp list = new Nil();
bool consing = false;
while (true)
{
if (consing)
{
SExp exp = null;
try { exp = stkExp.Pop(); }
catch
{
const string MSG = "Extra close parenthesis.";
throw new ParserException(MSG);
}
if (exp is __LeftParen)
{
stkExp.Push(list);
list = new Nil();
consing = false;
}
else
{
list = new Cell(exp, list);
}
}
else
{
if (!itor.MoveNext())
{
break;
}
else if (itor.Current is TokenRightParen)
{
consing = true;
}
else
{
SExp exp = CreateAtom(itor.Current);
stkExp.Push(exp);
}
}
}
List<SExp> l = new List<SExp>(stkExp);
l.Reverse();
if (l.Exists(exp=>exp is __LeftParen))
{
string msg = "Unclosed list detected.";
throw new ParserException(msg);
}
return l.ToArray();
}
}
}