forked from jamiepg1/valencia
-
Notifications
You must be signed in to change notification settings - Fork 2
/
expression.vala
154 lines (126 loc) · 4.29 KB
/
expression.vala
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* Copyright 2009-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
namespace Valencia {
public abstract class Expression : Object {
public abstract string to_string();
}
public class Id : Expression {
public string name;
public Id(string name) {
this.name = name;
}
public override string to_string() {
return name;
}
}
public class This : Expression {
public override string to_string() { return "this"; }
}
public class Base : Expression {
public override string to_string() { return "base"; }
}
public class New : Expression {
public Expression class_name;
public New(Expression class_name) {
this.class_name = class_name;
}
public override string to_string() {
return "new " + class_name.to_string();
}
}
public class MethodCall : Expression {
public Expression method;
public MethodCall(Expression method) {
this.method = method;
}
public override string to_string() {
return method.to_string() + "()";
}
}
public class CompoundExpression : Expression {
public Expression left;
public string right;
public CompoundExpression(Expression left, string right) {
this.left = left;
this.right = right;
}
public override string to_string() {
return left.to_string() + "." + right;
}
}
class ExpressionParser : Object {
Scanner scanner;
int pos;
bool partial;
public ExpressionParser(string input, int pos, bool partial) {
scanner = new Scanner(input);
this.pos = pos;
this.partial = partial;
}
bool accept(Token t) { return scanner.accept_token(t); }
ParseInfo parse_expr(bool nested) {
int parens = 0;
while (true) {
Token t = scanner.next_token();
if (t == Token.EOF || scanner.start > pos)
break;
bool is_new;
if (t == Token.NEW) {
is_new = true;
t = scanner.next_token();
if (scanner.start > pos)
break;
} else is_new = false;
if (t == Token.ID || (t == Token.THIS || t == Token.BASE) && !is_new) {
Expression e = null;
if (t == Token.ID)
e = new Id(scanner.val());
else if (t == Token.THIS)
e = new This();
else if (t == Token.BASE)
e = new Base();
while (true) {
if (scanner.end >= pos)
return new ParseInfo(is_new ? new New(e) : e);
if (accept(Token.LEFT_PAREN)) {
if (is_new) {
e = new New(e);
is_new = false;
}
int paren_pos = scanner.start;
ParseInfo info = parse_expr(true);
if (scanner.end > pos || info.inner != null || info.outer != null) {
if (info.outer == null) {
info.outer = e;
info.outer_pos = paren_pos;
}
return info;
}
e = new MethodCall(e);
}
if (!accept(Token.PERIOD))
break;
if (partial && scanner.end == pos)
e = new CompoundExpression(e, "");
else if (accept(Token.ID) && scanner.start <= pos)
e = new CompoundExpression(e, scanner.val());
else break;
}
}
if (nested) {
if (t == Token.LEFT_PAREN) {
++parens;
continue;
}
if (t == Token.RIGHT_PAREN && --parens < 0)
break;
}
}
return new ParseInfo(null);
}
public ParseInfo parse() { return parse_expr(false); }
}
}