Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added some grammar combinators.

  • Loading branch information...
commit bc15c6644199235f906119e984d6ab5b49c105e4 1 parent 6343e19
Luke Palmer authored June 16, 2011
1  StructuralEditor.js
@@ -2,7 +2,6 @@
2 2
 
3 3
 StructuralEditor = function($, SF, top_node, event_node) {
4 4
 
5  
-
6 5
 // CodeCatalog Snippet http://www.codecatalog.net/16/3/
7 6
 var elt = function(name, attrs) {
8 7
     var r = $(document.createElement(name));
113  StructuralGrammar.js
... ...
@@ -0,0 +1,113 @@
  1
+// StucturalGrammar : StructuralFramework -> Module
  2
+
  3
+StructuralGrammar = function(SF) {
  4
+
  5
+// CodeCatalog Snippet http://www.codecatalog.net/323/2/
  6
+var for_kv = function(object, body) {
  7
+    for (var k in object) {
  8
+        if (object.hasOwnProperty(k)) {
  9
+            body(k, object[k]);
  10
+        }
  11
+    }
  12
+};
  13
+// End CodeCatalog Snippet
  14
+
  15
+
  16
+// CodeCatalog Snippet http://www.codecatalog.net/378/2/
  17
+var regexp_tokenizer = function(tokens) { 
  18
+    return function(str) {
  19
+        var bestMatch = null;
  20
+        var bestFunc = null; 
  21
+        for_kv(tokens, function(k,v) {
  22
+            var m = new RegExp('^' + k)(str);
  23
+            if (m && (!bestMatch || m[0].length > bestMatch[0].length)) {
  24
+                bestMatch = m;
  25
+                bestFunc = v;
  26
+            }
  27
+        });
  28
+
  29
+        // don't match the whole string in case we are in the middle of typing a token
  30
+        // we use \0 to mean "eof" so this will pass.
  31
+        if (bestFunc && bestMatch[0].length < str.length) {
  32
+            return [bestFunc(bestMatch), str.slice(bestMatch[0].length)];
  33
+        }
  34
+        else {
  35
+            return null;
  36
+        }
  37
+    }
  38
+};
  39
+// End CodeCatalog Snippet
  40
+
  41
+// CodeCatalog Snippet http://www.codecatalog.net/368/1/
  42
+var arguments_to_array = function(argobj) {
  43
+    return Array.prototype.slice.call(argobj);
  44
+};
  45
+// End CodeCatalog Snippet
  46
+
  47
+// A grammar is an object that maps nonterminal names to syntactic forms,
  48
+// where syntactic forms are built up as combinators.
  49
+
  50
+// The final representation returned by these combinators is simply an
  51
+// EClass representing that symbol.
  52
+
  53
+// Our intermediate representation will be a simple open fixed point.
  54
+// Grammar = String -> (Grammar -> EClass).   We will pass the final grammar
  55
+// to a point in the grammar so it can refer to other nonterminals within itself.  
  56
+// As an unintended bonus, we also get grammar inheritance.
  57
+//
  58
+// For the Grammar argument, we'll use a proper function instead of an object
  59
+// so we can do renaming during inheritance.
  60
+
  61
+var $$ = {};
  62
+
  63
+$$.sym = function(name) {
  64
+    return function(grammar) { return grammar(name) }
  65
+};
  66
+
  67
+$$.str = function(cls) {
  68
+    return function(grammar) {
  69
+        return new SF.EClass({
  70
+            cls: cls
  71
+        })
  72
+    }
  73
+};
  74
+
  75
+$$.literal = function(str) {
  76
+    return function(grammar) {
  77
+        return new SF.EClass({
  78
+            make: function() {
  79
+                return this.__proto__.make.call(this, str)
  80
+            }
  81
+        })
  82
+    };
  83
+};
  84
+
  85
+$$.token = function(rx, cls) {
  86
+    return function(grammar) {
  87
+        var toks = {};
  88
+        toks[rx.source] = function(m) { return $$.str(cls)(grammar).make(m[0]) };
  89
+        return SF.Exp_box(cls, regexp_tokenizer(toks));
  90
+    };
  91
+};
  92
+
  93
+$$.seq = function() {
  94
+    var xs = arguments_to_array(arguments);
  95
+    return function(grammar) {
  96
+        return new SF.EClass({
  97
+            make: function() {
  98
+                return this.__proto__.make.apply(
  99
+                    this,
  100
+                    xs.map(function(x) { return x(grammar).make() }))
  101
+            }
  102
+        })
  103
+    };
  104
+};
  105
+
  106
+$$.grammar = function(top, grammar) {
  107
+    var lookup = function(s) { return grammar[s](lookup) };
  108
+    return lookup(top);
  109
+};
  110
+
  111
+return $$;
  112
+
  113
+};
13  demo/structural.html
@@ -3,6 +3,7 @@
3 3
   <script src="jquery.min.js"></script>
4 4
   <script src="../StructuralFramework.js"></script>
5 5
   <script src="../StructuralEditor.js"></script>
  6
+  <script src="../StructuralGrammar.js"></script>
6 7
 
7 8
   <style>
8 9
    .eatom { color: red }
@@ -13,7 +14,7 @@
13 14
   <script>
14 15
 
15 16
 // main : jQuery * StructuralFramework * (top_node -> StructuralEditor) -> Module
16  
-var main = function($, SF, SE) {
  17
+var main = function($, SF, SG, SE) {
17 18
 
18 19
 // CodeCatalog Snippet http://www.codecatalog.net/323/2/
19 20
 var for_kv = function(object, body) {
@@ -56,6 +57,7 @@
56 57
 // End CodeCatalog Snippet
57 58
 
58 59
 
  60
+/*
59 61
 var Exp_eplus_box = SF.Infix_assoc_box('eplus', 
60 62
     'eatom', regexp_tokenizer({
61 63
         '\\d+': function(m) {
@@ -78,8 +80,13 @@
78 80
 var Exp_eatom = new SF.EClass({
79 81
     cls: 'eatom'
80 82
 });
  83
+*/
81 84
 
82  
-var top_node  = Exp_eplus_box.make();
  85
+var top_class = SG.grammar('exp', {
  86
+    'exp': SG.seq(SG.token(/hello/), SG.literal('+'), SG.token(/world/))
  87
+});
  88
+
  89
+var top_node  = top_class.make();
83 90
 var editor = SE(top_node, $(document));
84 91
 
85 92
 $(document.body).append(editor);
@@ -89,9 +96,11 @@
89 96
 
90 97
 jQuery(function() {
91 98
     var SF = StructuralFramework(jQuery);
  99
+    var SG = StructuralGrammar(SF);
92 100
     main(
93 101
         jQuery, 
94 102
         SF,
  103
+        SG,
95 104
         function(top_node, event_node) { 
96 105
             return StructuralEditor(jQuery, SF, top_node, event_node) 
97 106
         }

0 notes on commit bc15c66

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