liquidscript 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +11 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +25 -0
- data/lib/liquidscript.rb +11 -0
- data/lib/liquidscript/buffer.rb +34 -0
- data/lib/liquidscript/compiler.rb +9 -0
- data/lib/liquidscript/compiler/base.rb +101 -0
- data/lib/liquidscript/compiler/base/action.rb +39 -0
- data/lib/liquidscript/compiler/base/blank.rb +24 -0
- data/lib/liquidscript/compiler/base/callable.rb +51 -0
- data/lib/liquidscript/compiler/base/helpers.rb +207 -0
- data/lib/liquidscript/compiler/icr.rb +40 -0
- data/lib/liquidscript/compiler/icr/classes.rb +59 -0
- data/lib/liquidscript/compiler/icr/expressions.rb +94 -0
- data/lib/liquidscript/compiler/icr/functions.rb +42 -0
- data/lib/liquidscript/compiler/icr/helpers.rb +20 -0
- data/lib/liquidscript/compiler/icr/literals.rb +106 -0
- data/lib/liquidscript/errors.rb +51 -0
- data/lib/liquidscript/generator.rb +11 -0
- data/lib/liquidscript/generator/base.rb +25 -0
- data/lib/liquidscript/generator/base/dsl.rb +19 -0
- data/lib/liquidscript/generator/base/replacements.rb +33 -0
- data/lib/liquidscript/generator/context.rb +7 -0
- data/lib/liquidscript/generator/javascript.rb +37 -0
- data/lib/liquidscript/generator/javascript/literals.rb +63 -0
- data/lib/liquidscript/generator/javascript/metas.rb +41 -0
- data/lib/liquidscript/generator/javascript/objects.rb +137 -0
- data/lib/liquidscript/icr.rb +18 -0
- data/lib/liquidscript/icr/code.rb +68 -0
- data/lib/liquidscript/icr/context.rb +94 -0
- data/lib/liquidscript/icr/representable.rb +39 -0
- data/lib/liquidscript/icr/set.rb +147 -0
- data/lib/liquidscript/icr/sexp.rb +41 -0
- data/lib/liquidscript/icr/variable.rb +68 -0
- data/lib/liquidscript/scanner.rb +40 -0
- data/lib/liquidscript/scanner/lexer.rl +106 -0
- data/lib/liquidscript/scanner/token.rb +37 -0
- data/lib/liquidscript/template.rb +16 -0
- data/lib/liquidscript/version.rb +5 -0
- data/liquidscript.gemspec +27 -0
- data/spec/fixtures/class.compile.yml +26 -0
- data/spec/fixtures/class.generate.yml +31 -0
- data/spec/fixtures/combination.generate.yml +33 -0
- data/spec/fixtures/complex.generate.yml +20 -0
- data/spec/fixtures/expression.generate.yml +4 -0
- data/spec/fixtures/function.generate.yml +11 -0
- data/spec/fixtures/get.generate.yml +5 -0
- data/spec/fixtures/literals.generate.yml +8 -0
- data/spec/fixtures/main.compile.yml +32 -0
- data/spec/fixtures/set.generate.yml +4 -0
- data/spec/fixtures/string.generate.yml +6 -0
- data/spec/lib/liquidscript/buffer_spec.rb +14 -0
- data/spec/lib/liquidscript/compiler/icr_spec.rb +139 -0
- data/spec/lib/liquidscript/generator/javascript_spec.rb +15 -0
- data/spec/lib/liquidscript/icr/code_spec.rb +0 -0
- data/spec/lib/liquidscript/icr/context_spec.rb +36 -0
- data/spec/lib/liquidscript/icr/set_spec.rb +59 -0
- data/spec/lib/liquidscript/scanner/lexer_spec.rb +58 -0
- data/spec/lib/liquidscript/scanner/token_spec.rb +0 -0
- data/spec/lib/liquidscript/scanner_spec.rb +21 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/helpers/lexer_helper.rb +5 -0
- data/spec/support/matchers/be_token.rb +9 -0
- data/spec/support/matchers/compile.rb +41 -0
- data/spec/support/matchers/generate.rb +46 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d8099fbffde0b4c86f743c1eeb2f7945876bda79
|
4
|
+
data.tar.gz: 61440eea14db6d81cff6245c03916e58092f310e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d58710b0697834bfa1501061adc3d9d0492206d71c24d8886a769e451dadff2e41bdcc527d8629fb4522ff92cb2a9e423ee96eb1559d7fc5370c04a3bbfd3262
|
7
|
+
data.tar.gz: 9552101c9846bde2f34eebedcf1e4dcd1fa4da268c3e563331e2872ad0d9d5d21ea82296c79044265cdc0f01023fb3333542c99ed52d312cb30e9b40fed3afa9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jeremy Rodi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Liquidscript
|
2
|
+
|
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
|
+
|
5
|
+
A javascript-based language that compiles to javascript.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'liquidscript'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install liquidscript
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To use liquidscript:
|
24
|
+
|
25
|
+
```
|
26
|
+
TODO: usage example
|
27
|
+
```
|
28
|
+
|
29
|
+
The language of liquidscript:
|
30
|
+
|
31
|
+
```coffeescript
|
32
|
+
# This is an object.
|
33
|
+
|
34
|
+
{
|
35
|
+
test: "hello",
|
36
|
+
|
37
|
+
# Note here that a single-quoted string does not have an ending
|
38
|
+
# delimiter. This is on purpose.
|
39
|
+
foo: 'bar # ' # syntax highlighting fix
|
40
|
+
}
|
41
|
+
```
|
42
|
+
|
43
|
+
```coffeescript
|
44
|
+
# This is a function
|
45
|
+
|
46
|
+
func = ()-> {
|
47
|
+
console.log("hello world")
|
48
|
+
}
|
49
|
+
|
50
|
+
func()
|
51
|
+
```
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it ( http://github.com/redjazz96/liquidscript/fork )
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new('spec')
|
6
|
+
|
7
|
+
namespace :ls do
|
8
|
+
rule '.rb' => ['.rl'] do |t|
|
9
|
+
sh "ragel -R #{t.source}"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Builds the ragel parser."
|
13
|
+
task :ragel => ["lib/liquidscript/scanner/lexer.rb"]
|
14
|
+
|
15
|
+
desc "Opens up a pry session."
|
16
|
+
task :pry => [:ragel] do
|
17
|
+
require "pry"
|
18
|
+
require File.expand_path("../lib/liquidscript", __FILE__)
|
19
|
+
Pry.start
|
20
|
+
end
|
21
|
+
|
22
|
+
task :clean do
|
23
|
+
File.unlink("lib/liquidscript/scanner/lexer.rb")
|
24
|
+
end
|
25
|
+
end
|
data/lib/liquidscript.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "liquidscript/icr"
|
3
|
+
require "liquidscript/errors"
|
4
|
+
require "liquidscript/version"
|
5
|
+
require "liquidscript/scanner"
|
6
|
+
require "liquidscript/compiler"
|
7
|
+
require "liquidscript/generator"
|
8
|
+
|
9
|
+
module Liquidscript
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
class Buffer
|
3
|
+
|
4
|
+
def initialize(*args)
|
5
|
+
@_buf = args
|
6
|
+
@_cache = nil
|
7
|
+
@_join = ''
|
8
|
+
end
|
9
|
+
|
10
|
+
def append(*a)
|
11
|
+
@_cache = nil
|
12
|
+
@_buf.push(*a)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_join!(to)
|
17
|
+
@_join = to
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :<<, :append
|
21
|
+
alias_method :push, :append
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@_cache ||= begin
|
25
|
+
@_buf.join @_join
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
to_s.inspect
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "liquidscript/compiler/base/blank"
|
2
|
+
require "liquidscript/compiler/base/action"
|
3
|
+
require "liquidscript/compiler/base/helpers"
|
4
|
+
require "liquidscript/compiler/base/callable"
|
5
|
+
|
6
|
+
module Liquidscript
|
7
|
+
module Compiler
|
8
|
+
class Base
|
9
|
+
|
10
|
+
include Helpers
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Initializes the compiler.
|
14
|
+
#
|
15
|
+
# @param scanner [Scanner, #each] the scanner. Used to
|
16
|
+
# manage the tokens. This could be stubbed out, if
|
17
|
+
# the #each function returns an Enumerator, which yields
|
18
|
+
# {Scanner::Token}s.
|
19
|
+
def initialize(scanner)
|
20
|
+
@scanner = scanner.each
|
21
|
+
@action = Action.new
|
22
|
+
reset!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the top set. If the variable @top isn't set by the
|
26
|
+
# inheriting class, then it defaults to the value of an array.
|
27
|
+
#
|
28
|
+
# @return [Array, #push]
|
29
|
+
def top
|
30
|
+
@top ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
# Begins the compiliation. Continues until the iterator raises
|
34
|
+
# a `StopIteration` error, and then returns the top set with
|
35
|
+
# {#top}.
|
36
|
+
#
|
37
|
+
# @raise [CompileError] if there's an error compiling.
|
38
|
+
# @raise [UnexpectedEndError] if the top {Array} isn't the topmost
|
39
|
+
# set.
|
40
|
+
# @return [Array] the topmost set.
|
41
|
+
def compile
|
42
|
+
# We're using this cool property of Base::Blank such that it
|
43
|
+
# will return a nil to any method call.
|
44
|
+
while !peek.is_a?(Blank) do
|
45
|
+
top.push compile_start
|
46
|
+
end
|
47
|
+
|
48
|
+
top
|
49
|
+
end
|
50
|
+
|
51
|
+
# Checks to see if the given input compiles.
|
52
|
+
#
|
53
|
+
# @see [#compile]
|
54
|
+
# @return [Boolean] if it compiles.
|
55
|
+
def compile?
|
56
|
+
compile
|
57
|
+
true
|
58
|
+
rescue CompileError
|
59
|
+
false
|
60
|
+
ensure
|
61
|
+
reset!
|
62
|
+
end
|
63
|
+
|
64
|
+
def scanner_nil
|
65
|
+
@_blank ||= Blank.new
|
66
|
+
end
|
67
|
+
|
68
|
+
# Pops the next argument off of the scanner. If the call
|
69
|
+
# raises a {StopIteration} error, it returns the value of
|
70
|
+
# {#scanner_nil} instead.
|
71
|
+
#
|
72
|
+
# @return [#type?, Blank]
|
73
|
+
def pop
|
74
|
+
@scanner.next
|
75
|
+
rescue StopIteration
|
76
|
+
scanner_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# Peeks at the next argument on the scanner. If the call
|
80
|
+
# raises a {StopIteration} error, it returns the value of
|
81
|
+
# {#scanner_nil} instead.
|
82
|
+
#
|
83
|
+
# @return [#type, Blank]
|
84
|
+
def peek
|
85
|
+
@scanner.peek
|
86
|
+
rescue StopIteration
|
87
|
+
scanner_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Resets the state of the compiler.
|
91
|
+
#
|
92
|
+
# @return [void]
|
93
|
+
def reset!
|
94
|
+
@scanner.rewind
|
95
|
+
end
|
96
|
+
|
97
|
+
alias_method :rewind, :reset!
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
|
5
|
+
# Used to construct blocks that are used with {#expect}. It's
|
6
|
+
# primarily syntaxic sugar, and DRYness.
|
7
|
+
class Action
|
8
|
+
|
9
|
+
# Returns a block that returns true, and takes no arguments.
|
10
|
+
# This is for {#expect}, when you don't want the token to be
|
11
|
+
# shifted, and you don't want the loop to end (if applicable).
|
12
|
+
#
|
13
|
+
# @return [Proc]
|
14
|
+
def nothing
|
15
|
+
@_nothing ||= proc { true }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a block that returns the first argument given to it.
|
19
|
+
# This is for {#expect}, when you want to shift the token, and
|
20
|
+
# you don't want the loop to end (if applicable). Also used
|
21
|
+
# internally for {Helpers#shift}.
|
22
|
+
#
|
23
|
+
# @return [Proc]
|
24
|
+
def shift
|
25
|
+
@_shift ||= proc { |_| _ }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a block that returns false, and takes one argument.
|
29
|
+
# This is for {#expect}, when you want to shift the token, and
|
30
|
+
# you want the loop to end (if applicable).
|
31
|
+
#
|
32
|
+
# @return [Proc]
|
33
|
+
def end_loop
|
34
|
+
@_end_loop ||= proc { |_| false }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
|
5
|
+
# Responds to all methods with `nil`.
|
6
|
+
class Blank
|
7
|
+
|
8
|
+
# Respond to all methods, with `nil`.
|
9
|
+
#
|
10
|
+
# @return [nil]
|
11
|
+
def method_missing(*_, &block)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Tells Ruby that we respond to all methods.
|
16
|
+
#
|
17
|
+
# @return [true]
|
18
|
+
def respond_to_missing?(_, __)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
class Callable
|
5
|
+
|
6
|
+
# Initialize the callable.
|
7
|
+
#
|
8
|
+
# @param bind [Object] the object that holds the method (if
|
9
|
+
# this represents a method call).
|
10
|
+
# @param block [Symbol, Block] if it's a Symbol, it represents
|
11
|
+
# a method on bind; otherwise, it's a pure block.
|
12
|
+
def initialize(bind, block)
|
13
|
+
@bind = bind
|
14
|
+
@block = if block.is_a? Symbol
|
15
|
+
:"compile_#{block}"
|
16
|
+
else
|
17
|
+
block
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Calls the thing that this represents. If this represents a
|
22
|
+
# method call, it calls the method with the given arguments;
|
23
|
+
# otherwise, it calls {#call} on the block.
|
24
|
+
#
|
25
|
+
# @param args [Object] passed to the call.
|
26
|
+
# @return [Object] the result of the call.
|
27
|
+
def call(*args)
|
28
|
+
if @block.is_a? Symbol
|
29
|
+
@bind.public_send(@block, *args)
|
30
|
+
elsif @block.respond_to?(:call)
|
31
|
+
@block.call(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# How many arguments the call can take. If this represents a
|
36
|
+
# block that has tricks enabled, then this isn't an issue; if
|
37
|
+
# it's a method call, however, it becomes important.
|
38
|
+
#
|
39
|
+
# @return [Numeric] the number of arguments it can take.
|
40
|
+
def arity
|
41
|
+
if @block.is_a? Symbol
|
42
|
+
@bind.method(@block).arity
|
43
|
+
else
|
44
|
+
@block.arity
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|