feat(Parser): implement Parser
Add a simple parser implementation that supports only field reads.
This commit is contained in:
@ -1,2 +1,81 @@
|
||||
import {FIELD, int} from 'facade/lang';
|
||||
import {ListWrapper, List} from 'facade/collection';
|
||||
import {Lexer, EOF, Token, $PERIOD} from './lexer';
|
||||
import {ClosureMap} from './closure_map';
|
||||
import {AST, ImplicitReceiver, FieldRead} from './ast';
|
||||
|
||||
var _implicitReceiver = new ImplicitReceiver();
|
||||
|
||||
export class Parser {
|
||||
@FIELD('final _lexer:Lexer')
|
||||
@FIELD('final _closureMap:ClosureMap')
|
||||
constructor(lexer:Lexer, closureMap:ClosureMap){
|
||||
this._lexer = lexer;
|
||||
this._closureMap = closureMap;
|
||||
}
|
||||
|
||||
parse(input:string):AST {
|
||||
var tokens = this._lexer.tokenize(input);
|
||||
return new _ParseAST(tokens, this._closureMap).parseChain();
|
||||
}
|
||||
}
|
||||
|
||||
class _ParseAST {
|
||||
@FIELD('final tokens:List<Token>')
|
||||
@FIELD('final closureMap:ClosureMap')
|
||||
@FIELD('index:int')
|
||||
constructor(tokens:List, closureMap:ClosureMap) {
|
||||
this.tokens = tokens;
|
||||
this.index = 0;
|
||||
this.closureMap = closureMap;
|
||||
}
|
||||
|
||||
peek(offset:int):Token {
|
||||
var i = this.index + offset;
|
||||
return i < this.tokens.length ? this.tokens[i] : EOF;
|
||||
}
|
||||
|
||||
get next():Token {
|
||||
return this.peek(0);
|
||||
}
|
||||
|
||||
advance() {
|
||||
this.index ++;
|
||||
}
|
||||
|
||||
optionalCharacter(code:int):boolean {
|
||||
if (this.next.isCharacter(code)) {
|
||||
this.advance();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
parseChain():AST {
|
||||
var exprs = [];
|
||||
while (this.index < this.tokens.length) {
|
||||
ListWrapper.push(exprs, this.parseAccess());
|
||||
}
|
||||
return ListWrapper.first(exprs);
|
||||
}
|
||||
|
||||
parseAccess():AST {
|
||||
var result = this.parseFieldRead(_implicitReceiver);
|
||||
while(this.optionalCharacter($PERIOD)) {
|
||||
result = this.parseFieldRead(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
parseFieldRead(receiver):AST {
|
||||
var id = this.parseIdentifier();
|
||||
return new FieldRead(receiver, id, this.closureMap.getter(id));
|
||||
}
|
||||
|
||||
parseIdentifier():string {
|
||||
var n = this.next;
|
||||
this.advance();
|
||||
return n.toString();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user