Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions d/pqmarkup-lite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.dub
docs.json
__dummy.html
docs/
/pqmarkup-lite
pqmarkup-lite.so
pqmarkup-lite.dylib
pqmarkup-lite.dll
pqmarkup-lite.a
pqmarkup-lite.lib
pqmarkup-lite-test-*
*.exe
*.o
*.obj
*.lst
3 changes: 3 additions & 0 deletions d/pqmarkup-lite/dub.sdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name "pqmarkup-lite"
authors "Bradley Chatha"
dependency "jcli" version="~>0.12.1"
8 changes: 8 additions & 0 deletions d/pqmarkup-lite/dub.selections.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"fileVersion": 1,
"versions": {
"jcli": "0.12.1",
"jioc": "0.2.0",
"silly": "1.0.2"
}
}
101 changes: 101 additions & 0 deletions d/pqmarkup-lite/source/app.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module app;

import std : Nullable;
import jcli : CommandDefault, CommandPositionalArg, CommandNamedArg, Result, CommandHelpText, CommandParser;
import lexer, syntax;

@CommandDefault
struct Options
{
@CommandPositionalArg(0, "file", "The markup file to use.")
string file;

@CommandNamedArg("t|is-test", "Specified if the provided file is a test file.")
Nullable!bool isTestFile;
}

struct TestCase
{
string input;
string output;
}

int main(string[] args)
{
import std : readText, writeln;

auto optionsResult = getOptions(args);
if(optionsResult.isFailure)
return -1;

const options = optionsResult.asSuccess.value;
const text = readText(options.file);

if(options.isTestFile.get(false))
{
auto result = getTestCases(text);
if(result.isFailure)
{
import std : writeln;
writeln("error: ", result.asFailure.error);
return -1;
}

foreach(test; result.asSuccess.value)
{
import std;
auto lexer = Lexer(test.input);

// DEBUG
auto ast = syntax.parse(lexer);
writeln(*ast);
writeln();
}
}
return 0;
}

Result!Options getOptions(string[] args)
{
import std : writeln;

CommandParser!Options parser;
Options options;

auto result = parser.parse(args[1..$], /*ref*/options);

if(!result.isSuccess)
{
CommandHelpText!Options help;
writeln(help.toString("pqmarkup-lite"));
return typeof(return).failure("");
}

return typeof(return).success(options);
}

Result!(TestCase[]) getTestCases(string text)
{
import std : splitter, filter, all, array, map, countUntil, byCodeUnit, until;
import std.ascii : isWhite; // dunno why, but I have to do this one separately for it to wkr.

const DELIM = " (()) ";
auto cases =
text.splitter('|')
.map!((split)
{
if(split.all!isWhite)
return null;

const delimStart = split.byCodeUnit.countUntil(DELIM);
if(delimStart < 0)
return null;
return [split[0..delimStart+1], split[delimStart+DELIM.length..$]];
})
.filter!(splits => splits !is null)
.map!(splits => TestCase(splits[0], splits[1]))
.until!(test => test.input == "@ ") // Allow myself to limit test cases until I've worked on the code to parse them
.array;

return typeof(return).success(cases);
}
132 changes: 132 additions & 0 deletions d/pqmarkup-lite/source/ast.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
module ast;

import std.sumtype;
import tokens;

alias AstNodeT = SumType!(
AstRoot,
AstString,
AstText,
AstHeader,
AstLink,
AstAbbr,
AstJunk,
AstWhiteSpace,
AstStyle,
AstNewLine,
AstInconclusive,
AstDot,
AstNumber,
AstBlock,
AstLinkRef,
AstListItem,
AstCode,
);

struct AstNode
{
import std.array : Appender;
import std.range : repeat, take;

AstNode* parent;
AstNodeT value;
AstNode*[] children;

this(ValueT)(AstNode* p, ValueT v, AstNode*[] c = null)
{
if(p)
p.addChild(&this);
this.value = AstNodeT(v);
this.children = c;
}

void addChild(AstNode* child)
{
import std.algorithm : remove;

if(child.parent)
child.parent.children = child.parent.children.remove!(i => i is child);

this.children ~= child;
child.parent = &this;
}

string toString()
{
import std.exception : assumeUnique;

Appender!(char[]) output;
this.toString(0, output);
return output.data.assumeUnique;
}

void toString(size_t indent, ref Appender!(char[]) output)
{
import std.conv : to;

output.put(repeat(' ').take(indent * 4));
output.put(this.value.to!string());
output.put('\n');
foreach(child; this.children)
child.toString(indent + 1, output);
}
}

struct AstRoot{}
struct AstString {}
struct AstText
{
string text;
}
struct AstHeader
{
int size;
bool isNegative;
}
struct AstLink
{
AstNode* textNode;
string href;
bool isLocalLink;
}
struct AstAbbr
{
AstNode* textNode;
AstNode* titleNode;
}
struct AstDot{}
struct AstWhiteSpace{}
struct AstNewLine{}
struct AstInconclusive
{
AstNode* textNode;
}
struct AstJunk
{
string text;
string message;
}
struct AstStyle
{
StringStyle style;
}
struct AstNumber
{
int value;
}
struct AstLinkRef
{
AstNode* textNode;
int value;
}
struct AstBlock
{
BlockType type;
}
struct AstListItem
{
}
struct AstCode
{
string text;
}
Loading