Skip to content

Commit

Permalink
Merge pull request #29 from WebFreak001/master
Browse files Browse the repository at this point in the history
  • Loading branch information
s-ludwig authored Jul 24, 2017
2 parents 903970e + 1954122 commit 132b1a9
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
2 changes: 1 addition & 1 deletion SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ A tag consists of the following parts, which, if present, must occur in the list

- **Attribute list**

List of attributes of the form `(att1=value, att2)`. An attribute must be a valid *identifier*. The value part can take any of the following forms:
List of attributes of the form `(att1=value, att2)`. Attributes can have new lines but the children must still be indented as usual. An attribute must be a valid *identifier*. The value part can take any of the following forms:

- Valid D expression
- String literal with double-quotes, which may contain *interpolations*
Expand Down
32 changes: 23 additions & 9 deletions source/diet/parser.d
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,18 @@ unittest { // test basic functionality
])
]);

// multiline attribute expression
assert(parseDiet("foo(\n\tatt=1+2,\n\tfoo=bar\n)").nodes == [
new Node(ln(0), "foo", [
Attribute(ln(0), "att", [
AttributeContent.interpolation(`1+2`),
]),
Attribute(ln(0), "foo", [
AttributeContent.interpolation(`bar`),
])
])
]);

// special nodes
assert(parseDiet("//comment").nodes == [
new Node(ln(0), Node.SpecialName.comment, null, [NodeContent.text("comment", ln(0))], NodeAttribs.rawTextNode)
Expand Down Expand Up @@ -1239,16 +1251,16 @@ private void parseAttributes(ref string input, ref size_t i, ref Node node, in r
assert(i < input.length && input[i] == '(');
i++;

skipWhitespace(input, i);
skipAnyWhitespace(input, i);
while (i < input.length && input[i] != ')') {
string name = parseIdent(input, i, ",)=", loc);
string value;
skipWhitespace(input, i);
skipAnyWhitespace(input, i);
if( i < input.length && input[i] == '=' ){
i++;
skipWhitespace(input, i);
skipAnyWhitespace(input, i);
enforcep(i < input.length, "'=' must be followed by attribute string.", loc);
value = skipExpression(input, i, loc);
value = skipExpression(input, i, loc, true);
assert(i <= input.length);
if (isStringLiteral(value) && value[0] == '\'') {
auto tmp = dstringUnescape(value[1 .. $-1]);
Expand All @@ -1260,7 +1272,7 @@ private void parseAttributes(ref string input, ref size_t i, ref Node node, in r
enforcep(input[i] == ')' || input[i] == ',', "Unexpected text following attribute: '"~input[0..i]~"' ('"~input[i..$]~"')", loc);
if (input[i] == ',') {
i++;
skipWhitespace(input, i);
skipAnyWhitespace(input, i);
}

if (name == "class" && value == `""`) continue;
Expand Down Expand Up @@ -1388,11 +1400,13 @@ private string skipIndent(ref string input)

private bool isIndentChar(dchar ch) { return ch == ' ' || ch == '\t'; }

private string skipWhitespace(in ref string s, ref size_t idx)
private string skipAnyWhitespace(in ref string s, ref size_t idx)
{
import std.ascii : isWhite;

size_t start = idx;
while (idx < s.length) {
if (s[idx] == ' ') idx++;
if (s[idx].isWhite) idx++;
else break;
}
return s[start .. idx];
Expand Down Expand Up @@ -1454,7 +1468,7 @@ unittest {
assert(!isStringLiteral(`"name" value="#{name}"`));
}

private string skipExpression(in ref string s, ref size_t idx, in ref Location loc)
private string skipExpression(in ref string s, ref size_t idx, in ref Location loc, bool multiline = false)
{
string clamp_stack;
size_t start = idx;
Expand All @@ -1463,7 +1477,7 @@ private string skipExpression(in ref string s, ref size_t idx, in ref Location l
switch (s[idx]) {
default: break;
case '\n', '\r':
enforcep(false, "Unexpected end of line.", loc);
enforcep(multiline, "Unexpected end of line.", loc);
break;
case ',':
if (clamp_stack.length == 0)
Expand Down

0 comments on commit 132b1a9

Please sign in to comment.