Skip to content
Browse files

added a README file and other .txt files that contain the wiki's impo…

…rtant info''
  • Loading branch information...
1 parent 6c0a3ab commit 805d1caea6939d218323b35471c2f8414854cae6 @alexwarth committed
Showing with 371 additions and 0 deletions.
  1. +48 −0 Not_Quite_JS.txt
  2. +150 −0 OMeta_Tutorial.txt
  3. +24 −0 README.txt
  4. +149 −0 Things_You_Should_Know.txt
View
48 Not_Quite_JS.txt
@@ -0,0 +1,48 @@
+The language supported in this workspace is not quite JavaScript; it is rather a (large) subset of JavaScript, extended with some
+new syntax.
+
+
+One such extension allows string literals to be written as
+
+ '`' <identifier> or '#' <identifier>
+
+For example, instead of writing
+ "foo"
+you can write
+ `foo
+And of course,
+ "foo" == `foo && `foo == #foo
+
+I did this because I think parse trees, like
+ ["plus", ["lit", 2], ["lit", 5]]
+look better when you write them like this
+ [`plus, [`lit, 2], [`lit, 5]]
+
+
+Another extension is that string literals, as in Smalltalk, can span multiple lines, e.g.,
+
+" this whole thing
+is a string
+yay!
+"
+
+This is useful because it lets you put an entire program into a string (I do this in the Prolog, Logo, and MetaToo projects). Keep in mind that, as in Python, you can put escape sequences inside multi-line strings. So if you want a '\' character inside one of these guys, you need to type '\\'.
+
+And because it's usually annoying to have to escape double quotes inside these big strings, you can also write multi-line string literals in Python-like syntax, e.g.,
+
+"""
+1+2
+alert("hello world")
+"""
+
+
+-Alex
+
+------------------------------------------------------------------------------------------------------------------------------------
+
+Hey, Alex -- How about using a symbol that is less in one's face than "#"? What about tilde ~ or ` or underline, etc.? -- Alan
+
+Hi Alan - this is funny, because the # was inspired by ST-80, heh heh... anyway, I like the idea of using ` instead. Try it now, it works. --- Alex
+
+Hi Alex -- I have always hated that convention in ST-80 (I was not around to protest when that went in). ST-80 had the interesting problem of moving from an environment at PARC in which any glyphs desired could be authored, displayed and printed, to the "outside world" in the early 80s in which none of those things could be done. So they had to go back to ASCII conventions and this was painful. Thanks for the change. --- Alan
+
View
150 OMeta_Tutorial.txt
@@ -0,0 +1,150 @@
+// a simple recognizer, produces no useful value
+
+ometa L {
+ number = digit+,
+ addExpr = addExpr '+' mulExpr
+ | addExpr '-' mulExpr
+ | mulExpr,
+ mulExpr = mulExpr '*' primExpr
+ | mulExpr '/' primExpr
+ | primExpr,
+ primExpr = '(' expr ')'
+ | number,
+ expr = addExpr
+}
+
+L.matchAll('6*(4+3)', 'expr')
+
+
+
+
+
+
+// a recognizer that also interprets
+
+ometa Calc {
+ digit = ^digit:d -> d.digitValue(),
+ number = number:n digit:d -> (n * 10 + d)
+ | digit,
+ addExpr = addExpr:x '+' mulExpr:y -> (x + y)
+ | addExpr:x '-' mulExpr:y -> (x - y)
+ | mulExpr,
+ mulExpr = mulExpr:x '*' primExpr:y -> (x * y)
+ | mulExpr:x '/' primExpr:y -> (x / y)
+ | primExpr,
+ primExpr = '(' expr:x ')' -> x
+ | number,
+ expr = addExpr
+}
+
+Calc.matchAll('6**(4+3)', 'expr')
+
+
+
+
+
+
+// parser and simple interpreter combo
+
+ometa CalcParser {
+ digit = ^digit:d -> d.digitValue(),
+ number = number:n digit:d -> (n * 10 + d)
+ | digit,
+ addExpr = addExpr:x '+' mulExpr:y -> ['add', x, y]
+ | addExpr:x '-' mulExpr:y -> ['sub', x, y]
+ | mulExpr,
+ mulExpr = mulExpr:x '*' primExpr:y -> ['mul', x, y]
+ | mulExpr:x '/' primExpr:y -> ['div', x, y]
+ | primExpr,
+ primExpr = '(' expr:x ')' -> x
+ | number:n -> ['num', n],
+ expr = addExpr
+}
+
+tree = CalcParser.matchAll('6*(4+3)', 'expr')
+
+ometa CalcInterpreter {
+ interp = ['num' anything:x] -> x
+ | ['add' interp:x interp:y] -> (x + y)
+ | ['sub' interp:x interp:y] -> (x - y)
+ | ['mul' interp:x interp:y] -> (x * y)
+ | ['div' interp:x interp:y] -> (x / y)
+}
+
+CalcInterpreter.match(tree, 'interp')
+
+
+
+
+
+
+
+// we can write a "compiler" instead
+
+ometa CalcCompiler {
+ comp = ['num' anything:x] -> x.toString()
+ | ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')')
+ | ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')')
+ | ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')')
+ | ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
+}
+
+code = CalcCompiler.match(tree, 'comp')
+eval(code)
+
+
+
+
+
+
+
+
+
+
+
+
+// spice things up with ML-like syntax
+
+ometa CalcCompiler {
+ comp ['num' anything:x] -> x.toString(),
+ comp ['add' comp:x comp:y] -> ('(' + x + '+' + y + ')'),
+ comp ['sub' comp:x comp:y] -> ('(' + x + '-' + y + ')'),
+ comp ['mul' comp:x comp:y] -> ('(' + x + '*' + y + ')'),
+ comp ['div' comp:x comp:y] -> ('(' + x + '/' + y + ')')
+}
+
+code = CalcCompiler.match(tree, 'comp')
+eval(code)
+
+
+
+
+
+
+
+
+
+
+
+
+// a neat trick: dispatch on node tags using higher-order rule "apply"
+
+ometa CalcCompiler {
+ comp [anything:t apply(t):ans] -> ans,
+ num anything:x -> x.toString(),
+ add comp:x comp:y -> ('(' + x + '+' + y + ')'),
+ sub comp:x comp:y -> ('(' + x + '-' + y + ')'),
+ mul comp:x comp:y -> ('(' + x + '*' + y + ')'),
+ div comp:x comp:y -> ('(' + x + '/' + y + ')')
+}
+
+code = CalcCompiler.match(tree, 'comp')
+eval(code)
+
+
+
+
+
+
+
+
View
24 README.txt
@@ -0,0 +1,24 @@
+The following files contain some important info:
+
+* Not_Quite_JS.txt explains the difference between "real" JavaScript and
+ the JavaScript that can be used in the OMeta/JS Workspace.
+
+* Things_You_Should_Know.txt explains the differences between the original
+ OMeta syntax (as it appeared in the DLS'07 paper) and the newer OMeta/js
+ syntax.
+
+* OMeta_Tutorial.txt contains a bunch of examples that show how OMeta
+ can be used for pattern matching, parsing, etc.
+
+Another good resource for OMeta programmers is the OMeta mailing list. To
+subscribe, please visit:
+
+ http://vpri.org/mailman/listinfo/ometa
+
+And you can also browse the archives of the mailing list at:
+
+ http://vpri.org/pipermail/ometa/
+
+Cheers,
+Alex
+
View
149 Things_You_Should_Know.txt
@@ -0,0 +1,149 @@
+OMeta/JS is a new version of OMeta, a language for pattern-directed metaprogramming first described in
+
+ Alessandro Warth and Ian Piumarta, "OMeta: An Object-Oriented Language for Pattern-Matching," in Proceedings of the Dynamic
+ Languages Symposium, 2007. (Available at http://www.cs.ucla.edu/~awarth/papers/dls07.pdf)
+
+This page contains the information necessary for someone who has read the OMeta paper to be able to use OMeta/JS.
+
+
+Pattern Syntax
+--------------
+
++------------------------------------------------------------------------+
+| "kind of thing" OMeta OMeta/JS |
++------------------------------------------------------------------------+
+| boolean true true |
+| number 123 123 |
+| character 'x' 'x' | (see note #1)
+| string "foo" 'foo' |
+| `foo |
+| #foo |
+| atom foo N/A |
+| rule application <expr> expr |
+| <r x y> r(x, y) | (see note #3)
+| <super stmt> super(`stmt) | (see note #4)
+| list ("hello" 42 answer ()) ['hello' 42 `answer []] |
+| negation ~'x' ~'x' |
+| look-ahead ~~'x' ~~'x' |
+| &'x' |
+| semantic predicate ?(> x y) ?(x > y) | (see note #2)
+| semantic action => (+ x y) -> (x + y) |
+| !(+ x y) !(x + y) |
+| binding <expr>:x expr:x | (in OMeta/JS, spaces are not allowed before the colon)
+| :x | (this is shorthand for "anything:x")
++------------------------------------------------------------------------+
+
+
+Note #1: There is no such thing as a character in JavaScript. Even though the language lets you access each "character" of a string via indexing, e.g, "foo"[0], the answer is not a character, but rather a string of length 1.
+
+
+Note #2: In the version of OMeta described in the paper, semantic actions and predicates were written in COLA (kind of a mix between Scheme and Smalltalk). In OMeta/JS, they are written in JavaScript. More specifically, they are either primary expressions, e.g.,
+
+ 123
+ x
+ foo.bar()
+ new Person()
+ (x + y) // note that you need parentheses around "x + y" in order to make it into a primary expression
+
+or something I made up called "statement expressions", which have the form
+
+ "{" <statement>* <expr> "}"
+
+For example,
+
+ { x += 2; y = "foo"; f(x) }
+
+The value of a statement expression is equal to that of its last expression.
+
+
+Note #3: The arguments you pass to a rule don't have to be statement expressions - they can be any JavaScript expression.
+
+Note #4: In OMeta/JS, "super" is just like any other rule (not a special form), so you have to quote the rule name that you pass in as an argument.
+
+
+A "Handy" New Shorthand
+-----------------------
+
+In OMeta/JS, the pattern
+
+ "foo"
+
+does not match the string 'foo'; it is instead shorthand for
+
+ token('foo')
+
+The Parser grammar provides a definition for token that skips any number of spaces, then tries to match the sequence of characters that was passed to it as an argument. I have used this in many of the example projects, and have found it to be very useful.
+
+Still, there are times when this is not what you want. But that's not a problem, because you can define it to do whatever you want (see the JavaScript Compiler project for an example).
+
+
+Rules
+-----
+
+Here is a parameterized rule taken from the paper, in the original OMeta syntax:
+
+ cRange x y ::= <char>:c ?(>= c x)
+ ?(<= c y) => c;
+
+And here is the same rule rule, in the new OMeta/JS syntax:
+
+ cRange :x :y = char:c ?(c >= x)
+ ?(c <= y) -> c
+
+
+A couple of (purely syntactic) differences:
+
+(1) rule declarations now use "=" instead of "::=", and
+(2) they are no longer terminated with a ";"
+
+
+A more significant difference has to do with the rule's arguments; note that in the OMeta/JS version, they are preceded by a ':'. This is actually shorthand for
+
+ cRange anything:x anything:y = ...
+
+This change has to do with an improvement in the parameter-passing mechanism, which now allows a rule's parameters to be pattern-matched against. (See the paper's "Future Work" section for more details.)
+
+The "=" is actually optional in rule declarations... this, combined with some new syntax that allows a rule to have multiple definitions that are tried in lexicographic order, allows programmers to write rules that have an "ML flavor":
+
+ ometa M {
+ fact 0 -> 1,
+ fact :n ?(n > 0) fact(n - 1):m -> (n * m)
+ }
+ M.match(5, "fact")
+
+
+Grammar Syntax
+--------------
+
+The only change here has to do with rule declarations, which now must be separated by commas:
+
+ ometa M {
+ x = y z,
+ y = "foo" "bar",
+ z = "baz"
+ }
+
+
+Using Grammars "from the outside"
+----------------------------------
+
+The public interface provided by an OMeta/JS grammar object to the rest of the world consists of two methods:
+
+ match(object, ruleName)
+
+and
+
+ matchAll(arrayOrStringObject, ruleName)
+
+
+Here's an example that hopefully explains the difference between the two. The key to understanding it is that a string is just a list of characters.
+
+ ometa M <: Parser {
+ theCharacters = "the" "cat" "sat" "on" "the" "mat",
+ theWholeString = [theCharacters]
+ }
+
+ input = "the cat sat on the mat"
+ M.matchAll(input, "theCharacters")
+ M.match(input, "theWholeString")
+

0 comments on commit 805d1ca

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