Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Unified Diff: utils/pub/yaml/parser.dart

Issue 10377186: Support a much larger subset of YAML. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: New chunks I guess Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: utils/pub/yaml/parser.dart
diff --git a/utils/pub/yaml/parser.dart b/utils/pub/yaml/parser.dart
index 78a0787f7d7c2f4b75e9d40ee9682fa021f5ac6c..dcd1e70b8d59a782e2cc2a5447a3513e27e13332 100644
--- a/utils/pub/yaml/parser.dart
+++ b/utils/pub/yaml/parser.dart
@@ -24,6 +24,7 @@ class _Parser {
static final SP = 0x20;
static final TILDE = 0x7E;
static final NEL = 0x85;
+ static final PLUS = 0x2B;
static final HYPHEN = 0x2D;
static final QUESTION_MARK = 0x3F;
static final COLON = 0x3A;
@@ -50,11 +51,35 @@ class _Parser {
static final VERTICAL_TAB = 0xB;
static final FORM_FEED = 0xC;
static final ESCAPE = 0x1B;
+ static final SLASH = 0x2F;
static final BACKSLASH = 0x5C;
+ static final UNDERSCORE = 0x5F;
static final NBSP = 0xA0;
static final LINE_SEPARATOR = 0x2028;
static final PARAGRAPH_SEPARATOR = 0x2029;
+ static final NUMBER_0 = 0x30;
+ static final NUMBER_9 = 0x39;
+
+ static final LETTER_A = 0x61;
+ static final LETTER_B = 0x62;
+ static final LETTER_E = 0x65;
+ static final LETTER_F = 0x66;
+ static final LETTER_N = 0x6E;
+ static final LETTER_R = 0x72;
+ static final LETTER_T = 0x74;
+ static final LETTER_U = 0x75;
+ static final LETTER_V = 0x76;
+ static final LETTER_X = 0x78;
+
+ static final LETTER_CAP_A = 0x41;
+ static final LETTER_CAP_F = 0x46;
+ static final LETTER_CAP_L = 0x4C;
+ static final LETTER_CAP_N = 0x4E;
+ static final LETTER_CAP_P = 0x50;
+ static final LETTER_CAP_U = 0x55;
+ static final LETTER_CAP_X = 0x58;
+
static final C_SEQUENCE_ENTRY = 4;
static final C_MAPPING_KEY = 5;
static final C_MAPPING_VALUE = 6;
@@ -81,6 +106,10 @@ class _Parser {
static final BLOCK_KEY = 4;
static final FLOW_KEY = 5;
+ static final CHOMPING_STRIP = 0;
+ static final CHOMPING_KEEP = 1;
+ static final CHOMPING_CLIP = 2;
+
/** The source string being parsed. */
final String s;
@@ -123,6 +152,21 @@ class _Parser {
/** A stack of the names of parse contexts. Used for error reporting. */
List<String> contextStack;
+ /**
+ * The buffer containing string currently being captured.
Bob Nystrom 2012/05/18 21:06:30 "string" -> "the string"
nweiz 2012/05/18 21:47:04 Done.
+ */
+ StringBuffer capturedString;
+
+ /**
+ * The beginning of the current section of the captured string.
+ */
+ int captureStart;
+
+ /**
+ * Whether the current string capture is being overridden.
+ */
+ bool capturingAs = false;
+
_Parser(String s)
: this.s = s,
len = s.length,
@@ -185,6 +229,11 @@ class _Parser {
}
/**
+ * Consumes the current character if it equals [char].
+ */
+ bool consumeChar(int char) => consume((c) => c == char);
+
+ /**
* Calls [consumer] until it returns a falsey value. Returns a list of all
* truthy return values of [consumer], or null if it didn't consume anything.
*
@@ -242,13 +291,19 @@ class _Parser {
* [consumer] returns a falsey value.
*/
transaction(consumer()) {
- int oldPos = pos, oldLine = line, oldColumn = column;
+ int oldPos = pos, oldLine = line, oldColumn = column,
+ oldCaptureStart = captureStart;
Bob Nystrom 2012/05/18 21:06:30 How about splitting these into separate declaratio
nweiz 2012/05/18 21:47:04 Done.
+ String capturedSoFar = capturedString == null ? null :
+ capturedString.toString();
var res = consumer();
if (truth(res)) return res;
pos = oldPos;
line = oldLine;
column = oldColumn;
+ captureStart = oldCaptureStart;
+ capturedString = capturedSoFar == null ? null :
+ new StringBuffer(capturedSoFar);
return res;
}
@@ -287,16 +342,50 @@ class _Parser {
* [consumer] in `transaction`.
*/
String captureString(consumer()) {
- int start = pos;
+ if (capturedString != null) throw 'captureString calls may not be nested';
Bob Nystrom 2012/05/18 21:06:30 This is a programmatic error, right? If so, I woul
nweiz 2012/05/18 21:47:04 Done.
+
+ captureStart = pos;
+ capturedString = new StringBuffer();
var res = transaction(consumer);
- if (!truth(res)) return null;
- return s.substring(start, pos);
+ if (!truth(res)) {
+ captureStart = capturedString = null;
Bob Nystrom 2012/05/18 21:06:30 This chained assignment doesn't really add a lot o
nweiz 2012/05/18 21:47:04 Done.
+ return null;
+ }
+
+ flushCapture();
+ var result = capturedString.toString();
+ captureStart = capturedString = null;
Bob Nystrom 2012/05/18 21:06:30 Ditto.
nweiz 2012/05/18 21:47:04 Done.
+ return result;
+ }
+
+ captureAs(String replacement, consumer()) =>
+ captureAndTransform(consumer, (_) => replacement);
Bob Nystrom 2012/05/18 21:06:30 +2 indent.
nweiz 2012/05/18 21:47:04 Done.
+
+ captureAndTransform(consumer(), String transformation(String captured)) {
+ if (capturedString == null) return consumer();
+ if (capturingAs) return consumer();
+
+ flushCapture();
+ capturingAs = true;
+ var res = consumer();
+ capturingAs = false;
+ if (!truth(res)) return res;
+
+ capturedString.add(transformation(s.substring(captureStart, pos)));
+ captureStart = pos;
+ return res;
+ }
+
+ void flushCapture() {
+ capturedString.add(s.substring(captureStart, pos));
+ captureStart = pos;
}
/**
* Adds a tag and an anchor to [node], if they're defined.
*/
_Node addProps(_Node node, _Pair<_Tag, String> props) {
+ if (props == null || node == null) return node;
if (truth(props.first)) node.tag = props.first;
if (truth(props.last)) node.anchor = props.last;
return node;
@@ -352,6 +441,40 @@ class _Parser {
return i;
}
+ /** Returns the indentation for a block scalar. */
+ int blockScalarAdditionalIndentation(_BlockHeader header, int indent) {
+ if (!header.autoDetectIndent) return header.additionalIndent;
+
+ var maxSpaces = 0;
+ var maxSpacesLine = 0;
+ var spaces = 0;
+ transaction(() {
+ do {
+ spaces = captureString(() => zeroOrMore(() => consumeChar(SP))).length;
+ if (spaces > maxSpaces) {
+ maxSpaces = spaces;
+ maxSpacesLine = line;
+ }
+ } while (b_break());
+ return false;
+ });
+
+ // If the next non-empty line isn't indented further than the start of the
+ // block scalar, that means the scalar is going to be empty. Returning any
+ // value > 0 will cause the parser not to consume any text.
+ if (spaces <= indent) return 1;
+
+ // It's an error for a leading empty line to be indented more than the first
+ // non-empty line.
+ if (maxSpaces > spaces) {
+ throw new SyntaxError(maxSpacesLine + 1, maxSpaces,
+ "leading empty lines may not be indented more than the first "
Bob Nystrom 2012/05/18 21:06:30 Sentence case and ".".
nweiz 2012/05/18 21:47:04 Done.
+ "non-empty line");
+ }
+
+ return spaces - indent;
+ }
+
/** Returns whether the current position is at the beginning of a line. */
bool get atStartOfLine() => column == 0;
@@ -400,6 +523,9 @@ class _Parser {
(char >= 0x10000 && char <= 0x10FFFF);
}
+ // 2
+ bool isJson(int char) => char == TAB || (char >= SP && char <= 0x10FFFF);
+
// 22
bool c_indicator(int type) => consume((c) => indicatorType(c) == type);
@@ -419,8 +545,20 @@ class _Parser {
// 27
bool isNonBreak(int char) => isPrintable(char) && !isBreak(char);
+ // 28
+ bool b_break() {
+ if (consumeChar(CR)) {
+ zeroOrOne(() => consumeChar(LF));
+ return true;
+ }
+ return consumeChar(LF);
+ }
+
+ // 29
+ bool b_asLineFeed() => captureAs("\n", () => b_break());
+
// 30
- bool b_non_content() => consume(isBreak);
+ bool b_nonContent() => captureAs("", () => b_break());
// 33
bool isSpace(int char) => char == SP || char == TAB;
@@ -428,36 +566,191 @@ class _Parser {
// 34
bool isNonSpace(int char) => isNonBreak(char) && !isSpace(char);
+ // 35
+ bool isDecDigit(int char) => char >= NUMBER_0 && char <= NUMBER_9;
+
+ // 36
+ bool isHexDigit(int char) {
+ return isDecDigit(char) ||
+ (char >= LETTER_A && char <= LETTER_F) ||
+ (char >= LETTER_CAP_A && char <= LETTER_CAP_F);
+ }
+
+ // 41
+ bool c_escape() => captureAs("", () => consumeChar(BACKSLASH));
+
+ // 42
+ bool ns_escNull() => captureAs("\x00", () => consumeChar(NUMBER_0));
+
+ // 43
+ bool ns_escBell() => captureAs("\x07", () => consumeChar(LETTER_A));
+
+ // 44
+ bool ns_escBackspace() => captureAs("\b", () => consumeChar(LETTER_B));
+
+ // 45
+ bool ns_escHorizontalTab() => captureAs("\t", () {
+ return consume((c) => c == LETTER_T || c == TAB);
+ });
+
+ // 46
+ bool ns_escLineFeed() => captureAs("\n", () => consumeChar(LETTER_N));
+
+ // 47
+ bool ns_escVerticalTab() => captureAs("\v", () => consumeChar(LETTER_V));
+
+ // 48
+ bool ns_escFormFeed() => captureAs("\f", () => consumeChar(LETTER_F));
+
+ // 49
+ bool ns_escCarriageReturn() => captureAs("\r", () => consumeChar(LETTER_R));
+
+ // 50
+ bool ns_escEscape() => captureAs("\x1B", () => consumeChar(LETTER_E));
+
+ // 51
+ bool ns_escSpace() => consumeChar(SP);
+
+ // 52
+ bool ns_escDoubleQuote() => consumeChar(DOUBLE_QUOTE);
+
+ // 53
+ bool ns_escSlash() => consumeChar(SLASH);
+
+ // 54
+ bool ns_escBackslash() => consumeChar(BACKSLASH);
+
+ // 55
+ bool ns_escNextLine() => captureAs("\x85", () => consumeChar(LETTER_CAP_N));
+
+ // 56
+ bool ns_escNonBreakingSpace() =>
+ captureAs("\xA0", () => consumeChar(UNDERSCORE));
+
+ // 57
+ bool ns_escLineSeparator() =>
+ captureAs("\u2028", () => consumeChar(LETTER_CAP_L));
+
+ // 58
+ bool ns_escParagraphSeparator() =>
+ captureAs("\u2029", () => consumeChar(LETTER_CAP_P));
+
+ // 59
+ bool ns_esc8Bit() => ns_escNBit(LETTER_X, 2);
+
+ // 60
+ bool ns_esc16Bit() => ns_escNBit(LETTER_U, 4);
+
+ // 61
+ bool ns_esc32Bit() => ns_escNBit(LETTER_CAP_U, 8);
+
+ // Helper method for 59 - 61
+ bool ns_escNBit(int char, int digits) {
+ if (!captureAs('', () => consumeChar(char))) return false;
+ var captured = captureAndTransform(
+ () => nAtOnce(digits, (c, _) => isHexDigit(c)),
+ (hex) => new String.fromCharCodes([Math.parseInt("0x$hex")]));
+ return expect(captured, "$digits hexidecimal digits");
+ }
+
+ // 62
+ bool c_ns_escChar() => context('escape sequence', () => transaction(() {
+ if (!truth(c_escape())) return false;
+ return truth(or([
+ ns_escNull, ns_escBell, ns_escBackspace, ns_escHorizontalTab,
+ ns_escLineFeed, ns_escVerticalTab, ns_escFormFeed, ns_escCarriageReturn,
+ ns_escEscape, ns_escSpace, ns_escDoubleQuote, ns_escSlash,
+ ns_escBackslash, ns_escNextLine, ns_escNonBreakingSpace,
+ ns_escLineSeparator, ns_escParagraphSeparator, ns_esc8Bit, ns_esc16Bit,
+ ns_esc32Bit
+ ]));
+ }));
+
// 63
bool s_indent(int indent) => nAtOnce(indent, (c, i) => c == SP);
+ // 64
+ bool s_indentLessThan(int indent) {
+ for (int i = 0; i < indent - 1; i++) {
+ if (!consumeChar(SP)) break;
+ }
+ return true;
+ }
+
+ // 65
+ bool s_indentLessThanOrEqualTo(int indent) => s_indentLessThan(indent + 1);
+
// 66
- bool s_separateInLine() => transaction(() =>
- truth(oneOrMore(() => consume(isSpace))) || atStartOfLine);
+ bool s_separateInLine() => transaction(() {
+ return captureAs('', () =>
+ truth(oneOrMore(() => consume(isSpace))) || atStartOfLine);
+ });
+
+ // 67
+ bool s_linePrefix(int indent, int ctx) => captureAs("", () {
+ switch (ctx) {
+ case BLOCK_OUT:
+ case BLOCK_IN:
+ return s_blockLinePrefix(indent);
+ case FLOW_OUT:
+ case FLOW_IN:
+ return s_flowLinePrefix(indent);
+ }
+ });
+
+ // 68
+ bool s_blockLinePrefix(int indent) => s_indent(indent);
// 69
- bool s_flowLinePrefix(int indent) {
- if (!s_indent(indent)) return false;
+ bool s_flowLinePrefix(int indent) => captureAs('', () {
+ if (!truth(s_indent(indent))) return false;
zeroOrOne(s_separateInLine);
return true;
- }
+ });
+
+ // 70
+ bool l_empty(int indent, int ctx) => transaction(() {
+ var start = or([
+ () => s_linePrefix(indent, ctx),
+ () => s_indentLessThan(indent)
+ ]);
+ if (!truth(start)) return false;
+ return b_asLineFeed();
+ });
+
+ // 71
+ bool b_asSpace() => captureAs(" ", () => consume(isBreak));
+
+ // 72
+ bool b_l_trimmed(int indent, int ctx) => transaction(() {
+ if (!truth(b_nonContent())) return false;
+ return truth(oneOrMore(() => captureAs("\n", () => l_empty(indent, ctx))));
+ });
+
+ // 73
+ bool b_l_folded(int indent, int ctx) =>
+ or([() => b_l_trimmed(indent, ctx), b_asSpace]);
// 74
- bool s_flowFolded(int indent) => false; // TODO(nweiz): implement
+ bool s_flowFolded(int indent) => transaction(() {
+ zeroOrOne(s_separateInLine);
+ if (!truth(b_l_folded(indent, FLOW_IN))) return false;
+ return s_flowLinePrefix(indent);
+ });
// 75
bool c_nb_commentText() {
- if (!c_indicator(C_COMMENT)) return false;
+ if (!truth(c_indicator(C_COMMENT))) return false;
zeroOrMore(() => consume(isNonBreak));
return true;
}
// 76
- bool b_comment() => atEndOfFile || b_non_content();
+ bool b_comment() => atEndOfFile || b_nonContent();
// 77
bool s_b_comment() {
- if (s_separateInLine()) {
+ if (truth(s_separateInLine())) {
zeroOrOne(c_nb_commentText);
}
return b_comment();
@@ -465,14 +758,14 @@ class _Parser {
// 78
bool l_comment() => transaction(() {
- if (!s_separateInLine()) return false;
+ if (!truth(s_separateInLine())) return false;
zeroOrOne(c_nb_commentText);
return b_comment();
});
// 79
bool s_l_comments() {
- if (!s_b_comment() && !atStartOfLine) return false;
+ if (!truth(s_b_comment()) && !atStartOfLine) return false;
zeroOrMore(l_comment);
return true;
}
@@ -507,7 +800,7 @@ class _Parser {
tag = c_ns_tagProperty();
if (truth(tag)) {
anchor = transaction(() {
- if (!s_separate(indent, ctx)) return null;
+ if (!truth(s_separate(indent, ctx))) return null;
return c_ns_anchorProperty();
});
return new _Pair<_Tag, String>(tag, anchor);
@@ -516,7 +809,7 @@ class _Parser {
anchor = c_ns_anchorProperty();
if (truth(anchor)) {
tag = transaction(() {
- if (!s_separate(indent, ctx)) return null;
+ if (!truth(s_separate(indent, ctx))) return null;
return c_ns_tagProperty();
});
return new _Pair<_Tag, String>(tag, anchor);
@@ -540,7 +833,7 @@ class _Parser {
// 104
_Node c_ns_aliasNode() {
- if (!c_indicator(C_ALIAS)) return null;
+ if (!truth(c_indicator(C_ALIAS))) return null;
var name = expect(ns_anchorName(), 'anchor name');
return new _AliasNode(name);
}
@@ -551,6 +844,164 @@ class _Parser {
// 106
_ScalarNode e_node() => e_scalar();
+ // 107
+ bool nb_doubleChar() => or([
+ c_ns_escChar,
+ () => consume((c) => isJson(c) && c != BACKSLASH && c != DOUBLE_QUOTE)
+ ]);
+
+ // 108
+ bool ns_doubleChar() => !isSpace(peek()) && truth(nb_doubleChar());
+
+ // 109
+ _Node c_doubleQuoted(int indent, int ctx) => context('string', () {
+ return transaction(() {
+ if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
+ var contents = nb_doubleText(indent, ctx);
+ if (!truth(c_indicator(C_DOUBLE_QUOTE))) return null;
+ return new _ScalarNode("!", contents);
+ });
+ });
+
+ // 110
+ String nb_doubleText(int indent, int ctx) => captureString(() {
+ switch (ctx) {
+ case FLOW_OUT:
+ case FLOW_IN:
+ nb_doubleMultiLine(indent);
+ break;
+ case BLOCK_KEY:
+ case FLOW_KEY:
+ nb_doubleOneLine();
+ break;
+ }
+ return true;
+ });
+
+ // 111
+ void nb_doubleOneLine() {
+ zeroOrMore(nb_doubleChar);
+ }
+
+ // 112
+ bool s_doubleEscaped(int indent) => transaction(() {
+ zeroOrMore(() => consume(isSpace));
+ if (!captureAs("", () => consumeChar(BACKSLASH))) return false;
+ if (!truth(b_nonContent())) return false;
+ zeroOrMore(() => captureAs("\n", () => l_empty(indent, FLOW_IN)));
+ return s_flowLinePrefix(indent);
+ });
+
+ // 113
+ bool s_doubleBreak(int indent) => or([
+ () => s_doubleEscaped(indent),
+ () => s_flowFolded(indent)
+ ]);
+
+ // 114
+ void nb_ns_doubleInLine() {
+ zeroOrMore(() => transaction(() {
+ zeroOrMore(() => consume(isSpace));
+ return ns_doubleChar();
+ }));
+ }
+
+ // 115
+ bool s_doubleNextLine(int indent) {
+ if (!truth(s_doubleBreak(indent))) return false;
+ zeroOrOne(() {
+ if (!truth(ns_doubleChar())) return;
+ nb_ns_doubleInLine();
+ or([
+ () => s_doubleNextLine(indent),
+ () => zeroOrMore(() => consume(isSpace))
+ ]);
+ });
+ return true;
+ }
+
+ // 116
+ void nb_doubleMultiLine(int indent) {
+ nb_ns_doubleInLine();
+ or([
+ () => s_doubleNextLine(indent),
+ () => zeroOrMore(() => consume(isSpace))
+ ]);
+ }
+
+ // 117
+ bool c_quotedQuote() => captureAs("'", () => rawString("''"));
+
+ // 118
+ bool nb_singleChar() => or([
+ c_quotedQuote,
+ () => consume((c) => isJson(c) && c != SINGLE_QUOTE)
+ ]);
+
+ // 119
+ bool ns_singleChar() => !isSpace(peek()) && truth(nb_singleChar());
+
+ // 120
+ _Node c_singleQuoted(int indent, int ctx) => context('string', () {
+ return transaction(() {
+ if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
+ var contents = nb_singleText(indent, ctx);
+ if (!truth(c_indicator(C_SINGLE_QUOTE))) return null;
+ return new _ScalarNode("!", contents);
+ });
+ });
+
+ // 121
+ String nb_singleText(int indent, int ctx) => captureString(() {
+ switch (ctx) {
+ case FLOW_OUT:
+ case FLOW_IN:
+ nb_singleMultiLine(indent);
+ break;
+ case BLOCK_KEY:
+ case FLOW_KEY:
+ nb_singleOneLine(indent);
+ break;
+ }
+ return true;
+ });
+
+ // 122
+ void nb_singleOneLine(int indent) {
+ zeroOrMore(nb_singleChar);
+ }
+
+ // 123
+ void nb_ns_singleInLine() {
+ zeroOrMore(() => transaction(() {
+ zeroOrMore(() => consume(isSpace));
+ return ns_singleChar();
+ }));
+ }
+
+ // 124
+ bool s_singleNextLine(int indent) {
+ if (!truth(s_flowFolded(indent))) return false;
+ zeroOrOne(() {
+ if (!truth(ns_singleChar())) return;
+ nb_ns_singleInLine();
+ or([
+ () => s_singleNextLine(indent),
+ () => zeroOrMore(() => consume(isSpace))
+ ]);
+ });
+ return true;
+ }
+
+ // 125
+ void nb_singleMultiLine(int indent) {
+ nb_ns_singleInLine();
+ or([
+ () => s_singleNextLine(indent),
+ () => zeroOrMore(() => consume(isSpace))
+ ]);
+ }
+
// 126
bool ns_plainFirst(int ctx) {
var char = peek();
@@ -600,15 +1051,17 @@ class _Parser {
// 131
String ns_plain(int indent, int ctx) => context('plain scalar', () {
- switch (ctx) {
- case FLOW_OUT:
- case FLOW_IN:
- return ns_plainMultiLine(indent, ctx);
- case BLOCK_KEY:
- case FLOW_KEY:
- return ns_plainOneLine(ctx);
- default: throw 'invalid context "$ctx"';
- }
+ return captureString(() {
+ switch (ctx) {
+ case FLOW_OUT:
+ case FLOW_IN:
+ return ns_plainMultiLine(indent, ctx);
+ case BLOCK_KEY:
+ case FLOW_KEY:
+ return ns_plainOneLine(ctx);
+ default: throw 'invalid context "$ctx"';
+ }
+ });
});
// 132
@@ -620,31 +1073,236 @@ class _Parser {
}
// 133
- String ns_plainOneLine(int ctx) => captureString(() {
- if (c_forbidden()) return false;
- if (!ns_plainFirst(ctx)) return false;
+ bool ns_plainOneLine(int ctx) {
+ if (truth(c_forbidden())) return false;
+ if (!truth(ns_plainFirst(ctx))) return false;
nb_ns_plainInLine(ctx);
return true;
- });
+ }
// 134
bool s_ns_plainNextLine(int indent, int ctx) => transaction(() {
- if (c_forbidden()) return false;
- if (!s_flowFolded(indent)) return false;
- if (!ns_plainChar(ctx)) return false;
+ if (!truth(s_flowFolded(indent))) return false;
+ if (truth(c_forbidden())) return false;
+ if (!truth(ns_plainChar(ctx))) return false;
nb_ns_plainInLine(ctx);
return true;
});
// 135
- String ns_plainMultiLine(int indent, int ctx) => captureString(() {
+ bool ns_plainMultiLine(int indent, int ctx) {
if (!truth(ns_plainOneLine(ctx))) return false;
zeroOrMore(() => s_ns_plainNextLine(indent, ctx));
return true;
+ }
+
+ // 136
+ int inFlow(int ctx) {
+ switch (ctx) {
+ case FLOW_OUT:
+ case FLOW_IN:
+ return FLOW_IN;
+ case BLOCK_KEY:
+ case FLOW_KEY:
+ return FLOW_KEY;
+ }
+ }
+
+ // 137
+ _SequenceNode c_flowSequence(int indent, int ctx) => transaction(() {
+ if (!truth(c_indicator(C_SEQUENCE_START))) return null;
+ zeroOrOne(() => s_separate(indent, ctx));
+ var content = zeroOrOne(() => ns_s_flowSeqEntries(indent, inFlow(ctx)));
+ if (!truth(c_indicator(C_SEQUENCE_END))) return null;
+ return new _SequenceNode("?", new List<_Node>.from(content));
});
+ // 138
+ Collection<_Node> ns_s_flowSeqEntries(int indent, int ctx) {
+ var first = ns_flowSeqEntry(indent, ctx);
+ if (!truth(first)) return new Queue<_Node>();
+ zeroOrOne(() => s_separate(indent, ctx));
+
+ var rest;
+ if (truth(c_indicator(C_COLLECT_ENTRY))) {
+ zeroOrOne(() => s_separate(indent, ctx));
+ rest = zeroOrOne(() => ns_s_flowSeqEntries(indent, ctx));
+ }
+
+ if (rest == null) rest = new Queue<_Node>();
+ rest.addFirst(first);
+
+ return rest;
+ }
+
+ // 139
+ _Node ns_flowSeqEntry(int indent, int ctx) => or([
+ () => ns_flowPair(indent, ctx),
+ () => ns_flowNode(indent, ctx)
+ ]);
+
+ // 140
+ _Node c_flowMapping(int indent, int ctx) {
+ if (!truth(c_indicator(C_MAPPING_START))) return null;
+ zeroOrOne(() => s_separate(indent, ctx));
+ var content = zeroOrOne(() => ns_s_flowMapEntries(indent, inFlow(ctx)));
+ if (!truth(c_indicator(C_MAPPING_END))) return null;
+ return new _MappingNode("?", content);
+ }
+
+ // 141
+ YamlMap ns_s_flowMapEntries(int indent, int ctx) {
+ var first = ns_flowMapEntry(indent, ctx);
+ if (!truth(first)) return new YamlMap();
+ zeroOrOne(() => s_separate(indent, ctx));
+
+ var rest;
+ if (truth(c_indicator(C_COLLECT_ENTRY))) {
+ zeroOrOne(() => s_separate(indent, ctx));
+ rest = ns_s_flowMapEntries(indent, ctx);
+ }
+
+ if (rest == null) rest = new YamlMap();
+
+ // TODO(nweiz): Duplicate keys should be an error. This includes keys with
+ // different representations but the same value (e.g. 10 vs 0xa). To make
+ // this user-friendly we'll probably also want to associate nodes with a
+ // source range.
+ if (!rest.containsKey(first.first)) rest[first.first] = first.last;
+
+ return rest;
+ }
+
+ // 142
+ _Pair<_Node, _Node> ns_flowMapEntry(int indent, int ctx) => or([
+ () => transaction(() {
+ if (!truth(c_indicator(C_MAPPING_KEY))) return false;
+ if (!truth(s_separate(indent, ctx))) return false;
+ return ns_flowMapExplicitEntry(indent, ctx);
+ }),
+ () => ns_flowMapImplicitEntry(indent, ctx)
+ ]);
+
+ // 143
+ _Pair<_Node, _Node> ns_flowMapExplicitEntry(int indent, int ctx) => or([
+ () => ns_flowMapImplicitEntry(indent, ctx),
+ () => new _Pair<_Node, _Node>(e_node(), e_node())
+ ]);
+
+ // 144
+ _Pair<_Node, _Node> ns_flowMapImplicitEntry(int indent, int ctx) => or([
+ () => ns_flowMapYamlKeyEntry(indent, ctx),
+ () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
+ () => c_ns_flowMapJsonKeyEntry(indent, ctx)
+ ]);
+
+ // 145
+ _Pair<_Node, _Node> ns_flowMapYamlKeyEntry(int indent, int ctx) {
+ var key = ns_flowYamlNode(indent, ctx);
+ if (!truth(key)) return null;
+ var value = or([
+ () => transaction(() {
+ zeroOrOne(() => s_separate(indent, ctx));
+ return c_ns_flowMapSeparateValue(indent, ctx);
+ }),
+ e_node
+ ]);
+ return new _Pair<_Node, _Node>(key, value);
+ }
+
+ // 146
+ _Pair<_Node, _Node> c_ns_flowMapEmptyKeyEntry(int indent, int ctx) {
+ var value = c_ns_flowMapSeparateValue(indent, ctx);
+ if (!truth(value)) return null;
+ return new _Pair<_Node, _Node>(e_node(), value);
+ }
+
+ // 147
+ _Node c_ns_flowMapSeparateValue(int indent, int ctx) => transaction(() {
+ if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
+ if (isPlainSafe(ctx, peek())) return null;
+
+ return or([
+ () => transaction(() {
+ if (!s_separate(indent, ctx)) return null;
+ return ns_flowNode(indent, ctx);
+ }),
+ e_node
+ ]);
+ });
+
+ // 148
+ _Pair<_Node, _Node> c_ns_flowMapJsonKeyEntry(int indent, int ctx) {
+ var key = c_flowJsonNode(indent, ctx);
+ if (!truth(key)) return null;
+ var value = or([
+ () => transaction(() {
+ zeroOrOne(() => s_separate(indent, ctx));
+ return c_ns_flowMapAdjacentValue(indent, ctx);
+ }),
+ e_node
+ ]);
+ return new _Pair<_Node, _Node>(key, value);
+ }
+
+ // 149
+ _Node c_ns_flowMapAdjacentValue(int indent, int ctx) {
+ if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
+ return or([
+ () => transaction(() {
+ zeroOrOne(() => s_separate(indent, ctx));
+ return ns_flowNode(indent, ctx);
+ }),
+ e_node
+ ]);
+ }
+
+ // 150
+ _Node ns_flowPair(int indent, int ctx) {
+ var pair = or([
+ () => transaction(() {
+ if (!truth(c_indicator(C_MAPPING_KEY))) return null;
+ if (!truth(s_separate(indent, ctx))) return null;
+ return ns_flowMapExplicitEntry(indent, ctx);
+ }),
+ () => ns_flowPairEntry(indent, ctx)
+ ]);
+ if (!truth(pair)) return null;
+
+ return map([pair]);
+ }
+
+ // 151
+ _Pair<_Node, _Node> ns_flowPairEntry(int indent, int ctx) => or([
+ () => ns_flowPairYamlKeyEntry(indent, ctx),
+ () => c_ns_flowMapEmptyKeyEntry(indent, ctx),
+ () => c_ns_flowPairJsonKeyEntry(indent, ctx)
+ ]);
+
+ // 152
+ _Pair<_Node, _Node> ns_flowPairYamlKeyEntry(int indent, int ctx) =>
+ transaction(() {
+ var key = ns_s_implicitYamlKey(FLOW_KEY);
+ if (!truth(key)) return null;
+ var value = c_ns_flowMapSeparateValue(indent, ctx);
+ if (!truth(value)) return null;
+ return new _Pair<_Node, _Node>(key, value);
+ });
+
+ // 153
+ _Pair<_Node, _Node> c_ns_flowPairJsonKeyEntry(int indent, int ctx) =>
+ transaction(() {
+ var key = c_s_implicitJsonKey(FLOW_KEY);
+ if (!truth(key)) return null;
+ var value = c_ns_flowMapAdjacentValue(indent, ctx);
+ if (!truth(value)) return null;
+ return new _Pair<_Node, _Node>(key, value);
+ });
+
// 154
- _Node c_s_implicitYamlKey(int ctx) => transaction(() {
+ _Node ns_s_implicitYamlKey(int ctx) => transaction(() {
+ // TODO(nweiz): this is supposed to be limited to 1024 characters.
+
// The indentation parameter is "null" since it's unused in this path
var node = ns_flowYamlNode(null, ctx);
if (!truth(node)) return null;
@@ -653,7 +1311,15 @@ class _Parser {
});
// 155
- _Node c_s_implicitJsonKey(int ctx) => null; // TODO(nweiz): implement
+ _Node c_s_implicitJsonKey(int ctx) => transaction(() {
+ // TODO(nweiz): this is supposed to be limited to 1024 characters.
+
+ // The indentation parameter is "null" since it's unused in this path
+ var node = c_flowJsonNode(null, ctx);
+ if (!truth(node)) return null;
+ zeroOrOne(s_separateInLine);
+ return node;
+ });
// 156
_Node ns_flowYamlContent(int indent, int ctx) {
@@ -663,13 +1329,17 @@ class _Parser {
}
// 157
- // TODO(nweiz): implement
- _Node ns_flowJsonContent(int indent, int ctx) => null;
+ _Node c_flowJsonContent(int indent, int ctx) => or([
+ () => c_flowSequence(indent, ctx),
+ () => c_flowMapping(indent, ctx),
+ () => c_singleQuoted(indent, ctx),
+ () => c_doubleQuoted(indent, ctx)
+ ]);
// 158
_Node ns_flowContent(int indent, int ctx) => or([
() => ns_flowYamlContent(indent, ctx),
- () => ns_flowJsonContent(indent, ctx)
+ () => c_flowJsonContent(indent, ctx)
]);
// 159
@@ -681,7 +1351,7 @@ class _Parser {
if (!truth(props)) return null;
var node = or([
() => transaction(() {
- if (!s_separate(indent, ctx)) return null;
+ if (!truth(s_separate(indent, ctx))) return null;
return ns_flowYamlContent(indent, ctx);
}),
e_scalar
@@ -690,6 +1360,18 @@ class _Parser {
}
]);
+ // 160
+ _Node c_flowJsonNode(int indent, int ctx) => transaction(() {
+ var props;
+ zeroOrOne(() => transaction(() {
+ props = c_ns_properties(indent, ctx);
+ if (!truth(props)) return null;
+ return s_separate(indent, ctx);
+ }));
+
+ return addProps(c_flowJsonContent(indent, ctx), props);
+ });
+
// 161
_Node ns_flowNode(int indent, int ctx) => or([
c_ns_aliasNode,
@@ -705,11 +1387,207 @@ class _Parser {
})
]);
+ // 162
+ _BlockHeader c_b_blockHeader() => transaction(() {
+ var indentation = c_indentationIndicator();
+ var chomping = c_chompingIndicator();
+ if (!truth(indentation)) indentation = c_indentationIndicator();
+ if (!truth(s_b_comment())) return null;
+
+ return new _BlockHeader(indentation, chomping);
+ });
+
+ // 163
+ int c_indentationIndicator() {
+ if (!isDecDigit(peek())) return null;
+ return next() - NUMBER_0;
+ }
+
+ // 164
+ int c_chompingIndicator() {
+ switch (peek()) {
+ case HYPHEN:
+ next();
+ return CHOMPING_STRIP;
+ case PLUS:
+ next();
+ return CHOMPING_KEEP;
+ default:
+ return CHOMPING_CLIP;
+ }
+ }
+
+ // 165
+ bool b_chompedLast(int chomping) {
+ if (atEndOfFile) return true;
+ switch (chomping) {
+ case CHOMPING_STRIP:
+ return b_nonContent();
+ case CHOMPING_CLIP:
+ case CHOMPING_KEEP:
+ return b_asLineFeed();
+ }
+ }
+
+ // 166
+ void l_chompedEmpty(int indent, int chomping) {
+ switch (chomping) {
+ case CHOMPING_STRIP:
+ case CHOMPING_CLIP:
+ l_stripEmpty(indent);
+ break;
+ case CHOMPING_KEEP:
+ l_keepEmpty(indent);
+ break;
+ }
+ }
+
+ // 167
+ void l_stripEmpty(int indent) => captureAs('', () {
+ zeroOrMore(() => transaction(() {
+ if (!truth(s_indentLessThanOrEqualTo(indent))) return false;
+ return b_nonContent();
+ }));
+ zeroOrOne(() => l_trailComments(indent));
+ return true;
+ });
+
+ // 168
+ void l_keepEmpty(int indent) {
+ zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN)));
+ zeroOrOne(() => captureAs('', () => l_trailComments(indent)));
+ }
+
+ // 169
+ bool l_trailComments(int indent) => transaction(() {
+ if (!truth(s_indentLessThanOrEqualTo(indent))) return false;
+ if (!truth(c_nb_commentText())) return false;
+ if (!truth(b_comment())) return false;
+ zeroOrMore(l_comment);
+ return true;
+ });
+
// 170
- _Node c_l_literal(int indent) => null; // TODO(nweiz); implement
+ _Node c_l_literal(int indent) => transaction(() {
+ if (!truth(c_indicator(C_LITERAL))) return null;
+ var header = c_b_blockHeader();
+ if (!truth(header)) return null;
+
+ var additionalIndent = blockScalarAdditionalIndentation(header, indent);
+ var content = l_literalContent(indent + additionalIndent, header.chomping);
+ if (!truth(content)) return null;
+
+ return new _ScalarNode("!", content);
+ });
+
+ // 171
+ bool l_nb_literalText(int indent) => transaction(() {
+ zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN)));
+ if (!truth(captureAs("", () => s_indent(indent)))) return false;
+ return truth(oneOrMore(() => consume(isNonBreak)));
+ });
+
+ // 172
+ bool b_nb_literalNext(int indent) => transaction(() {
+ if (!truth(b_asLineFeed())) return false;
+ return l_nb_literalText(indent);
+ });
+
+ // 173
+ String l_literalContent(int indent, int chomping) => captureString(() {
+ transaction(() {
+ if (!truth(l_nb_literalText(indent))) return false;
+ zeroOrMore(() => b_nb_literalNext(indent));
+ return b_chompedLast(chomping);
+ });
+ l_chompedEmpty(indent, chomping);
+ return true;
+ });
// 174
- _Node c_l_folded(int indent) => null; // TODO(nweiz); implement
+ _Node c_l_folded(int indent) => transaction(() {
+ if (!truth(c_indicator(C_FOLDED))) return null;
+ var header = c_b_blockHeader();
+ if (!truth(header)) return null;
+
+ var additionalIndent = blockScalarAdditionalIndentation(header, indent);
+ var content = l_foldedContent(indent + additionalIndent, header.chomping);
+ if (!truth(content)) return null;
+
+ return new _ScalarNode("!", content);
+ });
+
+ // 175
+ bool s_nb_foldedText(int indent) => transaction(() {
+ if (!truth(captureAs('', () => s_indent(indent)))) return false;
+ if (!truth(consume(isNonSpace))) return false;
+ zeroOrMore(() => consume(isNonBreak));
+ return true;
+ });
+
+ // 176
+ bool l_nb_foldedLines(int indent) {
+ if (!truth(s_nb_foldedText(indent))) return false;
+ zeroOrMore(() => transaction(() {
+ if (!truth(b_l_folded(indent, BLOCK_IN))) return false;
+ return s_nb_foldedText(indent);
+ }));
+ return true;
+ }
+
+ // 177
+ bool s_nb_spacedText(int indent) => transaction(() {
+ if (!truth(captureAs('', () => s_indent(indent)))) return false;
+ if (!truth(consume(isSpace))) return false;
+ zeroOrMore(() => consume(isNonBreak));
+ return true;
+ });
+
+ // 178
+ bool b_l_spaced(int indent) {
+ if (!truth(b_asLineFeed())) return false;
+ zeroOrMore(() => captureAs("\n", () => l_empty(indent, BLOCK_IN)));
+ return true;
+ }
+
+ // 179
+ bool l_nb_spacedLines(int indent) {
+ if (!truth(s_nb_spacedText(indent))) return false;
+ zeroOrMore(() => transaction(() {
+ if (!truth(b_l_spaced(indent))) return false;
+ return s_nb_spacedText(indent);
+ }));
+ return true;
+ }
+
+ // 180
+ bool l_nb_sameLines(int indent) => transaction(() {
+ zeroOrMore(() => captureAs('\n', () => l_empty(indent, BLOCK_IN)));
+ return or([
+ () => l_nb_foldedLines(indent),
+ () => l_nb_spacedLines(indent)
+ ]);
+ });
+
+ // 181
+ bool l_nb_diffLines(int indent) {
+ if (!truth(l_nb_sameLines(indent))) return false;
+ zeroOrMore(() => transaction(() {
+ if (!truth(b_asLineFeed())) return false;
+ return l_nb_sameLines(indent);
+ }));
+ return true;
+ }
+
+ // 182
+ String l_foldedContent(int indent, int chomping) => captureString(() {
+ transaction(() {
+ if (!truth(l_nb_diffLines(indent))) return false;
+ return b_chompedLast(chomping);
+ });
+ l_chompedEmpty(indent, chomping);
+ return true;
+ });
// 183
_SequenceNode l_blockSequence(int indent) => context('sequence', () {
@@ -717,7 +1595,7 @@ class _Parser {
if (additionalIndent <= 0) return null;
var content = oneOrMore(() => transaction(() {
- if (!s_indent(indent + additionalIndent)) return null;
+ if (!truth(s_indent(indent + additionalIndent))) return null;
return c_l_blockSeqEntry(indent + additionalIndent);
}));
if (!truth(content)) return null;
@@ -727,7 +1605,7 @@ class _Parser {
// 184
_Node c_l_blockSeqEntry(int indent) => transaction(() {
- if (!c_indicator(C_SEQUENCE_ENTRY)) return null;
+ if (!truth(c_indicator(C_SEQUENCE_ENTRY))) return null;
if (isNonSpace(peek())) return null;
return s_l_blockIndented(indent, BLOCK_IN);
@@ -738,7 +1616,7 @@ class _Parser {
var additionalIndent = countIndentation();
return or([
() => transaction(() {
- if (!s_indent(additionalIndent)) return null;
+ if (!truth(s_indent(additionalIndent))) return null;
return or([
() => ns_l_compactSequence(indent + 1 + additionalIndent),
() => ns_l_compactMapping(indent + 1 + additionalIndent)]);
@@ -753,7 +1631,7 @@ class _Parser {
if (!truth(first)) return null;
var content = zeroOrMore(() => transaction(() {
- if (!s_indent(indent)) return null;
+ if (!truth(s_indent(indent))) return null;
return c_l_blockSeqEntry(indent);
}));
content.insertRange(0, 1, first);
@@ -767,7 +1645,7 @@ class _Parser {
if (additionalIndent <= 0) return null;
var pairs = oneOrMore(() => transaction(() {
- if (!s_indent(indent + additionalIndent)) return null;
+ if (!truth(s_indent(indent + additionalIndent))) return null;
return ns_l_blockMapEntry(indent + additionalIndent);
}));
if (!truth(pairs)) return null;
@@ -782,8 +1660,30 @@ class _Parser {
]);
// 189
- // TODO(nweiz): implement
- _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) => null;
+ _Pair<_Node, _Node> c_l_blockMapExplicitEntry(int indent) {
+ var key = c_l_blockMapExplicitKey(indent);
+ if (!truth(key)) return null;
+
+ var value = or([
+ () => l_blockMapExplicitValue(indent),
+ e_node
+ ]);
+
+ return new _Pair<_Node, _Node>(key, value);
+ }
+
+ // 190
+ _Node c_l_blockMapExplicitKey(int indent) => transaction(() {
+ if (!truth(c_indicator(C_MAPPING_KEY))) return null;
+ return s_l_blockIndented(indent, BLOCK_OUT);
+ });
+
+ // 191
+ _Node l_blockMapExplicitValue(int indent) => transaction(() {
+ if (!truth(s_indent(indent))) return null;
+ if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
+ return s_l_blockIndented(indent, BLOCK_OUT);
+ });
// 192
_Pair<_Node, _Node> ns_l_blockMapImplicitEntry(int indent) => transaction(() {
@@ -795,13 +1695,13 @@ class _Parser {
// 193
_Node ns_s_blockMapImplicitKey() => context('mapping key', () => or([
() => c_s_implicitJsonKey(BLOCK_KEY),
- () => c_s_implicitYamlKey(BLOCK_KEY)
+ () => ns_s_implicitYamlKey(BLOCK_KEY)
]));
// 194
_Node c_l_blockMapImplicitValue(int indent) => context('mapping value', () =>
transaction(() {
- if (!c_indicator(C_MAPPING_VALUE)) return null;
+ if (!truth(c_indicator(C_MAPPING_VALUE))) return null;
return or([
() => s_l_blockNode(indent, BLOCK_OUT),
() => s_l_comments() ? e_node() : null
@@ -814,7 +1714,7 @@ class _Parser {
if (!truth(first)) return null;
var pairs = zeroOrMore(() => transaction(() {
- if (!s_indent(indent)) return null;
+ if (!truth(s_indent(indent))) return null;
return ns_l_blockMapEntry(indent);
}));
pairs.insertRange(0, 1, first);
@@ -830,10 +1730,10 @@ class _Parser {
// 197
_Node s_l_flowInBlock(int indent) => transaction(() {
- if (!s_separate(indent + 1, FLOW_OUT)) return null;
+ if (!truth(s_separate(indent + 1, FLOW_OUT))) return null;
var node = ns_flowNode(indent + 1, FLOW_OUT);
if (!truth(node)) return null;
- if (!s_l_comments()) return null;
+ if (!truth(s_l_comments())) return null;
return node;
});
@@ -845,14 +1745,13 @@ class _Parser {
// 199
_Node s_l_blockScalar(int indent, int ctx) => transaction(() {
- if (!s_separate(indent + 1, ctx)) return null;
+ if (!truth(s_separate(indent + 1, ctx))) return null;
var props = transaction(() {
var props = c_ns_properties(indent + 1, ctx);
if (!truth(props)) return null;
- if (!s_separate(indent + 1, ctx)) return null;
+ if (!truth(s_separate(indent + 1, ctx))) return null;
return props;
});
- if (!truth(props)) props = new _Pair<_Tag, String>(null, null);
var node = or([() => c_l_literal(indent), () => c_l_folded(indent)]);
if (!truth(node)) return null;
@@ -862,12 +1761,11 @@ class _Parser {
// 200
_Node s_l_blockCollection(int indent, int ctx) => transaction(() {
var props = transaction(() {
- if (!s_separate(indent + 1, ctx)) return null;
+ if (!truth(s_separate(indent + 1, ctx))) return null;
return c_ns_properties(indent + 1, ctx);
});
- if (!truth(props)) props = new _Pair<_Tag, String>(null, null);
- if (!s_l_comments()) return null;
+ if (!truth(s_l_comments())) return null;
return or([
() => l_blockSequence(seqSpaces(indent, ctx)),
() => l_blockMapping(indent)]);
@@ -889,7 +1787,7 @@ class _Parser {
// 205
bool l_documentSuffix() => transaction(() {
- if (!c_documentEnd()) return false;
+ if (!truth(c_documentEnd())) return false;
return s_l_comments();
});
@@ -918,7 +1816,7 @@ class _Parser {
// 208
_Node l_explicitDocument() {
- if (!c_directivesEnd()) return null;
+ if (!truth(c_directivesEnd())) return null;
var doc = l_bareDocument();
if (truth(doc)) return doc;
@@ -983,3 +1881,13 @@ class _Pair<E, F> {
String toString() => '($first, $last)';
}
+
+/** The information in the header for a block scalar. */
+class _BlockHeader {
+ final int additionalIndent;
+ final int chomping;
+
+ _BlockHeader(this.additionalIndent, this.chomping);
+
+ bool get autoDetectIndent() => additionalIndent == null;
+}

Powered by Google App Engine
This is Rietveld 408576698