liquidscript 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8099fbffde0b4c86f743c1eeb2f7945876bda79
4
- data.tar.gz: 61440eea14db6d81cff6245c03916e58092f310e
3
+ metadata.gz: 2630a75e954ba63bc5da7e92040fc2fce164236b
4
+ data.tar.gz: 92fca33ae8fec68d082e16ba4431f873c8b251c0
5
5
  SHA512:
6
- metadata.gz: d58710b0697834bfa1501061adc3d9d0492206d71c24d8886a769e451dadff2e41bdcc527d8629fb4522ff92cb2a9e423ee96eb1559d7fc5370c04a3bbfd3262
7
- data.tar.gz: 9552101c9846bde2f34eebedcf1e4dcd1fa4da268c3e563331e2872ad0d9d5d21ea82296c79044265cdc0f01023fb3333542c99ed52d312cb30e9b40fed3afa9
6
+ metadata.gz: 207d7676f032a4a00237f49c99d5feacb351ff7462b6354e240ce27e32d10f0eba5f787b116b2a91eed5893fe77d2f0754c8922dfda2867050ec7695cfa380ad
7
+ data.tar.gz: 29c50870b4ed865a79ab1939b38b568353f65746ca9f3e73a6f1a01880d47f80463d1ba0e5706c9529aa56b1392d56efc19f2164db7b94b5ddecd1e4fa2469f6
data/DOCS.md ADDED
@@ -0,0 +1,228 @@
1
+ # ![Liquidscript](http://i.imgur.com/xbdhTsr.png)
2
+
3
+ **A javascript-based language that compiles to javascript.** It compiles directly to javascript, requiring no runtime libraries. It means to take away the awkwardness of javascript, but keep the very essence and ideals of javascript. It incorporates some of the most well-used concepts, and allows you to write the code as you like.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'liquidscript'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install liquidscript
18
+
19
+ ## Syntax
20
+
21
+ Liquidscript has a very similar syntax to Javascript.
22
+
23
+ # This is a comment
24
+ something = 2
25
+ some_string = something.toString()
26
+
27
+ if(some_string == '2) {
28
+ console.log("It lives!")
29
+ }
30
+
31
+ The thing that should stand out to you the most there is the lack of an end quote to the single quotes in the if conditional. This is on purpose - a ending single quote is optional.
32
+
33
+ Note that there are also no semicolons (they don't exist in the language), and no `var` statement. The `var` statement is made automagically by liquidscript, so you don't have to.
34
+
35
+ ### Literals
36
+
37
+ #### String
38
+
39
+ Liquidscript has a very finite set of string literals - the only two options (so far) are double quotes and single quotes. There are plans to introduce heredocs. Double quotes are multiline, whereas **single quotes are limited to the same characters that identifiers are limited to**. This is so that keys for objects (in the `object[key]` syntax feels more natural (i.e., `object['key]`). Some examples:
40
+
41
+ string = "hello
42
+
43
+ world" # this'll translate to "hello\n\nworld"
44
+
45
+ single = 'test # there doesn't need to be an endquote here.
46
+
47
+ That's it!
48
+
49
+ #### Functions
50
+
51
+ Functions are defined using the arrow syntax:
52
+
53
+ some_function = -> {}
54
+
55
+ Brackets are **not** optional. The parameter list before the arrow, however, is. If you want something like coffeescript's fat arrow syntax, something like the following would have to be done:
56
+
57
+ self = this
58
+
59
+ some_function = -> {
60
+ # Change this to whatever property you wanted.
61
+ self.whatever
62
+ }
63
+
64
+ A parameter list works exactly like you'd expect:
65
+
66
+ some_function = (a, b, c)-> {
67
+ console.log(a, b, c)
68
+ }
69
+
70
+ some_function(1, 2, 3)
71
+
72
+ #### Numeric
73
+
74
+ There are numbers in liquidscript as well. It follows the JSON spec on this to the letter.
75
+
76
+ some_number = -2e+5
77
+
78
+ #### Array, Object
79
+
80
+ Arrays and objects are exactly like in javascript:
81
+
82
+ array = [1, "test", 'foo, bar]
83
+
84
+ object = {
85
+ test: "hello",
86
+ foo: "world" # a colon here is allowed
87
+ }
88
+
89
+ ### Controls
90
+
91
+ Liquidscript has control statements like `if`, and `else`. Liquidscript uses `elsif` instead of `else if`.
92
+
93
+ if(some_variable == 2) {
94
+ console.log("It's 2!")
95
+ } elsif(some_variable == 3) {
96
+ console.log("It's a 3!")
97
+ } else {
98
+ console.log("I don't know what it is!")
99
+ }
100
+
101
+ Liquidscript lacks `for`, `switch`, and `while`, but they will be added as well.
102
+
103
+ ### Classes and Modules
104
+
105
+ #### Modules
106
+ This is where liquidscript gets interesting, in my opinion. Modules are extreme syntaxic sugar:
107
+
108
+ module SomeModule {
109
+ VERSION: "1.7.0"
110
+ }
111
+
112
+ SomeModule.VERSION # => 1.7.0
113
+
114
+ That compiles directly to:
115
+
116
+ var SomeModule;
117
+ SomeModule = {
118
+ VERSION: "1.7.0"
119
+ };
120
+
121
+ SomeModule.VERSION; // => 1.7.0
122
+
123
+ The point of modules, however, is to bind code together into units, in an easier to read syntax. Commas are not needed between definitions, and other modules and classes can be defined within modules.
124
+
125
+ module SomeModule {
126
+ module OtherModule {
127
+ VERSION: "1.7.0"
128
+ VERSION_MAJOR: 1
129
+ VERSION_MINOR: 7
130
+ VERSION_PATCH: 0
131
+
132
+ version: -> {
133
+ return SomeModule.OtherModule.VERSION.split('.')
134
+ }
135
+ }
136
+ }
137
+
138
+ Which compiles directly to:
139
+
140
+ var SomeModule, OtherModule;
141
+
142
+ SomeModule = {
143
+ OtherModule: {
144
+ VERSION: "1.7.0",
145
+ VERSION_MAJOR: 1,
146
+ VERSION_MINOR: 7,
147
+ VERSION_PATCH: 0,
148
+ version: function() {
149
+ return SomeModule.OtherModule.VERSION.split('.');
150
+ }
151
+ }
152
+ };
153
+
154
+ #### Classes
155
+
156
+ Classes are meant to be instantized with the `new` keyword. They are defined very similarly to modules, but when values are defined, they default to being defined on the instance of the class:
157
+
158
+ class Greeter {
159
+ # This is a special function that is called whenever a
160
+ # new greeter is created.
161
+ initialize: (name)-> {
162
+ this.name = name
163
+ }
164
+
165
+ greet: -> {
166
+ console.log("Hello %s!", this.name)
167
+ }
168
+ }
169
+
170
+ new Greeter("Alice").greet()
171
+
172
+ This would translate directly to this:
173
+
174
+ var Greeter;
175
+
176
+ Greeter = function Greeter() {
177
+ if(this.initialize) {
178
+ this.initialize.apply(this, arguments);
179
+ }
180
+ };
181
+
182
+ Greeter.prototype.initialize = function(name) {
183
+ this.name = name;
184
+ };
185
+
186
+ Greeter.prototype.greet = function() {
187
+ console.log("Hello %s!", this.name);
188
+ };
189
+
190
+ new Greeter("Alice").greet()
191
+
192
+ This uses the functional prototype system in order to create instances of classes. Inheritance is not yet supported, but there will be progress towards it.
193
+
194
+ If you want a method defined on the class itself instead of the instance, prefix the function name with `this`:
195
+
196
+ class Greeter {
197
+ # This is a special function that is called whenever a
198
+ # new greeter is created.
199
+ initialize: (name)-> {
200
+ this.name = name
201
+ }
202
+
203
+ greet: -> {
204
+ console.log("Hello %s!", this.name)
205
+ }
206
+
207
+ self.meet: (first, second)-> {
208
+ new Greeter(first).greet()
209
+ new Greeter(second).greet()
210
+ }
211
+ }
212
+
213
+ Greeter.meet("Alice", "Bob")
214
+
215
+ This translates roughly to:
216
+
217
+ // ...
218
+
219
+ Greeter.meet = function(first, second) {
220
+ new Greeter(first).greet()
221
+ new Greeter(second).greet()
222
+ }
223
+
224
+ // ...
225
+
226
+ # The End!
227
+
228
+ That wraps it all up! If you're interested in more, checkout the [github repository](https://github.com/redjazz96/liquidscript) and read the documentation.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Liquidscript
1
+ # ![Liquidscript](http://i.imgur.com/xbdhTsr.png)
2
2
 
3
3
  [![Build Status](https://travis-ci.org/redjazz96/liquidscript.png?branch=master)](https://travis-ci.org/redjazz96/liquidscript) [![Coverage Status](https://coveralls.io/repos/redjazz96/liquidscript/badge.png?branch=master)](https://coveralls.io/r/redjazz96/liquidscript?branch=master) [![Code Climate](https://codeclimate.com/github/redjazz96/liquidscript.png)](https://codeclimate.com/github/redjazz96/liquidscript)
4
4
 
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "liquidscript"
4
+
5
+ if ARGV.length < 1
6
+ puts "Usage: #{File.basename($0)} infile [outfile]"
7
+ exit 1
8
+ end
9
+
10
+ infile = ARGV.shift
11
+ outfile = ARGV.shift || infile.gsub(/\.ls\Z/, ".js")
12
+
13
+ File.open(infile, "r") do |f|
14
+ out = Liquidscript::Template.new(f.read).render
15
+
16
+ File.open(outfile, "w") { |f| f.write out }
17
+ end
@@ -5,7 +5,12 @@ require "liquidscript/version"
5
5
  require "liquidscript/scanner"
6
6
  require "liquidscript/compiler"
7
7
  require "liquidscript/generator"
8
+ require "liquidscript/template"
8
9
 
9
10
  module Liquidscript
10
- # Your code goes here...
11
+ def compile(data)
12
+ compiler = Compiler::ICR.new(Scanner.new(data))
13
+ compiler.compile
14
+ Generate::Javascript.new(compiler.top)
15
+ end
11
16
  end
@@ -83,6 +83,75 @@ module Liquidscript
83
83
  types.any? { |type| peek.type == type }
84
84
  end
85
85
 
86
+ # @overload collect_compiles(compile, *end_on)
87
+ # Calls the method `:compile_#{compile}` for every peeked
88
+ # token that isn't a part of `end_on`. Once it encounters
89
+ # that, it returns the values of all of those calls. If the
90
+ # last element of `end_on` is a Hash, it is merged with the
91
+ # default actions that this takes and passes it to `expect`.
92
+ #
93
+ # @example
94
+ # def compile_if
95
+ # shift :if
96
+ # shift :lparen
97
+ # conditional = compile_expression
98
+ # shift :rparen
99
+ # shift :lbrack
100
+ # body = collect_compiles(:expression, :rbrack)
101
+ # [:if, conditional, body]
102
+ # end
103
+ # @param compile [Symbol] the method to call.
104
+ # @param end_on [Array<Symbol>] an array of symbols to end
105
+ # the loop.
106
+ # @return [Array<Object>]
107
+ #
108
+ # @overload collect_compiles(*end_on, &block)
109
+ # Calls the block for every peeked token that isn't in
110
+ # `end_on`. Once it encounters a token that it, it returns
111
+ # the value of all of the block calls. If the
112
+ # last element of `end_on` is a Hash, it is merged with the
113
+ # default actions that this takes and passes it to `expect`.
114
+ #
115
+ # @example
116
+ # collect_compiles(:test) { shift :_ }
117
+ #
118
+ # @yieldreturn The value you want to be placed in the
119
+ # array.
120
+ # @param end_on [Array<Symbol>] an array of symbols to end
121
+ # the loop.
122
+ # @return [Array<Object>] the results of all of the block
123
+ # calls.
124
+ def collect_compiles(*end_on)
125
+ compiles = []
126
+
127
+ if block_given?
128
+ compile = Proc.new
129
+ else
130
+ compile = end_on.shift
131
+ end
132
+
133
+ block = Callable.new(self, compile)
134
+
135
+ hash = if end_on.last.is_a? Hash
136
+ end_on.pop.dup
137
+ else
138
+ {}
139
+ end
140
+
141
+ do_compile = action do
142
+ compiles << block.call
143
+ end
144
+
145
+ hash.merge! end_on => action.end_loop,
146
+ :_ => do_compile
147
+
148
+ loop do
149
+ expect hash
150
+ end
151
+
152
+ compiles
153
+ end
154
+
86
155
  # The meat and potatos of the compiler. This maps actions to
87
156
  # tokens. In its basic form, it is passed a hash, with the
88
157
  # keys being token types, and the values the corresponding
@@ -176,7 +245,7 @@ module Liquidscript
176
245
  # @return [Hash]
177
246
  def normalize_arguments(args)
178
247
  hash = if args.last.is_a? Hash
179
- args.pop
248
+ args.pop.dup
180
249
  else
181
250
  {}
182
251
  end
@@ -14,8 +14,6 @@ module Liquidscript
14
14
  include Classes
15
15
  include Helpers
16
16
 
17
- always :keyword
18
-
19
17
  # (see Base#reset!)
20
18
  def reset!
21
19
  @top = Liquidscript::ICR::Set.new
@@ -33,7 +31,7 @@ module Liquidscript
33
31
  #
34
32
  # @return [ICR::Code]
35
33
  def compile_start
36
- expect :class, :module, :_ => :expression
34
+ compile_expression
37
35
  end
38
36
  end
39
37
  end
@@ -29,7 +29,7 @@ module Liquidscript
29
29
  compile_object = action do
30
30
  components << [
31
31
  _compile_class_body_key(mod),
32
- compile_expression
32
+ compile_vexpression
33
33
  ]
34
34
  end
35
35
 
@@ -8,12 +8,36 @@ module Liquidscript
8
8
  #
9
9
  # @return [ICR::Code]
10
10
  def compile_expression
11
- expect :number, :identifier,
12
- :dstring, :lparen,
13
- :sstring, :keyword,
14
- :lbrack => :object,
15
- :lbrace => :array,
16
- :arrow => :function
11
+ expect :if, :unless, :class, :module, :_ => :vexpression
12
+ end
13
+
14
+ # Compiles an expression that returns a value.
15
+ #
16
+ # @return [ICR::Code]
17
+ def compile_vexpression
18
+ out = expect :number, :identifier,
19
+ :dstring, :lparen,
20
+ :sstring, :operator,
21
+ :keyword, :unop,
22
+ :lbrack => :object,
23
+ :lbrace => :array,
24
+ :arrow => :function
25
+
26
+ if peek? :binop
27
+ compile_binop out
28
+ elsif peek? :prop
29
+ compile_property(out)
30
+ else
31
+ out
32
+ end
33
+ end
34
+
35
+ def compile_binop(left)
36
+ code :binop, shift(:binop), left, compile_vexpression
37
+ end
38
+
39
+ def compile_unop
40
+ code :unop, shift(:unop), compile_vexpression
17
41
  end
18
42
 
19
43
  # Handles an assignment of the form `identifier = expression`,
@@ -23,7 +47,7 @@ module Liquidscript
23
47
  # @return [ICR::Code]
24
48
  def compile_assignment(identifier)
25
49
  shift :equal
26
- value = compile_expression
50
+ value = compile_vexpression
27
51
 
28
52
  if identifier.type == :identifier
29
53
  variable = set(identifier)
@@ -52,7 +76,7 @@ module Liquidscript
52
76
 
53
77
  expression = action do
54
78
  maybe_func = 0
55
- components << compile_expression
79
+ components << compile_vexpression
56
80
  end
57
81
 
58
82
  loop do
@@ -88,6 +112,44 @@ module Liquidscript
88
112
  end
89
113
  end
90
114
 
115
+ [:if, :elsif].each do |key|
116
+ define_method(:"compile_#{key}") do
117
+ shift key
118
+ shift :lparen
119
+ conditional = compile_vexpression
120
+ shift :rparen
121
+ shift :lbrack
122
+
123
+ body = collect_compiles(:expression, :rbrack)
124
+
125
+ if peek?(:elsif, :else)
126
+ code key, conditional, body, expect(:elsif, :else)
127
+ else
128
+ code key, conditional, body
129
+ end
130
+ end
131
+ end
132
+
133
+ def compile_unless
134
+ shift :unless
135
+ shift :lparen
136
+ conditional = compile_vexpression
137
+ shift :rparen
138
+ shift :lbrack
139
+
140
+ body = collect_compiles(:expression, :rbrack)
141
+ code :unless, conditional, body
142
+ end
143
+
144
+ def compile_else
145
+ shift :else
146
+ shift :lbrack
147
+
148
+ body = collect_compiles(:expression, :rbrack)
149
+
150
+ code :else, body
151
+ end
152
+
91
153
  end
92
154
  end
93
155
  end
@@ -6,7 +6,7 @@ module Liquidscript
6
6
  def compile_property(prop)
7
7
  shift :prop
8
8
 
9
- ref = if prop.type == :identifier
9
+ ref = if [:identifier, :class, :module].include?(prop.type)
10
10
  ref(prop)
11
11
  else
12
12
  prop
@@ -16,7 +16,8 @@ module Liquidscript
16
16
  code :property, ref, ident
17
17
  end
18
18
 
19
- code = expect :identifier => property
19
+ # Just in case there is a property named 'class' or 'module'
20
+ code = expect [:identifier, :class, :module] => property
20
21
 
21
22
  expect :lparen => action { compile_call(code) },
22
23
  :equal => action { compile_assignment(code) },
@@ -26,13 +27,9 @@ module Liquidscript
26
27
 
27
28
  def compile_call(subject)
28
29
  shift :lparen
29
- arguments = []
30
30
 
31
- loop do
32
- expect :comma => action.shift,
33
- :rparen => action.end_loop,
34
- :_ => action { arguments << compile_expression }
35
- end
31
+ arguments = collect_compiles :expression, :rparen,
32
+ :comma => action.shift
36
33
 
37
34
  code :call, subject, *arguments
38
35
  end
@@ -26,22 +26,20 @@ module Liquidscript
26
26
  code :sstring, pop.value[1..-1]
27
27
  end
28
28
 
29
+ def compile_operator
30
+ code :operator, shift(:operator), compile_vexpression
31
+ end
32
+
29
33
  def compile_keyword
30
- code :keyword, shift(:keyword), compile_expression
34
+ code :keyword, shift(:keyword)
31
35
  end
32
36
 
33
37
  def compile_object
34
38
  shift :lbrack
35
39
 
36
- objects = []
37
- compile_object = action do
38
- objects << [compile_object_key, compile_expression]
39
- end
40
-
41
- loop do
42
- expect :rbrack => action.end_loop,
43
- :comma => action.shift,
44
- [:identifier, :dstring] => compile_object
40
+ objects = collect_compiles :rbrack,
41
+ :comma => action.shift do
42
+ [compile_object_key, compile_vexpression]
45
43
  end
46
44
 
47
45
  code :object, objects
@@ -50,14 +48,8 @@ module Liquidscript
50
48
  def compile_array
51
49
  shift :lbrace
52
50
 
53
- parts = []
54
- compile_part = action { parts << compile_expression }
55
-
56
- loop do
57
- expect :rbrace => action.end_loop,
58
- :comma => action.shift,
59
- :_ => compile_part
60
- end
51
+ parts = collect_compiles(:vexpression, :rbrace,
52
+ :comma => action.shift)
61
53
 
62
54
  code :array, parts
63
55
  end
@@ -73,17 +65,17 @@ module Liquidscript
73
65
  compile_function_with_parameters([])
74
66
  end
75
67
 
76
- def compile_function_with_parameters(parameter)
68
+ def compile_function_with_parameters(parameters)
77
69
  shift :arrow
78
70
  shift :lbrack
79
71
 
80
72
  expressions = Liquidscript::ICR::Set.new
81
73
  expressions.context = Liquidscript::ICR::Context.new
82
74
  expressions.context.parent = top.context
83
- expressions[:arguments] = parameter
75
+ expressions[:arguments] = parameters
84
76
  @set << expressions
85
77
 
86
- parameter.each do |parameter|
78
+ parameters.each do |parameter|
87
79
  set(parameter).parameter!
88
80
  end
89
81
 
@@ -3,6 +3,15 @@ module Liquidscript
3
3
  class Javascript < Base
4
4
  module Literals
5
5
 
6
+ BINOP_SWITCH = {
7
+ "==" => "===",
8
+ "===" => "==",
9
+ "!=" => "!==",
10
+ "!==" => "!=",
11
+ "or" => "||",
12
+ "and" => "&&"
13
+ }.freeze
14
+
6
15
  def generate_number(code)
7
16
 
8
17
  "#{code.first}"
@@ -10,7 +19,7 @@ module Liquidscript
10
19
 
11
20
  def generate_dstring(code)
12
21
 
13
- "\"#{code.first.gsub(/"/, '\\"')}\""
22
+ "\"#{code.first.gsub("\n", "\\n")}\""
14
23
  end
15
24
 
16
25
  def generate_sstring(code)
@@ -18,10 +27,22 @@ module Liquidscript
18
27
  "'#{code.first.gsub(/'/, "\\'")}'"
19
28
  end
20
29
 
21
- def generate_keyword(code)
30
+ def generate_unop(code)
22
31
  " #{code[1].value} #{replace(code[2])}"
23
32
  end
24
33
 
34
+ def generate_binop(code)
35
+ op = BINOP_SWITCH.fetch(code[1].value) do
36
+ code[1].value
37
+ end
38
+
39
+ " #{replace(code[2])} #{op} #{replace(code[3])}"
40
+ end
41
+
42
+ def generate_keyword(code)
43
+ " #{code[1].value} "
44
+ end
45
+
25
46
  def generate_object(code)
26
47
 
27
48
  object = buffer
@@ -4,7 +4,6 @@ module Liquidscript
4
4
  module Metas
5
5
 
6
6
  def generate_exec(code)
7
-
8
7
  exec = buffer
9
8
  exec << _exec_context(code)
10
9
  code.codes.inject(exec) do |m, c|
@@ -23,10 +22,34 @@ module Liquidscript
23
22
  end
24
23
 
25
24
  def generate_get(code)
26
-
27
25
  "#{code[1].name}"
28
26
  end
29
27
 
28
+ { :if => "if(%s)",
29
+ :elsif => "else if(%s)",
30
+ :unless => "if(!(%s))" }.each do |k, v|
31
+
32
+ define_method(:"generate_#{k}") do |code|
33
+ part = buffer
34
+ part << "\n#{v % replace(code[1])} {\n"
35
+ code[2].inject(part) { |m, p| m << replace(p) }
36
+ part << "\n}\n"
37
+
38
+ if code[3]
39
+ part << replace(code[3])
40
+ else
41
+ part
42
+ end
43
+ end
44
+ end
45
+
46
+ def generate_else(code)
47
+ part = buffer
48
+ part << "\nelse {\n"
49
+ code[1].inject(part) { |m, p| m << replace(p) }
50
+ part << "\n}\n"
51
+ end
52
+
30
53
  protected
31
54
 
32
55
  def _exec_context(code)
@@ -12,7 +12,7 @@ module Liquidscript
12
12
  # The variables that are allowed to be used as a global scope,
13
13
  # i.e. used in a `get` context without a previous `set`.
14
14
  DEFAULT_ALLOWED_VARIABLES = [
15
- :window, :global, :exports, :console, :this
15
+ :window, :global, :exports, :console, :this, :arguments
16
16
  ]
17
17
 
18
18
  # The parent of the current context.
@@ -17,6 +17,12 @@
17
17
  string_double = '"' ( any -- '"' | '\\"' )* '"';
18
18
  identifier = [A-Za-z_$][A-Za-z0-9_$]*;
19
19
  string_single = "'" [A-Za-z0-9_$\-]+;
20
+ keywords = 'undefined' | 'null' | 'true' | 'false';
21
+ unops = '!' | '++' | '--' | '~' | 'new' | 'return' |
22
+ 'typeof';
23
+ binops = '+' | '-' | '*' | '/' | '&' | '|' | '^' | '<<' | '>>' |
24
+ '>>>' | '==' | '!=' | '===' | '!==' | '>' | '>=' | '<' | '<=' |
25
+ '&&' | '||' | 'instanceof' | 'or' | 'and';
20
26
 
21
27
  main := |*
22
28
  number => { emit :number };
@@ -24,8 +30,13 @@
24
30
  string_single => { emit :sstring };
25
31
  'class' => { emit :class };
26
32
  'module' => { emit :module };
27
- 'new' => { emit :keyword };
28
- 'return' => { emit :keyword };
33
+ 'if' => { emit :if };
34
+ 'unless' => { emit :unless };
35
+ 'elsif' => { emit :elsif };
36
+ 'else' => { emit :else };
37
+ unops => { emit :unop };
38
+ binops => { emit :binop };
39
+ keywords => { emit :keyword };
29
40
  identifier => { emit :identifier };
30
41
  '->' => { emit :arrow };
31
42
  '=' => { emit :equal };
@@ -9,7 +9,7 @@ module Liquidscript
9
9
  @_render ||= begin
10
10
  compiler = Compiler::ICR.new(Scanner.new(@data))
11
11
  compiler.compile
12
- Generator::Javascript.new(compiler).generate
12
+ Generator::Javascript.new(compiler.top).generate
13
13
  end
14
14
  end
15
15
  end
@@ -1,5 +1,5 @@
1
1
  module Liquidscript
2
2
 
3
3
  # The current version of liquidscript.
4
- VERSION = "0.0.1".freeze
4
+ VERSION = "0.1.0".freeze
5
5
  end
@@ -0,0 +1,11 @@
1
+ module Sprockets
2
+ class LiquidscriptTemplate < Template
3
+ def self.default_mime_type
4
+ 'application/javascript'
5
+ end
6
+
7
+ def render(context)
8
+ @output ||= Liquidscript.compile(data)
9
+ end
10
+ end
11
+ end
@@ -1,7 +1,13 @@
1
1
  data: |
2
2
  thing = {
3
3
  test: -> {
4
- "hello"
4
+ if(undefined) {
5
+ "test"
6
+ } elsif(null) {
7
+ "um"
8
+ } else {
9
+ "hello"
10
+ }
5
11
  }
6
12
  }
7
13
 
@@ -12,7 +18,13 @@ compiled: |
12
18
 
13
19
  thing = {
14
20
  "test": function() {
15
- "hello"
21
+ if(undefined) {
22
+ "test"
23
+ } else if(null) {
24
+ "um"
25
+ } else {
26
+ "hello"
27
+ }
16
28
  }
17
29
  };
18
30
 
@@ -0,0 +1,23 @@
1
+ data: |
2
+ nodejs = -> {
3
+ out = false
4
+
5
+ if(typeof global != 'undefined) {
6
+ out = true
7
+ }
8
+
9
+ return out
10
+ }
11
+
12
+ compiled: |
13
+ var nodejs;
14
+
15
+ nodejs = function() {
16
+ var out;
17
+ out = false;
18
+ if(typeof global !== 'undefined') {
19
+ out = true;
20
+ }
21
+
22
+ return out
23
+ };
@@ -1,6 +1,11 @@
1
1
  data: |
2
2
  test = "hello"
3
3
  foo = 'world
4
+ thing = "hello \" test
5
+ world"
4
6
 
5
7
  compiled: |
6
- var test,foo; test = "hello"; foo = 'world';
8
+ var test, foo, thing;
9
+ test = "hello";
10
+ foo = 'world';
11
+ thing = "hello \" test \n world";
@@ -0,0 +1,29 @@
1
+ (-> {
2
+ root = this
3
+ previousUnderscore = root._
4
+ breaker = {}
5
+ ArrayProto = root.Array.prototype
6
+ ObjProto = root.Object.prototype
7
+ FuncProto = root.Function.prototype
8
+
9
+ push = ArrayProto.push
10
+ slice = ArrayProto.slice
11
+ concat = ArrayProto.concat
12
+ toString = ObjProto.toString
13
+ hasOwnProperty = ObjProto.hasOwnProperty
14
+
15
+ class _ {
16
+
17
+ }
18
+
19
+ if(typeof exports != 'undefined) {
20
+ if(typeof root.module !== 'undefined && root.module.exports) {
21
+ exports = root.module.exports = _
22
+ }
23
+
24
+ exports._ = _
25
+ } else {
26
+ root._ = _
27
+ }
28
+ _.VERSION = "1.6.0"
29
+ }).call()
@@ -47,10 +47,10 @@ describe Liquidscript::Scanner::Lexer, :lexer_helper do
47
47
 
48
48
  it "scans keywords" do
49
49
  scan("return test = new foo").should eq [
50
- [:keyword, "return"],
50
+ [:unop, "return"],
51
51
  [:identifier, "test"],
52
52
  [:equal, "="],
53
- [:keyword, "new"],
53
+ [:unop, "new"],
54
54
  [:identifier, "foo"]
55
55
  ]
56
56
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: liquidscript
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Rodi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-07 00:00:00.000000000 Z
11
+ date: 2014-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -83,18 +83,21 @@ dependencies:
83
83
  description: A javascript-based language that compiles to javascript.
84
84
  email:
85
85
  - redjazz96@gmail.com
86
- executables: []
86
+ executables:
87
+ - lscript
87
88
  extensions: []
88
89
  extra_rdoc_files: []
89
90
  files:
90
91
  - ".gitignore"
91
92
  - ".rspec"
92
93
  - ".travis.yml"
94
+ - DOCS.md
93
95
  - Gemfile
94
96
  - Guardfile
95
97
  - LICENSE.txt
96
98
  - README.md
97
99
  - Rakefile
100
+ - bin/lscript
98
101
  - lib/liquidscript.rb
99
102
  - lib/liquidscript/buffer.rb
100
103
  - lib/liquidscript/compiler.rb
@@ -131,6 +134,7 @@ files:
131
134
  - lib/liquidscript/scanner/token.rb
132
135
  - lib/liquidscript/template.rb
133
136
  - lib/liquidscript/version.rb
137
+ - lib/sprockets/liquidscript_template.rb
134
138
  - liquidscript.gemspec
135
139
  - spec/fixtures/class.compile.yml
136
140
  - spec/fixtures/class.generate.yml
@@ -141,8 +145,10 @@ files:
141
145
  - spec/fixtures/get.generate.yml
142
146
  - spec/fixtures/literals.generate.yml
143
147
  - spec/fixtures/main.compile.yml
148
+ - spec/fixtures/operator.generate.yml
144
149
  - spec/fixtures/set.generate.yml
145
150
  - spec/fixtures/string.generate.yml
151
+ - spec/fixtures/underscore.ls
146
152
  - spec/lib/liquidscript/buffer_spec.rb
147
153
  - spec/lib/liquidscript/compiler/icr_spec.rb
148
154
  - spec/lib/liquidscript/generator/javascript_spec.rb
@@ -191,8 +197,10 @@ test_files:
191
197
  - spec/fixtures/get.generate.yml
192
198
  - spec/fixtures/literals.generate.yml
193
199
  - spec/fixtures/main.compile.yml
200
+ - spec/fixtures/operator.generate.yml
194
201
  - spec/fixtures/set.generate.yml
195
202
  - spec/fixtures/string.generate.yml
203
+ - spec/fixtures/underscore.ls
196
204
  - spec/lib/liquidscript/buffer_spec.rb
197
205
  - spec/lib/liquidscript/compiler/icr_spec.rb
198
206
  - spec/lib/liquidscript/generator/javascript_spec.rb