Parse gathers
This commit is contained in:
@@ -25,4 +25,7 @@ var test2 = 5;
|
||||
|
||||
```
|
||||
, Output "this"
|
||||
```
|
||||
```
|
||||
|
||||
- no label gather on an output
|
||||
--(labeled) deep gather
|
||||
@@ -254,11 +254,16 @@ class HankBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
public function take(chars: Int) {
|
||||
public function peek(chars: Int) {
|
||||
if (cleanBuffer.length < chars) {
|
||||
throw 'Not enough characters left in buffer.';
|
||||
}
|
||||
var data = cleanBuffer.substr(0, chars);
|
||||
return data;
|
||||
}
|
||||
|
||||
public function take(chars: Int) {
|
||||
var data = peek(chars);
|
||||
drop(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package hank;
|
||||
|
||||
using Extensions.OptionExtender;
|
||||
import haxe.ds.Option;
|
||||
|
||||
enum ExprType {
|
||||
EIncludeFile(path: String);
|
||||
@@ -14,6 +15,7 @@ enum ExprType {
|
||||
EHaxeLine(haxe: String);
|
||||
|
||||
EHaxeBlock(haxe: String);
|
||||
EGather(label: Option<String>, depth: Int, expr: ExprType);
|
||||
}
|
||||
|
||||
typedef HankExpr = {
|
||||
@@ -28,14 +30,15 @@ typedef HankAST = Array<HankExpr>;
|
||||
**/
|
||||
@:allow(tests.ParserTest)
|
||||
class Parser {
|
||||
var symbols = [
|
||||
'INCLUDE ' => include,
|
||||
'->' => divert,
|
||||
'===' => knot,
|
||||
'==' => knot,
|
||||
'=' => stitch,
|
||||
'~' => haxeLine,
|
||||
'```' => haxeBlock
|
||||
static var symbols: Array<Map<String, HankBuffer -> HankBuffer.Position -> ExprType>> = [
|
||||
['INCLUDE ' => include],
|
||||
['->' => divert],
|
||||
['===' => knot],
|
||||
['==' => knot],
|
||||
['=' => stitch],
|
||||
['~' => haxeLine],
|
||||
['```' => haxeBlock],
|
||||
['-' => gather]
|
||||
];
|
||||
|
||||
var buffers: Array<HankBuffer> = [];
|
||||
@@ -86,7 +89,7 @@ class Parser {
|
||||
return parsedAST;
|
||||
}
|
||||
|
||||
function parseExpr(buffer: HankBuffer, position: HankBuffer.Position) : ExprType {
|
||||
static function parseExpr(buffer: HankBuffer, position: HankBuffer.Position) : ExprType {
|
||||
var line = buffer.peekLine();
|
||||
switch (line) {
|
||||
case None:
|
||||
@@ -96,13 +99,15 @@ class Parser {
|
||||
return ENoOp;
|
||||
}
|
||||
|
||||
for (symbol in symbols.keys()) {
|
||||
for (rule in symbols) {
|
||||
var symbol = rule.keys().next();
|
||||
var rule = rule[symbol];
|
||||
if (StringTools.startsWith(line, symbol)) {
|
||||
return symbols[symbol](buffer, position);
|
||||
return rule(buffer, position);
|
||||
}
|
||||
}
|
||||
|
||||
return output(buffers[0], position);
|
||||
return output(buffer, position);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,6 +161,27 @@ class Parser {
|
||||
return EHaxeLine(buffer.takeLine('lr').unwrap());
|
||||
}
|
||||
|
||||
static function gather(buffer: HankBuffer, position: HankBuffer.Position) : ExprType {
|
||||
var depth = 0;
|
||||
var c = '';
|
||||
do {
|
||||
c = buffer.peek(1);
|
||||
if (c == '-') {
|
||||
buffer.take(1);
|
||||
depth += 1;
|
||||
}
|
||||
} while (c == '-');
|
||||
buffer.skipWhitespace();
|
||||
var label = if (buffer.peek(1) == '(') {
|
||||
var text = buffer.takeUntil([')'], true).unwrap().output.substr(1);
|
||||
buffer.skipWhitespace();
|
||||
Some(text);
|
||||
} else {
|
||||
None;
|
||||
};
|
||||
return EGather(label, depth, parseExpr(buffer, buffer.position()));
|
||||
}
|
||||
|
||||
static function haxeBlock(buffer: HankBuffer, position: HankBuffer.Position): ExprType {
|
||||
buffer.drop('```');
|
||||
var rawContents = buffer.takeUntil(['```'], false, true).unwrap().output;
|
||||
|
||||
@@ -101,5 +101,7 @@ class ParserTest extends utest.Test {
|
||||
assertNextExpr(EHaxeBlock("var haxeVar = 'test';var test2 = 5;"));
|
||||
assertNextExpr(EHaxeBlock('story.runEmbeddedHank("Output this");'));
|
||||
assertNextExpr(EHaxeBlock('story.runEmbeddedHank("Output \\"this\\"");'));
|
||||
assertNextExpr(EGather(None, 1, EOutput(new Output([Text("no label gather on an output")]))));
|
||||
assertNextExpr(EGather(Some('labeled'), 2, EOutput(new Output([Text("deep gather")]))));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user