Created
October 23, 2009 08:17
-
-
Save devyn/216743 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Distributed OS, Language Prototype II (Treetop) | |
# With Documentation | |
require 'rubygems' | |
require 'treetop' | |
module DiOS | |
grammar LangProto2 | |
# The main scope of a file. It's also the body of a thing! | |
rule ether | |
thing_body | |
end | |
# Anything. Can be an "atom," "thing," or "action." | |
rule anything | |
atom / thing / action | |
end | |
# See thing_body | |
rule thing | |
'(' thing_body ')' | |
end | |
# [ ... ] is for expressions | |
# %[ ... ] is for closures | |
rule action | |
'%[' action_body ']' / | |
'[' action_body ']' | |
end | |
# Holy crap. Okay, so, let me give a few definitions here: | |
# ---------------------- | |
# nil (or null) is a thing with no value. like a void. | |
# true (or yes) is sorta like a proton. it has a positive charge. | |
# false (or no) is like an electron. it has a negative charge. | |
# ---------------------- | |
# IMPORTANT: The only values considered negative are nil and false. Like Ruby. | |
# ---------------------- | |
# self refers to the current scope. can often be omitted (like watashi in Japanese). | |
# ^ refers to the arguments passed to this scope. only for closures and their children. if no arguments were passed, returns (). | |
# \ refers to the top level scope (or 'ether'). for example: [\ system] -- refers to the "system" message of the ether. | |
# !! is a special message. See the note for it in "message" for more information. | |
# obviously, numbers are allowed. decimal: 73_891_033 octal: 0755 hexadecimal: 0xDEAD binary: 0b10010110 | |
# strings: "#[name] is a #[fruit]" or 'I am dead' (similar rules to Ruby) | |
# regexp: Same as Ruby, without of the 'o' flag. | |
# word: like an Erlang 'atom.' most useful for message passing. | |
rule atom | |
('nil' / 'null') | |
/ ('true' / 'yes') | |
/ ('false' / 'no') | |
/ 'self' | |
/ '^' | |
/ "\\" | |
/ "!!" | |
/ ("0" [0-7]+ / "0x" [0-9A-Fa-f]+ / "0b" [01]+ / [0-9_]+) | |
/ '"' (action_embed / escape_code / !'"' .)+ '"' | |
/ "'" ("\\\\" / "\\'" / "\\" . / !"'" .)+ "'" | |
/ "/" rxp_body "/" rxp_flag* | |
/ [A-Za-z_] [A-Za-z0-9_]* | |
end | |
# NOTE: Repeating [+-*/] means "make it permanent," like [+-*/] '=' in a lot of languages. | |
# Example: player points ++ 10 | |
# (ruby) player.points += 10 | |
# NOTE: Messages are by default passed to "self." If the message gets no response in "self," the parent scope is tried. | |
# If you want to be sure you're sending a message to the top level, you can use "\" | |
# If nothing responds to a message, an error will be issued. | |
# NOTE: Errors, return focus, etc. | |
# The "->" or "return value" operator does *not* return focus to the caller. Instead it just sets the return value. That's all. | |
# Because of this, the "!!" special message has a few interesting behaviours. | |
# 1) Return focus / jumping: "!!" by itself, with no parameters, will immediately return to the caller. Example: | |
# -> ^ base exp([^ exponent];). !!. -- return "base to the power of exponent" and jump to caller | |
# 2) Errors: "!!(error: (code: <atom> description: <atom>))" will not only return to the caller, | |
# but also send an error to the caller. Example: | |
# raise_error: %[ | |
# !!(error: (code: IntentionalError description: "This error was intentionally set.")) | |
# ] | |
# 3) Error handling: Yes, the error message itself also handles errors. Example: | |
# !!( | |
# try: %[ | |
# -- error prone code goes here | |
# ] | |
# fail: ( | |
# RuntimeError: %[ | |
# -- respond to errors with code RuntimeError (can also be a list-thing) | |
# ] | |
# nil: %[ | |
# -- respond to any other errors not mentioned above | |
# ] | |
# ) | |
# ensure: %[ | |
# -- optionally, what you want to make sure (no matter what) gets run. | |
# ] | |
# ) | |
# NOTE: On arguments... The argument message "^" returns the thing that was passed to this closure. | |
# If there are no arguments to this scope, the parent scope is tried, and so on. | |
# If no arguments can be found, this is equal to "nil" | |
# NOTE: Argument from existing thing: | |
# send: %[^ object [^ message][^ arguments]] | |
# [send(object: [console] message: out arguments: (line: "Hello, world!"))] | |
# NOTE: Mixins are used to do pretty much everything... (by default the "system defaults" thing is mixed in to everything) | |
# to mix a thing into another thing: | |
# | |
# [self ++[HTTP Server]]. -- extend / mix in "HTTP Server" | |
# [self ++(property: value)]. -- mix in (property: value) which is the standard way of adding a message dynamically, | |
# could also be shortened to ++(property: value). in the middle of an action. | |
# | |
# example: | |
# [system defaults ++( | |
# send: %[ | |
# ^ require( message; ). | |
# self [^ at(index: 1)][^ at(start: 2 end: -1)]. | |
# ] | |
# ]. | |
# [console send(out; line: "Hello, world!")]. | |
rule message | |
( | |
anything (thing/action)? / | |
([+-*/] [+-*/]? / [<>=!&|] '='? / "&&" / "||") whitespace? anything | |
) / | |
(whitespace &(message) / "") | |
end | |
# any length of messages, optionally with the "return value" operator. | |
rule messages | |
whitespace? ('->' whitespace?)? message+ whitespace? | |
end | |
# NOTE: (x: nil) is equal to (x;) | |
# Just a bit of syntactic sugar for lists :D | |
# ( | |
# message1: "Hello, world!" | |
# "AAAA"; | |
# []. | |
# ) | |
rule thing_body | |
whitespace? | |
( | |
whitespace? | |
anything ':' whitespace? | |
anything | |
whitespace? | |
/ | |
whitespace? | |
anything ';' | |
whitespace? | |
/ | |
whitespace? | |
anything '.' | |
whitespace? | |
)* | |
whitespace? | |
end | |
# Message lists separated by periods. Optionally, | |
# you may have a period at the last message list, but it isn't required. | |
# It may or may not make your code look better, and depends on your style. | |
rule action_body | |
whitespace? messages:(messages ('.' whitespace? &messages / '.'?))+ whitespace? | |
end | |
# Well, actually, comments count as whitespace as well :D | |
rule whitespace | |
(block_comment / line_comment / [\s]+)+ | |
end | |
# --[ block comments can appear anywhere ]-- | |
rule block_comment | |
"--[" (!"]--" .)* "]--" | |
end | |
# -- line comments can only appear at the ends of lines. | |
rule line_comment | |
"--" [^\n]* | |
end | |
# Standard escape codes you should be familiar with. Moving on... | |
rule escape_code | |
"\\" ( | |
[\\"abrnstfe] / | |
"x" [0-9A-Fa-f] [0-9A-Fa-f] / | |
[0-7] [0-7] [0-7] / | |
. | |
) | |
end | |
# Like #{ ... } in Ruby, we use #[ ... ]. Duh! | |
rule action_embed | |
'#[' action_body ']' | |
end | |
# Standard regexp syntax. A few weird quirks are in here, and need to be ironed out. | |
rule rxp_body | |
( | |
rxp_escape_code / | |
"[" ( | |
(rxp_escape_code / [^/]) | |
'-' | |
(rxp_escape_code / [^/]) | |
)* "]" / | |
"(" rxp_body ")" / | |
"{" [0-9]+ ("," [0-9]+)? "}" / | |
"\\Q" (rxp_escape_code / !"\\E" !'/' .)* "\\E" / | |
[*+?] / | |
[\^$] / | |
"|" / | |
(!"/" .)+ | |
)* | |
end | |
# Regexp escapes. | |
rule rxp_escape_code | |
"\\" ( | |
[\\/arnstfe] / | |
[\[\^$.|?*+(){}\]] / | |
[dDsSwWbBAZ] / | |
"x" [0-9A-Fa-f] [0-9A-Fa-f] / | |
[0-7] [0-7] [0-7] / | |
. | |
) | |
end | |
# Regexp flags. i, m, and x. Equal to Ruby. | |
rule rxp_flag | |
[imx] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment