Skip to content

Commit

Permalink
Initial working commit
Browse files Browse the repository at this point in the history
  • Loading branch information
b-fuze committed Jun 26, 2019
0 parents commit cc39469
Show file tree
Hide file tree
Showing 9 changed files with 1,289 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
111 changes: 111 additions & 0 deletions don.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#! /usr/bin/env node

const { parse } = require("./parse.js")
const { readFileSync } = require("fs")
const path = require("path")

const file = process.argv[2]
const src = readFileSync(file, "utf8")

function checkDependencyReferences(donTree) {
const undefinedDependencies = [
// {
// target: "target",
// dependency: "dep",
// }
]

for (const [target, commands] of Object.entries(donTree)) {
for (const command of commands) {
if (command.type === "dependency") {
for (const dep of command.dependencies) {
if (!donTree.hasOwnProperty(dep)) {
undefinedDependencies.push({
target,
dependency: dep,
})
}
}
}
}
}

return undefinedDependencies
}

function checkCircular(donTree, target, commands, stack = new Set()) {
let commandNum = 0

for (const command of commands) {
commandNum++

if (command.type === "dependency") {
for (const depName of command.dependencies) {
let depDepth = stack.size
const dependencyStack = new Set(stack)

dependencyStack.add(depName)

if (dependencyStack.size === depDepth + 1) {
// No circular reference for this dep, check further dependencies
return checkCircular(donTree, target, donTree[depName], dependencyStack)
} else {
// Found circular reference
return {
target,
via: Array.from(dependencyStack).slice(-1)[0],
dependency: depName,
commandNumber: commandNum,
}
}
}
}
}

return null
}

const absFile = path.resolve(__dirname, file)

try {
const parsed = parse(src)

// Check for undefined dependencies
let undefinedDependencies = checkDependencyReferences(parsed)

if (undefinedDependencies.length) {
console.error(absFile + "\nError:\n")

for (const undep of undefinedDependencies) {
console.error(` Target "${ undep.target }" references undefined dependency "${ undep.dependency }"`)
}

process.exit(1)
}

let circularDeps = []

for (const [target, commands] of Object.entries(parsed)) {
const targetCircularDeps = checkCircular(parsed, target, commands, new Set([target]))

if (targetCircularDeps) {
circularDeps.push(targetCircularDeps)
}
}

if (circularDeps.length) {
console.error(absFile + "\nError:")

for (const cirdep of circularDeps) {
console.error(` Target "${ cirdep.target }" has circular dependency "${ cirdep.dependency }" via its dependency "${ cirdep.via }" on command ${ cirdep.commandNumber }`)
}

process.exit(1)
}

console.log(JSON.stringify(parsed, null, 4))
} catch(e) {
const loc = e.location.start
console.error(`${ absFile }:${ loc.line }:${ loc.column }\n${ e.name }: ${ e.message }`)
}

77 changes: 77 additions & 0 deletions don.pegjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
function text_val(array) {
return typeof array === "string" ? array : array.flat().join("")
}
}

start
= targets_arr:( tgt:target nl { return tgt } ) + {
const targets = {}

for (const target of targets_arr) {
targets[target.name] = target.commands
}

return targets
}

target
= tn:target_name ":" is nl
commands:( ( command / command_dependency ) + ) { return { name: tn, commands } }

command
= main_ci:command_indent "- " ! ( "$" target_name ) cs:command_string nl
multil_str:( multil_ci:command_indent ! "- " multil_cs:command_string nl {
if (multil_ci === main_ci + " ") {
const multiline_begin = multil_cs.slice(0, 2)

if (multiline_begin !== "- " && multiline_begin !== "-") {
return " " + multil_cs
} else {
return expected("Multi line commands can't start with a single hyphen, consider quoting the single hyphen")
}
} else {
return expected("multi-line indent matching first line of command")
}
}
) * {
return {
type: "command",
command: text_val(cs) + text_val(multil_str),
}
}

command_dependency
= main_ci:command_indent "- " cs:dependency_string nl {
return {
type: "dependency",
dependencies: cs,
}
}

command_indent
= " " " " * { return text() }

target_name
= [a-z0-9_-]i + { return text() }

command_string
= [^\n] + { return text() }

dependency_string
= "$" name:target_name is right:dependency_string { return [name].concat(right) }
/ "$" name:target_name is { return [name] }

// Inline space
is
= " " * { return text() }

// White space
ws
= [ \n] + { return text() }

// Newline
nl
= "\n"
/ "\r\n"

14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "don",
"version": "1.0.0",
"description": "Make and YAML inspired build tool",
"main": "don.js",
"scripts": {
"test": "node ./don.js test.don",
"build": "pegjs -o parse.js don.pegjs"
},
"keywords": [
"build",
"tool",
"javascript"
],
"author": "b-fuze",
"license": "MIT",
"devDependencies": {
"pegjs": "^0.10.0"
}
}
Loading

0 comments on commit cc39469

Please sign in to comment.