openspg-concept-rule-antlr4
v0.1.4
Published
OpenSPG Concept Rule Mark Language Lexer and Parser by official ANTLR4 grammar
Maintainers
Readme
OpenSPG Concept-Rule Mark Language Lexer and Parser, generated by official ANTLR4 grammar.
Change Log · Report Bug · Pull Request

Installation
npm install openspg-concept-rule-antlr4It will be
pnpm/yarn add openspg-concept-rule-antlr4if you use pnpm or yarn.
Usage
Language Parser
parse(code, [options]):parse()parses the provided code as an entire Concept-Rule source unit.options:tolerant:boolean, default isfalse. Iftrue, the parser will try to parse as much as possible, even if the input is invalid, and never throw an error.selector:function, default is(p) => p.sourceUnit(). If provided, the parser will only return the nodes that match the selector. It will be useful when you want to parse a specific node.
output:SyntaxNode, the root node of the AST.
// parse.mjs
import {parse} from 'openspg-concept-rule-antlr4';
const code = `// Sample
namespace Sample
\`TaxOfRiskUser\`/\`赌博App开发者\`:
rule: [[
Define (s:\`ProductChain\`.\`TaxonomyOfCompanyAccident\`/\`周期性行业头部上市公司停产事故\`)-[p: leadTo]->(o:\`ProductChain\`.\`TaxonomyOfIndustryInfluence\`/\`成本上升\`) {
Structure {
\`TaxOfRiskApp\`
}
Constraint {
R("30天内浏览"): p.timestamp > -30
o = group(s).count(u)
}
Action {
downEvent = createNodeInstance(
type = ProductChain.IndustryInfluence,
value = {
subject = down.id
}
)
createEdgeInstance(
src = s,
dst = downEvent,
type = leadTo,
value = {
}
)
}
}
]]
`;
const ast = parse(code, {tolerant: true, selector: (p) => p.sourceUnit()});
Tokenizer
tokenizer(code, [options]):tokenizer()parses the provided code as tokens.options:tolerant:boolean, default isfalse.
output:SyntaxToken[].
// tokenizer.mjs
import {tokenizer} from 'openspg-concept-rule-antlr4';
const tokens = tokenizer(code, {tolerant: true});
Traverse AST
We can use it alongside the parser to traverse nodes.
import {parse, visit, serialize} from 'openspg-concept-rule-antlr4';
const ast = parse(code);
// Use `visit` to traverse ast by enter/exit node type.
visit(ast, {
enter: ({node, parent}) => {
console.log(node.type, parent?.type); // print node type
},
exit: () => {
}, // will call when exit node
Identifier: ({node: identifierNode}) => {
console.log(identifierNode.name); // print identifier name
},
exitContractDefinition: ({node: contractDefinitionNode}) => {
// will call when exit ContractDefinition node
}
});
// Use `serialize` to modify ast.
const newAST = serialize(ast, ({node}) => {
// do something
if (node.type === 'Identifier') {
return node.name;
}
return node;
})// traverse.mjs
import {parse, traverse} from 'openspg-concept-rule-antlr4';
const ast = parse(code);
const newAST = traverse(ast, (path) => {
// path.path => `SourceUnit.Namespace` ...
// path.node => current node
// path.parentPath => parent node path
// path.depth => current node depth
// path.stop(); => stop traverse
// path.rewrite({...}); => rewrite current node
// path.matches({ type: 'xxx' }); => check if current node matches the given filter
// return () => {}; => will call when exit node
});Low-level API
Not recommended, but you can use it if you want.
import {ConceptRuleLexer, ConceptRuleParser, CharStream, CommonTokenStream} from 'openspg-concept-rule-antlr4';
const code = `...`; // code here
const input = CharStream.fromString(code);
const lexer = new SolidityLexer(input);
const tokens = new CommonTokenStream(lexer);
const parser = new SolidityParser(tokens);
const parseTree = parser.sourceUnit();
// do something with parseTree