lib/parser.js (78 lines of code) (raw):
'use strict';
const { BaseParser } = require('@jacksontian/skyline');
const { Tag, tip } = require('./tag');
class Parser extends BaseParser {
constructor(lexer) {
super(lexer);
}
move() {
this.look = this.lexer.scan();
}
tagTip(tag) {
return tip(tag);
}
annotation() {
this.match(Tag.START);
const items = [];
while (!this.is(Tag.END)) {
if (this.is(Tag.TEXT)) {
items.push({
type: 'description',
attrs: [],
text: this.look
});
this.move();
} else if (this.is(Tag.TYPE)) {
var type = this.look;
var item = {
type: type.typeName,
attrs: []
};
this.move();
if (this.look.tag === '[') {
this.move();
while (this.look.tag === Tag.ID) {
var attrName = this.look;
this.move();
this.match('=');
var attrValue = this.look;
this.match(Tag.ID);
item.attrs.push({
name: attrName,
value: attrValue
});
if (this.look.tag === ',') {
this.move();
}
}
this.match(']');
}
if (type.typeName === 'param') {
var name = this.look;
this.match(Tag.ID);
item.name = name;
} else if (type.typeName === 'error') {
var code = this.look;
this.match(Tag.ID);
item.code = code;
}
var text = this.look;
this.match(Tag.TEXT);
item.text = text;
items.push(item);
} else {
this.error('expect "@xxx"');
}
}
this.match(Tag.END);
return {
type: 'annotation',
items: items
};
}
program() {
this.move();
return this.annotation();
}
}
module.exports = Parser;