This code is designed to parse a directory structure for grammar files and extract language information for a parser generator tool, likely ANTLR. It utilizes two key functions: findGrammars(directory)
to recursively extract language information from grammar files, and getParser(language)
to search for corresponding parser files.
npm run import -- "get antlr tool"
import fs from 'fs'
import path from 'path'
const PARSER_PATH = path.join(__dirname, '../Resources/Parsers')
const LANGUAGES = []
const GRAMMARS = []
function findGrammars(directory) {
let grammars = fs.readdirSync(path.join(PARSER_PATH, directory))
for(let j = 0; j < grammars.length; j++) {
if(grammars[j][0] == '.' || grammars[j].match('examples')) {
continue
}
if(grammars[j].endsWith('.g4')) {
let language = path.basename(grammars[j], path.extname(grammars[j]))
.replace('Lexer', '').replace('Parser', '')
if(!LANGUAGES.includes(directory)) {
LANGUAGES.push(directory)
}
if(!LANGUAGES.includes(language)) {
LANGUAGES.push(language)
}
GRAMMARS.push(path.join(directory, grammars[j]))
} else if (fs.statSync(path.join(PARSER_PATH, directory, grammars[j])).isDirectory()) {
findGrammars(path.join(directory, grammars[j]))
}
}
}
let languages = fs.readdirSync(PARSER_PATH)
for(let i = 0; i < languages.length; i++) {
if(languages[i][0] == '.') {
continue
}
if(!fs.statSync(path.join(PARSER_PATH, languages[i])).isDirectory()) {
continue
}
findGrammars(languages[i])
}
async function getParser(language) {
for(let i = 0; i < GRAMMARS.length; i++) {
if(GRAMMARS[i].match(language + '/') || GRAMMARS[i].match('/' + language)) {
let lang = path.basename(GRAMMARS[i], path.extname(GRAMMARS[i]))
.replace('Lexer', '').replace('Parser', '')
let lexerPath = path.join(PARSER_PATH, path.dirname(GRAMMARS[i]), lang + 'Lexer.js')
let parserPath = path.join(PARSER_PATH, path.dirname(GRAMMARS[i]), lang + 'Parser.js')
let listenerPath = path.join(PARSER_PATH, path.dirname(GRAMMARS[i]), lang + 'Listener.js')
if(!fs.existsSync(listenerPath)) {
listenerPath = path.join(PARSER_PATH, path.dirname(GRAMMARS[i]), lang + 'ParserListener.js')
}
let hasListener = fs.existsSync(listenerPath)
console.log(language, lexerPath, parserPath)
if(!fs.existsSync(lexerPath) || !fs.existsSync(parserPath)) {
continue
}
let codeCell = `
import antlr4 from 'antlr4'
import lexer from '${lexerPath}'
import parser from '${parserPath}'
${hasListener?('import listener from \''+listenerPath+'\''):''}
export default {antlr4, lexer, parser${hasListener?', listener':''}}
`
let module = await importer.makeESModule(codeCell, __filename + '<inline>', global)
return module
}
}
return {}
}
export default getParser
import path from 'path';
import fs from 'fs';
import { importESModule } from 'import-ES-module';
const parserPath = path.join(__dirname, '../Resources/Parsers');
const languages = [];
const grammars = [];
/**
* Recursively finds grammars in the given directory.
* @param {string} directory The current directory to search.
*/
async function findGrammars(directory) {
try {
const files = await fs.promises.readdir(path.join(parserPath, directory));
for (const file of files) {
if (file.startsWith('.') || file.includes('examples')) {
continue;
}
if (file.endsWith('.g4')) {
const language = file.replace('Lexer', '').replace('Parser', '');
if (!languages.includes(directory)) {
languages.push(directory);
}
if (!languages.includes(language)) {
languages.push(language);
}
grammars.push(path.join(directory, file));
} else if ((await fs.promises.stat(path.join(parserPath, directory, file))).isDirectory()) {
await findGrammars(path.join(directory, file));
}
}
} catch (error) {
console.error(`Error reading directory ${directory}:`, error);
}
}
/**
* Finds all grammars in the parser path.
*/
async function initializeGrammars() {
try {
const directories = await fs.promises.readdir(parserPath);
for (const directory of directories) {
if (directory.startsWith('.') ||!(await fs.promises.stat(path.join(parserPath, directory))).isDirectory()) {
continue;
}
await findGrammars(directory);
}
} catch (error) {
console.error(`Error reading parser path:`, error);
}
}
/**
* Gets the parser for the given language.
* @param {string} language The language to get the parser for.
* @returns {object} The parser object, or an empty object if not found.
*/
async function getParser(language) {
try {
for (const grammar of grammars) {
if (grammar.includes(language + '/') || grammar.includes('/' + language)) {
const lang = path.basename(grammar, path.extname(grammar)).replace('Lexer', '').replace('Parser', '');
const lexerPath = path.join(parserPath, path.dirname(grammar), lang + 'Lexer.js');
const parserPath = path.join(parserPath, path.dirname(grammar), lang + 'Parser.js');
const listenerPath = path.join(parserPath, path.dirname(grammar), lang + 'Listener.js');
const hasListener = await fs.promises.exists(listenerPath);
if (!hasListener) {
listenerPath = path.join(parserPath, path.dirname(grammar), lang + 'ParserListener.js');
}
const codeCell = `
import antlr4 from 'antlr4';
import lexer from '${lexerPath}';
import parser from '${parserPath}';
${hasListener? 'import listener from \'' + listenerPath + '\'' : ''}
export default { antlr4, lexer, parser${hasListener? ', listener' : ''} }
`;
const module = await importESModule(codeCell, __filename + '', global);
return module;
}
}
return {};
} catch (error) {
console.error(`Error getting parser for language ${language}:`, error);
return {};
}
}
await initializeGrammars();
export default getParser;
Code Breakdown
This code is used to parse a directory structure for grammar files and extract language information. It appears to be designed for a parser generator tool, likely ANTLR.
The code assumes the following directory structure:
Resources/
Parsers/
Language1/
Language1.g4
Language1Lexer.js
Language1Parser.js
Language1Listener.js
Language2/
Language2.g4
Language2Lexer.js
Language2Parser.js
Language2Listener.js
...
findGrammars(directory)
This function recursively traverses the directory structure and extracts language information from grammar files (*.g4
).
LANGUAGES
array.findGrammars(directory)
recursively.GRAMMARS
array.getParser(language)
This function searches for the parser files corresponding to the given language.
GRAMMARS
array and checks if any grammar file path matches the given language.path
module.The code first reads the top-level Parsers
directory and calls findGrammars(directory)
for each subdirectory. Then, it calls getParser(language)
for each language in the LANGUAGES
array.