mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
with shelling out to javascript
This commit is contained in:
parent
5dd295bd08
commit
f7a0bf19cb
4 changed files with 809 additions and 695 deletions
7
code.jaa
7
code.jaa
|
@ -1,9 +1,9 @@
|
|||
# TODO: switch/case statements
|
||||
# Flow: For loops, etc.
|
||||
# ++ and -- (prefix and postfix)
|
||||
# postfix ifs and unlesses
|
||||
# Fix array comprehensions -- they're mad busted.
|
||||
# Start looking up all free assignments in scope -- to var or not to var.
|
||||
# Literal javascript interpolation.
|
||||
# Think of a name for this crazy thing.
|
||||
|
||||
# Functions:
|
||||
|
@ -65,6 +65,11 @@ wine &&= cheese
|
|||
# Nested property access and calls.
|
||||
((moon.turn(360))).shapes[3].move({x: 45, y: 30}).position
|
||||
|
||||
# Embedded JavaScript.
|
||||
callback(
|
||||
`function(e) { e.stop(); }`
|
||||
)
|
||||
|
||||
# Try/Catch/Finally/Throw.
|
||||
try
|
||||
all_hell_breaks_loose()
|
||||
|
|
48
grammar.y
48
grammar.y
|
@ -10,6 +10,7 @@ token TRY CATCH FINALLY THROW
|
|||
token BREAK CONTINUE
|
||||
token FOR IN WHILE
|
||||
token NEWLINE
|
||||
token JS
|
||||
|
||||
prechigh
|
||||
nonassoc UMINUS NOT '!'
|
||||
|
@ -82,6 +83,7 @@ rule
|
|||
Literal:
|
||||
NUMBER { result = LiteralNode.new(val[0]) }
|
||||
| STRING { result = LiteralNode.new(val[0]) }
|
||||
| JS { result = LiteralNode.new(val[0]) }
|
||||
| REGEX { result = LiteralNode.new(val[0]) }
|
||||
| TRUE { result = LiteralNode.new(true) }
|
||||
| FALSE { result = LiteralNode.new(false) }
|
||||
|
@ -179,16 +181,6 @@ rule
|
|||
| ObjectStart AssignList ObjectEnd { result = ObjectNode.new(val[1]) }
|
||||
;
|
||||
|
||||
ObjectStart:
|
||||
"{" { result = nil }
|
||||
| "{" "\n" { result = nil }
|
||||
;
|
||||
|
||||
ObjectEnd:
|
||||
"}" { result = nil }
|
||||
| "\n" "}" { result = nil }
|
||||
;
|
||||
|
||||
AssignList:
|
||||
/* nothing */ { result = []}
|
||||
| AssignObj { result = val }
|
||||
|
@ -203,12 +195,12 @@ rule
|
|||
;
|
||||
|
||||
Invocation:
|
||||
Value "(" ArgList ")" { result = CallNode.new(val[0], val[2]) }
|
||||
Value ParenStart ArgList ParenEnd { result = CallNode.new(val[0], val[2]) }
|
||||
;
|
||||
|
||||
# An Array.
|
||||
Array:
|
||||
"[" ArgList "]" { result = ArrayNode.new(val[1]) }
|
||||
ArrayStart ArgList ArrayEnd { result = ArrayNode.new(val[1]) }
|
||||
;
|
||||
|
||||
# A list of arguments to a method call.
|
||||
|
@ -244,7 +236,7 @@ rule
|
|||
;
|
||||
|
||||
Parenthetical:
|
||||
"(" Expressions ")" { result = ParentheticalNode.new(val[1]) }
|
||||
ParenStart Expressions ParenEnd { result = ParentheticalNode.new(val[1]) }
|
||||
;
|
||||
|
||||
While:
|
||||
|
@ -260,6 +252,36 @@ rule
|
|||
IF Expression "." { result = ForNode.new(IfNode.new(val[6], Nodes.new([val[0]])), val[2], val[4]) }
|
||||
;
|
||||
|
||||
ObjectStart:
|
||||
"{" { result = nil }
|
||||
| "{" "\n" { result = nil }
|
||||
;
|
||||
|
||||
ObjectEnd:
|
||||
"}" { result = nil }
|
||||
| "\n" "}" { result = nil }
|
||||
;
|
||||
|
||||
ParenStart:
|
||||
"(" { result = nil }
|
||||
| "(" "\n" { result = nil }
|
||||
;
|
||||
|
||||
ParenEnd:
|
||||
")" { result = nil }
|
||||
| "\n" ")" { result = nil }
|
||||
;
|
||||
|
||||
ArrayStart:
|
||||
"[" { result = nil }
|
||||
| "[" "\n" { result = nil }
|
||||
;
|
||||
|
||||
ArrayEnd:
|
||||
"]" { result = nil }
|
||||
| "\n" "]" { result = nil }
|
||||
;
|
||||
|
||||
end
|
||||
|
||||
---- header
|
||||
|
|
10
lexer.rb
10
lexer.rb
|
@ -11,6 +11,7 @@ class Lexer
|
|||
IDENTIFIER = /\A([a-zA-Z$_]\w*)/
|
||||
NUMBER = /\A([0-9]+(\.[0-9]+)?)/
|
||||
STRING = /\A("(.*?)"|'(.*?)')/
|
||||
JS = /\A(`(.*?)`)/
|
||||
OPERATOR = /\A([+\*&|\/\-%=<>]+)/
|
||||
WHITESPACE = /\A([ \t\r]+)/
|
||||
NEWLINE = /\A([\r\n]+)/
|
||||
|
@ -18,6 +19,8 @@ class Lexer
|
|||
CODE = /\A(=>)/
|
||||
REGEX = /\A(\/(.*?)\/[imgy]{0,4})/
|
||||
|
||||
JS_CLEANER = /(\A`|`\Z)/
|
||||
|
||||
# This is how to implement a very simple scanner.
|
||||
# Scan one caracter at the time until you find something to parse.
|
||||
def tokenize(code)
|
||||
|
@ -35,6 +38,7 @@ class Lexer
|
|||
return if identifier_token
|
||||
return if number_token
|
||||
return if string_token
|
||||
return if js_token
|
||||
return if regex_token
|
||||
return if remove_comment
|
||||
return if whitespace_token
|
||||
|
@ -67,6 +71,12 @@ class Lexer
|
|||
@i += string.length
|
||||
end
|
||||
|
||||
def js_token
|
||||
return false unless script = @chunk[JS, 1]
|
||||
@tokens << [:JS, script.gsub(JS_CLEANER, '')]
|
||||
@i += script.length
|
||||
end
|
||||
|
||||
def regex_token
|
||||
return false unless regex = @chunk[REGEX, 1]
|
||||
@tokens << [:REGEX, regex]
|
||||
|
|
Loading…
Reference in a new issue