Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add case-insensitive strings (taken from Citrus).

  • Loading branch information...
commit 3037fa3b811fc881f237f331536b16ae9d5dfbf7 1 parent d07ef81
James Coglan authored
1  jake.yml
@@ -25,6 +25,7 @@ packages:
25 25 - canopy/compiler/any_char
26 26 - canopy/compiler/char_class
27 27 - canopy/compiler/string
  28 + - canopy/compiler/ci_string
28 29 - canopy/compiler/predicated_atom
29 30 - canopy/compiler/repeat
30 31 - canopy/compiler/sequence
27 source/canopy/compiler/ci_string.js
... ... @@ -0,0 +1,27 @@
  1 +Canopy.Compiler.extend({
  2 + CIString: new JS.Module({
  3 + toSexp: function() {
  4 + return ['ci-string', this.stringValue()];
  5 + },
  6 +
  7 + compile: function(builder, address, nodeType) {
  8 + var string = this.stringValue(),
  9 + length = string.length,
  10 + temp = builder.tempVar_('temp', builder.slice_(length)),
  11 + tlc = '.toLowerCase()';
  12 +
  13 + builder.if_(temp + tlc + ' === "' + string + '"' + tlc, function(builder) {
  14 + builder.syntaxNode_(address, nodeType, temp, length);
  15 + });
  16 + builder.else_(function(builder) {
  17 + builder.failure_(address);
  18 + });
  19 + },
  20 +
  21 + stringValue: function() {
  22 + var string = '"' + this.elements[1].textValue + '"';
  23 + return eval(string);
  24 + }
  25 + })
  26 +});
  27 +
