Plain Markdown support. Directory support.
* Upgraded build common to version 1.9. * Updated the release target in build.xml to take advantage of the new features of common build 1.9. The release target now copies over the libs and release resources. * JLPMain now recognises directories in it's input list. It will add all the files in a given directory to the input list (including files in abitrarily nested subdirectories). * Abstracted the parser behavior further. Processor no longer needs to know about Parboiled ParseRunners and can use non-Parboiled parsers. * Created the JLPParser interface to support the new parser abstraction. * JLPPegParser implements the new interface trivially by creating it's own parse runner and calling it with the input given. * Added MarkdownParser, which does not actually parse the file, just creates the bare-bones SourceFile object needed for the generator to emit the Markdown contents.
This commit is contained in:
parent
9eb80e91a6
commit
1f9b6cc66d
11
build.xml
11
build.xml
@ -1,13 +1,20 @@
|
|||||||
<project name="Jonathan's Literate Programming" basedir="." default="release">
|
<project name="Jonathan's Literate Programming" basedir="." default="release">
|
||||||
|
|
||||||
<import file="jdb-build-1.6.xml"/>
|
<import file="jdb-build-1.9.xml"/>
|
||||||
<property environment="env"/>
|
<property environment="env"/>
|
||||||
<property file="project.properties"/>
|
<property file="project.properties"/>
|
||||||
|
|
||||||
<target name="release" depends="build">
|
<target name="release" depends="build">
|
||||||
|
<mkdir dir="${release.dir}/lib"/>
|
||||||
<copy file="${build.dir}/${name}-${version}.${build.number}.jar"
|
<copy file="${build.dir}/${name}-${version}.${build.number}.jar"
|
||||||
tofile="${release.dir}/${name}-${version}.jar"/>
|
tofile="${release.dir}/${name}-${version}.jar"/>
|
||||||
<copy file="${basedir}/jlp" todir="${release.dir}"/>
|
<copy todir="${release.dir}">
|
||||||
|
<fileset dir="${resources.dir}/release"/>
|
||||||
|
</copy>
|
||||||
|
<copy todir="${release.dir}/lib">
|
||||||
|
<fileset dir="${build.dir}/lib/runtime/jar"/>
|
||||||
|
</copy>
|
||||||
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<project name="Jonathan Bernard Build Common">
|
<project name="Jonathan Bernard Build Common"
|
||||||
|
xmlns:ivy="antlib:org.apache.ivy.ant">
|
||||||
|
|
||||||
<property environment="env"/>
|
<property environment="env"/>
|
||||||
|
|
||||||
@ -16,6 +17,7 @@
|
|||||||
<property name="build.dir" value="${basedir}/build"/>
|
<property name="build.dir" value="${basedir}/build"/>
|
||||||
<property name="lib.dir" value="${basedir}/lib"/>
|
<property name="lib.dir" value="${basedir}/lib"/>
|
||||||
<property name="resources.dir" value="${basedir}/resources"/>
|
<property name="resources.dir" value="${basedir}/resources"/>
|
||||||
|
<property name="splash.image" value="splash.png"/>
|
||||||
|
|
||||||
<!--======== PATHS ========-->
|
<!--======== PATHS ========-->
|
||||||
<path id="groovy.classpath">
|
<path id="groovy.classpath">
|
||||||
@ -59,9 +61,25 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!--======== LIBRARY TARGETS ========-->
|
<!--======== LIBRARY TARGETS ========-->
|
||||||
<target name="lib" depends="-lib-local,-lib-ivy"/>
|
<target name="-lib" depends="-lib-local,-lib-ivy,lib"/>
|
||||||
|
|
||||||
|
<target name="lib"/>
|
||||||
|
|
||||||
<target name="-lib-ivy" unless="${lib.local}"/>
|
<target name="-init-ivy">
|
||||||
|
<ivy:settings id="ivy.settings" file="ivysettings.xml"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="-lib-ivy" depends="-init-ivy" unless="${lib.local}">
|
||||||
|
<ivy:retrieve settingsRef="ivy.settings"
|
||||||
|
pattern="${lib.dir}/[conf]/[type]/[artifact]-[revision].[ext]"
|
||||||
|
conf="compile,runtime"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="-lib-groovy" if="${lib.local}">
|
||||||
|
<copy todir="${build.dir}/lib/runtime/jar">
|
||||||
|
<fileset dir="${env.GROOVY_HOME}/embeddable"/>
|
||||||
|
</copy>
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="-lib-local" if="${lib.local}">
|
<target name="-lib-local" if="${lib.local}">
|
||||||
<echo message="Resolving libraries locally."/>
|
<echo message="Resolving libraries locally."/>
|
||||||
@ -96,7 +114,7 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!--======== COMPILATION TARGETS ========-->
|
<!--======== COMPILATION TARGETS ========-->
|
||||||
<target name="-compile-groovy" depends="-init,-init-groovy,lib">
|
<target name="-compile-groovy" depends="-init,-init-groovy,-lib,-lib-groovy">
|
||||||
<mkdir dir="${build.dir}/main/classes"/>
|
<mkdir dir="${build.dir}/main/classes"/>
|
||||||
<groovyc srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
|
<groovyc srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
|
||||||
includeAntRuntime="false">
|
includeAntRuntime="false">
|
||||||
@ -109,7 +127,7 @@
|
|||||||
</groovyc>
|
</groovyc>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="-compile-java" depends="-init,lib">
|
<target name="-compile-java" depends="-init,-lib">
|
||||||
<mkdir dir="${build.dir}/main/classes"/>
|
<mkdir dir="${build.dir}/main/classes"/>
|
||||||
<javac srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
|
<javac srcdir="${src.dir}/main" destdir="${build.dir}/main/classes"
|
||||||
includeAntRuntime="false" classpathref="compile-libs"/>
|
includeAntRuntime="false" classpathref="compile-libs"/>
|
||||||
@ -178,13 +196,42 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!--======== BUILD TARGETS ========-->
|
<!--======== BUILD TARGETS ========-->
|
||||||
<target name="-build-modular"
|
<target name="-build-modular-lib" unless="executable.jar"
|
||||||
depends="compile,increment-build-number,resources">
|
depends="compile,increment-build-number,resources">
|
||||||
|
|
||||||
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
|
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
|
||||||
basedir="${build.dir}/main/classes"/>
|
basedir="${build.dir}/main/classes"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="-build-modular-executable" if="executable.jar"
|
||||||
|
depends="compile,increment-build-number,resources">
|
||||||
|
|
||||||
|
<pathconvert property="jar.classpath" pathsep=" " refid="runtime-libs">
|
||||||
|
<mapper>
|
||||||
|
<chainedmapper>
|
||||||
|
<!-- remove absolute path -->
|
||||||
|
<flattenmapper />
|
||||||
|
|
||||||
|
<!-- add lib/ prefix -->
|
||||||
|
<globmapper from="*" to="lib/*" />
|
||||||
|
</chainedmapper>
|
||||||
|
</mapper>
|
||||||
|
</pathconvert>
|
||||||
|
|
||||||
|
<jar destfile="${build.dir}/${name}-${version}.${build.number}.jar"
|
||||||
|
basedir="${build.dir}/main/classes">
|
||||||
|
|
||||||
|
<manifest>
|
||||||
|
<attribute name="Main-Class" value="${main.class}"/>
|
||||||
|
<attribute name="Class-Path" value="${jar.classpath}"/>
|
||||||
|
<attribute name="SplashScreen-Image" value="${splash.image}"/>
|
||||||
|
</manifest>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="-build-modular"
|
||||||
|
depends="-build-modular-lib,-build-modular-executable"/>
|
||||||
|
|
||||||
<target name="-build-packed-libs"
|
<target name="-build-packed-libs"
|
||||||
depends="compile,increment-build-number,resources">
|
depends="compile,increment-build-number,resources">
|
||||||
|
|
@ -1,6 +1,8 @@
|
|||||||
#Sun, 25 Dec 2011 21:56:17 -0600
|
#Sun, 25 Dec 2011 23:07:02 -0600
|
||||||
name=jlp
|
name=jlp
|
||||||
version=1.0
|
version=1.1
|
||||||
build.number=0
|
build.number=6
|
||||||
lib.local=true
|
lib.local=true
|
||||||
release.dir=release
|
release.dir=release
|
||||||
|
main.class=com.jdblabs.jlp.JLPMain
|
||||||
|
executable.jar=true
|
||||||
|
@ -73,19 +73,27 @@ public class JLPMain {
|
|||||||
|
|
||||||
// get files passed in
|
// get files passed in
|
||||||
def filenames = opts.getArgs()
|
def filenames = opts.getArgs()
|
||||||
def inputFiles = (filenames.collect { filename ->
|
def inputFiles = []
|
||||||
|
|
||||||
|
filenames.each { filename ->
|
||||||
// create a File object
|
// create a File object
|
||||||
File file = new File(filename)
|
File file = new File(filename)
|
||||||
|
|
||||||
// if this is a relative path, resolve it against our path root
|
// if this is a relative path, resolve it against our path root
|
||||||
if (!file.isAbsolute()) { file = new File(pathRoot, filename) }
|
if (!file.isAbsolute()) { file = new File(pathRoot, filename) }
|
||||||
|
|
||||||
// warn the user about files that do not exist
|
|
||||||
if (!file.exists()) {
|
|
||||||
System.err.println
|
|
||||||
"'${file.canonicalPath}' does not exist: ignored." }
|
|
||||||
|
|
||||||
return file }).findAll { it.exists() }
|
// if this file does not exist, warn the user and skip it
|
||||||
|
if (!file.exists()) {
|
||||||
|
System.err.println(
|
||||||
|
"'${file.canonicalPath}' does not exist: ignored.")
|
||||||
|
return }
|
||||||
|
|
||||||
|
// if this file is a directory, add all the files in it (recurse
|
||||||
|
// into sub-directories and add their contents as well).
|
||||||
|
if (file.isDirectory()) { file.eachFileRecurse {
|
||||||
|
if (it.isFile()) { inputFiles << it }}}
|
||||||
|
|
||||||
|
else { inputFiles << file } }
|
||||||
|
|
||||||
Processor.process(outputDir, css, inputFiles)
|
Processor.process(outputDir, css, inputFiles)
|
||||||
}
|
}
|
||||||
|
6
src/main/com/jdblabs/jlp/JLPParser.java
Normal file
6
src/main/com/jdblabs/jlp/JLPParser.java
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package com.jdblabs.jlp;
|
||||||
|
|
||||||
|
import com.jdblabs.jlp.ast.SourceFile;
|
||||||
|
|
||||||
|
public interface JLPParser {
|
||||||
|
public SourceFile parse(String input); }
|
@ -8,9 +8,10 @@ import org.parboiled.BaseParser;
|
|||||||
import org.parboiled.Context;
|
import org.parboiled.Context;
|
||||||
import org.parboiled.Rule;
|
import org.parboiled.Rule;
|
||||||
import org.parboiled.annotations.*;
|
import org.parboiled.annotations.*;
|
||||||
|
import org.parboiled.parserunners.ReportingParseRunner;
|
||||||
|
|
||||||
@BuildParseTree
|
@BuildParseTree
|
||||||
public class JLPPegParser extends BaseParser<Object> {
|
public class JLPPegParser extends BaseParser<Object> implements JLPParser {
|
||||||
|
|
||||||
int curLineNum = 1;
|
int curLineNum = 1;
|
||||||
|
|
||||||
@ -31,6 +32,10 @@ public class JLPPegParser extends BaseParser<Object> {
|
|||||||
public JLPPegParser() {
|
public JLPPegParser() {
|
||||||
this("/**", "*/", "!#$%^&*()_-=+|;:'\",<>?~`", "///"); }
|
this("/**", "*/", "!#$%^&*()_-=+|;:'\",<>?~`", "///"); }
|
||||||
|
|
||||||
|
public SourceFile parse(String input) {
|
||||||
|
ReportingParseRunner rpr = new ReportingParseRunner(this.SourceFile());
|
||||||
|
return (SourceFile) rpr.run(input).resultValue; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the rule:
|
* Parses the rule:
|
||||||
* SourceFile = (Block / DocBlock / CodeBlock)+
|
* SourceFile = (Block / DocBlock / CodeBlock)+
|
||||||
|
20
src/main/com/jdblabs/jlp/MarkdownParser.groovy
Normal file
20
src/main/com/jdblabs/jlp/MarkdownParser.groovy
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.jdblabs.jlp
|
||||||
|
|
||||||
|
import com.jdblabs.jlp.ast.*
|
||||||
|
|
||||||
|
public class MarkdownParser implements JLPParser {
|
||||||
|
|
||||||
|
public SourceFile parse(String input) {
|
||||||
|
|
||||||
|
def sourceFile = new SourceFile()
|
||||||
|
def block
|
||||||
|
def docBlock = new DocBlock(0)
|
||||||
|
def codeBlock = new CodeBlock(0)
|
||||||
|
def docText = new DocText(0)
|
||||||
|
|
||||||
|
docText.value = input
|
||||||
|
docBlock.docTexts << docText
|
||||||
|
block = new Block(codeBlock, docBlock, 0)
|
||||||
|
sourceFile.blocks << block
|
||||||
|
|
||||||
|
return sourceFile }}
|
@ -2,7 +2,6 @@ package com.jdblabs.jlp
|
|||||||
|
|
||||||
import org.parboiled.BaseParser
|
import org.parboiled.BaseParser
|
||||||
import org.parboiled.Parboiled
|
import org.parboiled.Parboiled
|
||||||
import org.parboiled.parserunners.ReportingParseRunner
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processor processes one batch of input files to create a set of output files.
|
* Processor processes one batch of input files to create a set of output files.
|
||||||
@ -22,7 +21,7 @@ public class Processor {
|
|||||||
// shortcut for docs[currentDocId]
|
// shortcut for docs[currentDocId]
|
||||||
public TargetDoc currentDoc
|
public TargetDoc currentDoc
|
||||||
|
|
||||||
protected Map<String, BaseParser> parsers = [:]
|
protected Map<String, JLPParser> parsers = [:]
|
||||||
protected Map<String, JLPBaseGenerator> generators = [:]
|
protected Map<String, JLPBaseGenerator> generators = [:]
|
||||||
|
|
||||||
public static void process(File outputDir, String css,
|
public static void process(File outputDir, String css,
|
||||||
@ -61,11 +60,9 @@ public class Processor {
|
|||||||
// TODO: add logic to configure or autodetect the correct parser for
|
// TODO: add logic to configure or autodetect the correct parser for
|
||||||
// each file
|
// each file
|
||||||
def parser = getParser(sourceTypeForFile(currentDoc.sourceFile))
|
def parser = getParser(sourceTypeForFile(currentDoc.sourceFile))
|
||||||
def parseRunner = new ReportingParseRunner(parser.SourceFile())
|
|
||||||
|
|
||||||
// TODO: error detection
|
// TODO: error detection
|
||||||
currentDoc.sourceAST = parseRunner.run(
|
currentDoc.sourceAST = parser.parse(currentDoc.sourceFile.text) }
|
||||||
currentDoc.sourceFile.text).resultValue }
|
|
||||||
|
|
||||||
// run our generator parse phase (first pass over the ASTs)
|
// run our generator parse phase (first pass over the ASTs)
|
||||||
processDocs {
|
processDocs {
|
||||||
@ -175,6 +172,7 @@ public class Processor {
|
|||||||
case 'groovy': return 'groovy';
|
case 'groovy': return 'groovy';
|
||||||
case 'java': return 'java';
|
case 'java': return 'java';
|
||||||
case 'js': return 'javascript';
|
case 'js': return 'javascript';
|
||||||
|
case 'md': return 'markdown';
|
||||||
default: return 'unknown'; }}
|
default: return 'unknown'; }}
|
||||||
|
|
||||||
protected getGenerator(String sourceType) {
|
protected getGenerator(String sourceType) {
|
||||||
@ -187,13 +185,14 @@ public class Processor {
|
|||||||
return generators[sourceType] }
|
return generators[sourceType] }
|
||||||
|
|
||||||
protected getParser(String sourceType) {
|
protected getParser(String sourceType) {
|
||||||
println "Looking for a ${sourceType} parser."
|
|
||||||
if (parsers[sourceType] == null) {
|
if (parsers[sourceType] == null) {
|
||||||
switch(sourceType) {
|
switch(sourceType) {
|
||||||
case 'erlang':
|
case 'erlang':
|
||||||
parsers[sourceType] = Parboiled.createParser(
|
parsers[sourceType] = Parboiled.createParser(
|
||||||
JLPPegParser, '%%')
|
JLPPegParser, '%%')
|
||||||
println "Built an erlang parser."
|
break
|
||||||
|
case 'markdown':
|
||||||
|
parsers[sourceType] = new MarkdownParser()
|
||||||
break
|
break
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'c++':
|
case 'c++':
|
||||||
@ -203,7 +202,6 @@ public class Processor {
|
|||||||
default:
|
default:
|
||||||
parsers[sourceType] = Parboiled.createParser(JLPPegParser,
|
parsers[sourceType] = Parboiled.createParser(JLPPegParser,
|
||||||
'/**', '*/', '!#$%^&*()_-=+|;:\'",<>?~`', '///')
|
'/**', '*/', '!#$%^&*()_-=+|;:\'",<>?~`', '///')
|
||||||
println "Built a java parser."
|
|
||||||
break }}
|
break }}
|
||||||
|
|
||||||
return parsers[sourceType] }
|
return parsers[sourceType] }
|
||||||
|
Loading…
Reference in New Issue
Block a user