@lcap/nasl-parser
Version:
Take Nasl text to Nasl AST with the help of generalized parsing.
120 lines (100 loc) • 4.39 kB
text/typescript
import * as nasl from './decorated-nasl-ast';
import { isNewList, isStructure, isLogic, isFunction, isLogicDeclaration, isEnum} from '@lcap/nasl-concepts/asserts';
import { Visitor, withNoEnv } from './common-util';
import { CompilerEnvInfo } from './resolve-global-bindings';
// import { tryAddToNaslDataSource } from './process-annotations-entity';
/**
* 怎么说呢,步子不能迈太大,还是分三步吧。
* 1. 编译器内置一批可用的注解和处理规则,这样 AI 就能用起来了
* 2. 编译器给一套规范和一个入口,用户可用 ts、js 写处理规则,编译器会调用用户的处理规则
* 3. 用户可用 nasl 文本语法写处理规则
*
* 发现一个用构造函数 @column(id = ..., name = ..., required = ...)相比于 @id =..., @name =... @required =... 的好处
* 用构造函数的话,可以为 id、name、required 都设默认值,所以 @column 可以不写这些参数。
* 如果不用构造函数的话,即便要用默认值,@id、@name、@required 也都必须写出来,因为一般来说如果用户不标记,也不能认为有一批默认的标记吧
*/
// processAnnotations -> tryAddToNaslDataSource -> addToSpecificNaslDataSource -> toNaslDataEntity -> processColumnAnnotation
export function processAnnotations(cei: CompilerEnvInfo, nodes: Array<nasl.SupportedDefinition>, dataSources: any[]) {
new Visitor().preOrderVisitAll(cei, nodes, withNoEnv(processLogicAnnotations));
new Visitor().preOrderVisitAll(cei, nodes, withNoEnv(processEnumAnnotations));
new Visitor().preOrderVisitAll(cei, nodes, withNoEnv(processStructAnnotations));
// @ts-ignore
// nodes = new Visitor().preOrderVisitAll(cei, nodes, withNoEnv(tryAddToNaslDataSource(dataSources)));
}
const IDE = 'ide';
const DISPLAY = 'display';
export function processLogicAnnotations(nl : nasl.Logic | nasl.Function) {
if (!isLogic(nl) && !isFunction(nl) && !isLogicDeclaration(nl)) {
return nl;
}
const cAnns: Array<nasl.CstAnnotation> = nl.annotations;
if (cAnns) {
cAnns.forEach(cAnn => {
cAnn.value.forEach(ann => {
nl[ann.name] = (ann.value as nasl.StringLiteral).value;
});
});
}
return nl;
}
export function processEnumAnnotations(ne: nasl.Enum) {
if (!isEnum(ne)) {
return ne;
}
const cAnns: Array<nasl.CstAnnotation> = ne.annotations;
if (cAnns) {
cAnns.forEach(cAnn => {
cAnn.value.forEach(ann => {
ne[ann.name] = (ann.value as nasl.StringLiteral).value;
});
});
}
ne.enumItems.forEach(processEnumItemAnnotations);
return ne;
function processEnumItemAnnotations(ei: nasl.EnumItem) {
const cAnns: Array<nasl.CstAnnotation> = ei.annotations;
if (cAnns) {
cAnns.forEach(cAnn => {
cAnn.value.forEach(ann => {
ei[ann.name] = ann.value;
if (ann.name === 'label') {
ei.label = new nasl.StaticString({value: (ann.value as nasl.StringLiteral).value}); // 厉害啊!
}
});
});
}
}
}
export function processStructAnnotations(ns: nasl.Structure) {
if (!isStructure(ns)) {
return ns;
}
const cAnns: Array<nasl.CstAnnotation> = ns.annotations;
if (cAnns) {
cAnns.forEach(cAnn => {
cAnn.value.forEach(ann => {
ns[ann.name] = (ann.value as nasl.StringLiteral).value;
});
});
}
ns.properties.forEach(processStructPropertyAnnotations);
return ns;
function processStructPropertyAnnotations(sp: nasl.StructureProperty) {
const cAnns: Array<nasl.CstAnnotation> = sp.annotations;
if (cAnns) {
cAnns.forEach(cAnn => {
cAnn.value.forEach(ann => {
if (ann.name === 'label') {
sp.label = (ann.value as nasl.StringLiteral).value; // 厉害啊!
}
});
});
}
}
}
// @ts-ignore
export const forceToString = (e: AnnArgVal) => (e as StringLit).val;
// @ts-ignore
export const forceToBoolean = (e: AnnArgVal) => (e as BooleanLit).val;
// @ts-ignore
export const forceToNumber = (e: AnnArgVal) => (e as IntegerLit | DecimalLit).val;