4 source/canopy/compiler/string.js
@@ -6,9 +6,7 @@ Canopy.Compiler.extend({
6 6
7 7 compile: function(builder, address, nodeType) {
8 8 var string = this.textValue,
9   - length = eval(this.textValue).length,
10   - input = builder.input_(),
11   - offset = builder.offset_();
  9 + length = eval(this.textValue).length;
12 10
13 11 builder.if_(builder.slice_(length) + ' === ' + string, function(builder) {
14 12 builder.syntaxNode_(address, nodeType, string, length);
159 source/canopy/meta_grammar.js
@@ -1147,14 +1147,19 @@ Canopy.MetaGrammar = new JS.Module("Canopy.MetaGrammar", {
1147 1147 if (address0) {
1148 1148 } else {
1149 1149 this._offset = index1;
1150   - address0 = this.__consume__any_char_expression();
  1150 + address0 = this.__consume__ci_string_expression();
1151 1151 if (address0) {
1152 1152 } else {
1153 1153 this._offset = index1;
1154   - address0 = this.__consume__char_class_expression();
  1154 + address0 = this.__consume__any_char_expression();
1155 1155 if (address0) {
1156 1156 } else {
1157 1157 this._offset = index1;
  1158 + address0 = this.__consume__char_class_expression();
  1159 + if (address0) {
  1160 + } else {
  1161 + this._offset = index1;
  1162 + }
1158 1163 }
1159 1164 }
1160 1165 }
@@ -1445,6 +1450,156 @@ Canopy.MetaGrammar = new JS.Module("Canopy.MetaGrammar", {
1445 1450 }
1446 1451 return this._nodeCache.string_expression[index0] = address0;
1447 1452 },
  1453 + __consume__ci_string_expression: function(input) {
  1454 + var address0 = null;
  1455 + var index0 = this._offset;
  1456 + this._nodeCache.ci_string_expression = this._nodeCache.ci_string_expression || {};
  1457 + var cached = this._nodeCache.ci_string_expression[index0];
  1458 + if (cached) {
  1459 + this._offset += cached.textValue.length;
  1460 + return cached;
  1461 + }
  1462 + var index1 = this._offset;
  1463 + var elements0 = [];
  1464 + var labelled0 = {};
  1465 + var text0 = "";
  1466 + var address1 = null;
  1467 + if (this._input.substring(this._offset, this._offset + 1) === "`") {
  1468 + var klass0 = this.klass.SyntaxNode;
  1469 + address1 = new klass0("`", this._offset, []);
  1470 + this._offset += 1;
  1471 + } else {
  1472 + address1 = null;
  1473 + }
  1474 + if (address1) {
  1475 + elements0.push(address1);
  1476 + text0 += address1.textValue;
  1477 + var address2 = null;
  1478 + var remaining0 = 0;
  1479 + var index2 = this._offset;
  1480 + var elements1 = [];
  1481 + var text1 = "";
  1482 + var address3 = true;
  1483 + while (address3) {
  1484 + var index3 = this._offset;
  1485 + var index4 = this._offset;
  1486 + var elements2 = [];
  1487 + var labelled1 = {};
  1488 + var text2 = "";
  1489 + var address4 = null;
  1490 + if (this._input.substring(this._offset, this._offset + 1) === "\\") {
  1491 + var klass1 = this.klass.SyntaxNode;
  1492 + address4 = new klass1("\\", this._offset, []);
  1493 + this._offset += 1;
  1494 + } else {
  1495 + address4 = null;
  1496 + }
  1497 + if (address4) {
  1498 + elements2.push(address4);
  1499 + text2 += address4.textValue;
  1500 + var address5 = null;
  1501 + var temp0 = this._input.substring(this._offset, this._offset + 1);
  1502 + if (temp0 === "") {
  1503 + address5 = null;
  1504 + } else {
  1505 + var klass2 = this.klass.SyntaxNode;
  1506 + address5 = new klass2(temp0, this._offset, []);
  1507 + this._offset += 1;
  1508 + }
  1509 + if (address5) {
  1510 + elements2.push(address5);
  1511 + text2 += address5.textValue;
  1512 + } else {
  1513 + elements2 = null;
  1514 + this._offset = index4;
  1515 + }
  1516 + } else {
  1517 + elements2 = null;
  1518 + this._offset = index4;
  1519 + }
  1520 + if (elements2) {
  1521 + this._offset = index4;
  1522 + var klass3 = this.klass.SyntaxNode;
  1523 + address3 = new klass3(text2, this._offset, elements2, labelled1);
  1524 + this._offset += text2.length;
  1525 + } else {
  1526 + address3 = null;
  1527 + }
  1528 + if (address3) {
  1529 + } else {
  1530 + this._offset = index3;
  1531 + var temp1 = this._input.substring(this._offset, this._offset + 1);
  1532 + var match0 = null;
  1533 + if (match0 = temp1.match(/^[^`]/)) {
  1534 + var klass4 = this.klass.SyntaxNode;
  1535 + address3 = new klass4(match0[0], this._offset, []);
  1536 + this._offset += 1;
  1537 + } else {
  1538 + address3 = null;
  1539 + }
  1540 + if (address3) {
  1541 + } else {
  1542 + this._offset = index3;
  1543 + }
  1544 + }
  1545 + if (address3) {
  1546 + elements1.push(address3);
  1547 + text1 += address3.textValue;
  1548 + remaining0 -= 1;
  1549 + }
  1550 + }
  1551 + if (remaining0 <= 0) {
  1552 + this._offset = index2;
  1553 + var klass5 = this.klass.SyntaxNode;
  1554 + address2 = new klass5(text1, this._offset, elements1);
  1555 + this._offset += text1.length;
  1556 + } else {
  1557 + address2 = null;
  1558 + }
  1559 + if (address2) {
  1560 + elements0.push(address2);
  1561 + text0 += address2.textValue;
  1562 + var address6 = null;
  1563 + if (this._input.substring(this._offset, this._offset + 1) === "`") {
  1564 + var klass6 = this.klass.SyntaxNode;
  1565 + address6 = new klass6("`", this._offset, []);
  1566 + this._offset += 1;
  1567 + } else {
  1568 + address6 = null;
  1569 + }
  1570 + if (address6) {
  1571 + elements0.push(address6);
  1572 + text0 += address6.textValue;
  1573 + } else {
  1574 + elements0 = null;
  1575 + this._offset = index1;
  1576 + }
  1577 + } else {
  1578 + elements0 = null;
  1579 + this._offset = index1;
  1580 + }
  1581 + } else {
  1582 + elements0 = null;
  1583 + this._offset = index1;
  1584 + }
  1585 + if (elements0) {
  1586 + this._offset = index1;
  1587 + var klass7 = null;
  1588 + if (Canopy.Compiler.CIString instanceof Function) {
  1589 + klass7 = Canopy.Compiler.CIString;
  1590 + } else {
  1591 + klass7 = this.klass.SyntaxNode;
  1592 + }
  1593 + address0 = new klass7(text0, this._offset, elements0, labelled0);
  1594 + if (!(Canopy.Compiler.CIString instanceof Function)) {
  1595 + address0.extend(Canopy.Compiler.CIString);
  1596 + }
  1597 + this._offset += text0.length;
  1598 + } else {
  1599 + address0 = null;
  1600 + }
  1601 + return this._nodeCache.ci_string_expression[index0] = address0;
  1602 + },
1448 1603 __consume__any_char_expression: function(input) {
1449 1604 var address0 = null;
1450 1605 var index0 = this._offset;
4 source/canopy/meta_grammar.peg
@@ -38,6 +38,7 @@ grammar Canopy.MetaGrammar
38 38 / predicated_atom
39 39 / reference_expression
40 40 / string_expression
  41 + / ci_string_expression
41 42 / any_char_expression
42 43 / char_class_expression
43 44
@@ -49,6 +50,9 @@ grammar Canopy.MetaGrammar
49 50 string_expression <- "\"" ("\\" . / [^"])* "\""
50 51 <Canopy.Compiler.String>
51 52
  53 + ci_string_expression <- "`" ("\\" . / [^`])* "`"
  54 + <Canopy.Compiler.CIString>
  55 +
52 56 any_char_expression <- "." <Canopy.Compiler.AnyChar>
53 57
54 58 char_class_expression <- "[" "^"? ("\\" . / [^\]])+ "]"
13 spec/canopy/compiler/string_spec.js
@@ -11,6 +11,7 @@ Canopy.Compiler.StringSpec = JS.Test.describe(Canopy.Compiler.String, function()
11 11 })
12 12
13 13 it('does not parse other strings', function() {
  14 + assertNull( StringTestParser.parse('FOO') )
14 15 assertNull( StringTestParser.parse('bar') )
15 16 })
16 17
@@ -21,5 +22,17 @@ Canopy.Compiler.StringSpec = JS.Test.describe(Canopy.Compiler.String, function()
21 22 it('does not parse the empty string', function() {
22 23 assertNull( StringTestParser.parse('') )
23 24 })
  25 +
  26 + describe('case-insensitive strings', function() {
  27 + before(function() {
  28 + Canopy.compile('grammar CIStringTest\
  29 + string <- `foo`')
  30 + })
  31 +
  32 + it('parses the string it contains', function() {
  33 + assertParse( ['foo', 0, []], CIStringTestParser.parse('foo') )
  34 + assertParse( ['FOO', 0, []], CIStringTestParser.parse('FOO') )
  35 + })
  36 + })
24 37 })
25 38
17 spec/canopy/meta_grammar_parser_spec.js
@@ -85,6 +85,23 @@ function() {
85 85 })
86 86 })
87 87
  88 + describe('with a case-insensitive string rule', function() {
  89 + before(function() {
  90 + this.compiler = new Canopy.Compiler('\
  91 + grammar String \
  92 + string <- `foo` \
  93 + ')
  94 + })
  95 +
  96 + it('compiles a ci-string-rule parser', function() {
  97 + assertEqual(['grammar', 'String',
  98 + ['rule', 'string',
  99 + ['ci-string', 'foo']]],
  100 +
  101 + compiler.toSexp() )
  102 + })
  103 + })
  104 +
88 105 describe('with a maybe string rule', function() {
89 106 before(function() {
90 107 this.compiler = new Canopy.Compiler('\

0 comments on commit 3037fa3

Please sign in to comment.
Something went wrong with that request. Please try again.