Skip to content

Commit 4585ca4

Browse files
committed
fix glayzzle#45 & add some tests
1 parent 1721238 commit 4585ca4

File tree

6 files changed

+52
-25
lines changed

6 files changed

+52
-25
lines changed

src/ast/function.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ var KIND = 'function';
1414
* @property {Parameter[]} arguments
1515
* @property {Identifier} type
1616
* @property {boolean} byref
17+
* @property {boolean} nullable
1718
* @property {Block|null} body
1819
*/
19-
var fn = Declaration.extends(function _Function(name, args, byref, type, location) {
20+
var fn = Declaration.extends(function _Function(name, args, byref, type, nullable, location) {
2021
Declaration.apply(this, [KIND, name, location]);
2122
this.arguments = args;
2223
this.byref = byref;
2324
this.type = type;
25+
this.nullable = nullable;
2426
this.body = null;
2527
});
2628
module.exports = fn;

src/ast/parameter.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ var KIND = 'parameter';
1515
* @property {Node|null} value
1616
* @property {boolean} byref
1717
* @property {boolean} variadic
18+
* @property {boolean} nullable
1819
*/
19-
var Parameter = Declaration.extends(function Parameter(name, type, value, isRef, isVariadic, location) {
20+
var Parameter = Declaration.extends(function Parameter(name, type, value, isRef, isVariadic, nullable, location) {
2021
Declaration.apply(this, [KIND, name, location]);
2122
this.value = value;
2223
this.type = type;
2324
this.byref = isRef;
2425
this.variadic = isVariadic;
26+
this.nullable = nullable;
2527
});
2628

2729
module.exports = Parameter;

src/parser.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ parser.prototype.parse = function(code) {
183183
* Raise an error
184184
*/
185185
parser.prototype.raiseError = function(message, msgExpect, expect, token) {
186+
message += ' on line ' + this.lexer.yylloc.first_line;
186187
if (!this.suppressErrors) {
187188
throw new Error(message);
188189
}
@@ -219,7 +220,7 @@ parser.prototype.error = function(expect) {
219220
}
220221
this.token !== this.EOF
221222
return this.raiseError(
222-
msg + ' on line ' + this.lexer.yylloc.first_line,
223+
msg,
223224
msgExpect,
224225
expect,
225226
token

src/parser/function.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ module.exports = {
6969
this.next();
7070
}
7171
var isRef = this.is_reference();
72-
var name = false, use = [], returnType = false;
72+
var name = false, use = [], returnType = null, nullable = false;
7373
if (type !== 1) {
7474
if (this.expect(this.tok.T_STRING)) {
7575
name = this.text();
@@ -85,13 +85,17 @@ module.exports = {
8585
if (this.expect(')')) this.next();
8686
}
8787
if (this.token === ':') {
88-
returnType = this.next().read_type();
88+
if (this.next().token === '?') {
89+
nullable = true;
90+
this.next();
91+
}
92+
returnType = this.read_type();
8993
}
9094
if (type === 1) {
9195
// closure
92-
return result(params, isRef, use, returnType);
96+
return result(params, isRef, use, returnType, nullable);
9397
}
94-
return result(name, params, isRef, returnType);
98+
return result(name, params, isRef, returnType, nullable);
9599
}
96100
/**
97101
* ```ebnf
@@ -144,8 +148,17 @@ module.exports = {
144148
,read_parameter: function() {
145149
var node = this.node('parameter'),
146150
name = null,
147-
value = null;
148-
var type = this.read_type();
151+
value = null,
152+
type = null,
153+
nullable = false;
154+
if (this.token === '?') {
155+
this.next();
156+
nullable = true;
157+
}
158+
type = this.read_type();
159+
if (nullable && !type) {
160+
this.raiseError('Expecting a type definition combined with nullable operator');
161+
}
149162
var isRef = this.is_reference();
150163
var isVariadic = this.is_variadic();
151164
if (this.expect(this.tok.T_VARIABLE)) {
@@ -155,16 +168,17 @@ module.exports = {
155168
if (this.token == '=') {
156169
value = this.next().read_expr();
157170
}
158-
return node(name, type, value, isRef, isVariadic);
171+
return node(name, type, value, isRef, isVariadic, nullable);
159172
}
160173
/**
174+
* Reads a list of arguments
161175
* ```ebnf
162176
* function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')'
163177
* ```
164178
*/
165179
,read_function_argument_list: function() {
166180
var result = [];
167-
if (this.expect('(')) this.next();
181+
this.expect('(') && this.next();
168182
if (this.token !== ')') {
169183
while(this.token != this.EOF) {
170184
result.push(this.read_argument_list());
@@ -173,7 +187,7 @@ module.exports = {
173187
} else break;
174188
}
175189
}
176-
if (this.expect(')')) this.next();
190+
this.expect(')') && this.next();
177191
return result;
178192
}
179193
/**
@@ -194,16 +208,18 @@ module.exports = {
194208
* ```
195209
*/
196210
,read_type: function() {
211+
var result = this.node('identifier');
197212
switch(this.token) {
198213
case this.tok.T_ARRAY:
199214
this.next();
200-
return ['array'];
215+
return result(['', 'array'], false);
216+
case this.tok.T_NAMESPACE:
201217
case this.tok.T_NS_SEPARATOR:
202218
case this.tok.T_STRING:
203219
return this.read_namespace_name();
204220
case this.tok.T_CALLABLE:
205221
this.next();
206-
return ['callable'];
222+
return result(['', 'callable'], false);
207223
default:
208224
return null;
209225
}

test/functionTests.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
var should = require("should");
22
var parser = require('../src/index');
33

4-
/*describe('Function tests', function() {
4+
describe('Function tests', function() {
5+
var ast = parser.parseEval(
6+
'function &foo($a = 1, callable $b, ?array &...$params) : ?boolean {}'
7+
);
58

6-
it('test variadic', function () {
9+
it('test description', function () {
710
// Get result from parser
8-
var ast = parser.parseEval('function &foo($a = 1, array &...$params) {}');
9-
var fn = ast[1][0];
10-
fn[0].should.be.exactly('function');
11-
fn[1].should.be.exactly('foo');
12-
13-
var args = fn[2];
14-
args.length.should.be.exactly(2);
11+
ast.children[0].kind.should.be.exactly('function');
12+
ast.children[0].name.should.be.exactly('foo');
13+
ast.children[0].byref.should.be.exactly(true);
14+
ast.children[0].nullable.should.be.exactly(true);
15+
ast.children[0].type.name.should.be.exactly('boolean');
16+
});
1517

18+
it('test arguments', function () {
19+
/*
1620
// 1st param
1721
var arg1 = args[0];
1822
arg1[0].should.be.exactly('param');
@@ -31,6 +35,8 @@ var parser = require('../src/index');
3135
should.equal(arg2[3], null);
3236
arg2[4].should.be.exactly(true, 'byref');
3337
arg2[5].should.be.exactly(true, 'variadic');
38+
*/
3439
});
3540

36-
});*/
41+
42+
});

test/namespaceTest.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('Test namespace statements', function() {
2929
});
3030

3131
var multiNs = parser.parseEval([
32-
'namespace foo {',
32+
'namespace \\foo {',
3333
' $i++;',
3434
'}',
3535
'namespace {',

0 commit comments

Comments
 (0)