UNPKG

@lcap/nasl-parser

Version:

Take Nasl text to Nasl AST with the help of generalized parsing.

140 lines (118 loc) 4.52 kB
import { PackNaslAndCst, wellDefined } from './common-util'; // import * as nasl from '@lcap/nasl'; import * as nasl from './decorated-nasl-ast'; import { Visitor, sequenceWithEnv_, composeWithEnv } from './common-util'; import { processAnnotations, processLogicAnnotations } from './process-annotations'; import { addLogicLocalBindings, removeLogicLocalBindings, usingNamespace, resolveCallee, resolveTypeRef, resolveQEnumId, } from './resolve-local-bindings'; import { isStructure, isEnum, isLogic, isDataSource, isFrontendType } from '@lcap/nasl-concepts/asserts'; import { collectAllGlobalDefinitions, CompilerEnvInfo, leaveNamespace } from './resolve-global-bindings'; /** * 缺失: * *** Type<Ty, Ty> 使用处的 Ty 区分是引入的 type variable 还是外层定义的 reference type。 * *** Annotation 处理 * NewList 缺 TypeAnnotation * ArrayAccess 多维下标支持,翻译成连续 Get 调用 * callNameSpace 完整实现 * type 的 nameSpace 完整实现 * qualified name 等 * { } 和 [ ] 的识别 * */ /** * 已实现: * toNaslAST 不会区分函数、逻辑、接口调用、new 构造器调用,先统一为逻辑调用。会在下一个 refine-nasl-call 阶段区分。 * */ /** * class 方法与全局函数相比 * - 可隐式传递数据,(通过 this)。仁者见仁,智者见智。 * * 承上,visitor 模式与普通架构相比 * - 在 this 上动态派发(通过 override),将多个函数名 toNaslAAA、toNaslBBB、toNaslCCC 全部统一为 toNasl 或 visit。 * 这样大量的递归调用 toNaslAAA、toNaslBBB 也可全部统一为 toNasl 或 visit。仁者见仁,智者见智。 * - 如使用外部 visitor 模式,仍需要遍历一遍整棵 AST 结构来写出 visitor,并不节约代码量。 * 如使用内部 visitor 模式,仍没有充足的控制权,如遍历顺序等。仁者见仁,智者见智。 */ // defs.nasl 是一个数组,方便后续处理 export function toNaslAST(seqNasl : Array<nasl.SupportedDefinition>) { if (!seqNasl) { return null; } const cei = new CompilerEnvInfo(); seqNasl = addGlobalBindings(cei, seqNasl); seqNasl = addLocalBindings(cei, seqNasl); const dataSources = new Array(); processAnnotations(cei, seqNasl, dataSources); const app = new nasl.App({ logics: extractLogics(seqNasl), enums: extractEnums(seqNasl), structures: extractStructures(seqNasl), frontendTypes: seqNasl.filter(isFrontendType), dataSources: [], }); app.name = 'UnstableFeatureTestOnly'; // const app : nasl.App = collectAppFromSeqNasl(sn); // app.dataSources = dataSources; // return PackNaslAndCst(app, {App: defs.cst}); return app; } function addGlobalBindings(cei: CompilerEnvInfo, seqNaslDefs: any) { const tasks = (env: CompilerEnvInfo, obj: any) => { collectAllGlobalDefinitions(env, obj); return obj; } const clean = (env: CompilerEnvInfo, obj: any) => { leaveNamespace(env, obj); return obj; } return new Visitor().preOrderVisitAll(cei, seqNaslDefs, tasks, clean); } function addLocalBindings(cei: CompilerEnvInfo, seqNaslDefs: any) { const tasks = (env: CompilerEnvInfo, obj: any) => { usingNamespace(env, obj); addLogicLocalBindings(env, obj); obj = resolveCallee(env, obj); obj = resolveTypeRef(env, obj); obj = resolveQEnumId(env, obj); return obj; } const clean = (env: CompilerEnvInfo, obj: any) => { removeLogicLocalBindings(env, obj); return obj; } return new Visitor().preOrderVisitAll(cei, seqNaslDefs, tasks, clean); } function extractStructures(nodes: Array<nasl.SupportedDefinition>) { const res = []; new Visitor().preOrderVisitAll(null, nodes, (env, obj) => { if (isStructure(obj)) { res.push(obj); } return obj; }); return res; } function extractEnums(nodes: Array<nasl.SupportedDefinition>) { const res = []; new Visitor().preOrderVisitAll(null, nodes, (env, obj) => { if (isEnum(obj)) { res.push(obj); } return obj; }); return res; } function extractLogics(nodes: Array<nasl.SupportedDefinition>) { const res = []; new Visitor().preOrderVisitAll(null, nodes, (env, obj) => { if (isLogic(obj)) { res.push(obj); } return obj; }); return res; }