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
@@ -0,0 +1,40 @@
|
|
1
|
+
require "liquidscript/scanner/token"
|
2
|
+
require "liquidscript/scanner/lexer"
|
3
|
+
|
4
|
+
module Liquidscript
|
5
|
+
|
6
|
+
# @todo Stream scanning.
|
7
|
+
# um...
|
8
|
+
class Scanner
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
def initialize(source)
|
13
|
+
@tokenizer = Lexer.new
|
14
|
+
@source = source
|
15
|
+
end
|
16
|
+
|
17
|
+
def each
|
18
|
+
e = buffer.each
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
e.each(&Proc.new)
|
22
|
+
else
|
23
|
+
e
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def inspect
|
28
|
+
"#<#{self.class.to_s}:#{'0x%08x' % self.object_id}>"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def buffer
|
34
|
+
@_parts ||= begin
|
35
|
+
@tokenizer.perform(@source)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
%%{
|
2
|
+
|
3
|
+
machine lexer;
|
4
|
+
|
5
|
+
variable data @data;
|
6
|
+
variable p @p;
|
7
|
+
variable pe @pe;
|
8
|
+
variable eof @eof;
|
9
|
+
access @;
|
10
|
+
|
11
|
+
number_integer = '-'? [0-9][1-9]*;
|
12
|
+
number_frac = '.' [0-9]+;
|
13
|
+
number_e = ('e' | 'E') ('+' | '-' | '');
|
14
|
+
number_exp = number_e [0-9]+;
|
15
|
+
number = number_integer number_frac? number_exp?;
|
16
|
+
|
17
|
+
string_double = '"' ( any -- '"' | '\\"' )* '"';
|
18
|
+
identifier = [A-Za-z_$][A-Za-z0-9_$]*;
|
19
|
+
string_single = "'" [A-Za-z0-9_$\-]+;
|
20
|
+
|
21
|
+
main := |*
|
22
|
+
number => { emit :number };
|
23
|
+
string_double => { emit :dstring };
|
24
|
+
string_single => { emit :sstring };
|
25
|
+
'class' => { emit :class };
|
26
|
+
'module' => { emit :module };
|
27
|
+
'new' => { emit :keyword };
|
28
|
+
'return' => { emit :keyword };
|
29
|
+
identifier => { emit :identifier };
|
30
|
+
'->' => { emit :arrow };
|
31
|
+
'=' => { emit :equal };
|
32
|
+
'{' => { emit :lbrack };
|
33
|
+
'(' => { emit :lparen };
|
34
|
+
'[' => { emit :lbrace };
|
35
|
+
'}' => { emit :rbrack };
|
36
|
+
')' => { emit :rparen };
|
37
|
+
']' => { emit :rbrace };
|
38
|
+
':' => { emit :colon };
|
39
|
+
'.' => { emit :prop };
|
40
|
+
',' => { emit :comma };
|
41
|
+
'\n' => { line.call };
|
42
|
+
space => { };
|
43
|
+
any => { error };
|
44
|
+
*|;
|
45
|
+
}%%
|
46
|
+
|
47
|
+
module Liquidscript
|
48
|
+
class Scanner
|
49
|
+
|
50
|
+
# A lexer, built from ragel.
|
51
|
+
#
|
52
|
+
# @private
|
53
|
+
class Lexer
|
54
|
+
|
55
|
+
attr_reader :tokens
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
%% write data;
|
59
|
+
# %% # fix
|
60
|
+
@tokens = []
|
61
|
+
clean!
|
62
|
+
end
|
63
|
+
|
64
|
+
def clean!
|
65
|
+
@p = nil
|
66
|
+
@pe = nil
|
67
|
+
@te = nil
|
68
|
+
@ts = nil
|
69
|
+
@act = nil
|
70
|
+
@eof = nil
|
71
|
+
@top = nil
|
72
|
+
@line = { :start => 0, :num => 0 }
|
73
|
+
@data = nil
|
74
|
+
@stack = nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def emit(type)
|
78
|
+
@tokens << Token.new(type, @data[@ts..(@te - 1)],
|
79
|
+
@line[:num], @ts - @line[:start])
|
80
|
+
end
|
81
|
+
|
82
|
+
def error
|
83
|
+
raise SyntaxError, "Unexpected #{@data[@ts..(@te-1)].pack('c*')}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def perform(data)
|
87
|
+
@data = data.unpack("c*") if data.is_a? String
|
88
|
+
@eof = data.length
|
89
|
+
|
90
|
+
@tokens = []
|
91
|
+
|
92
|
+
line = proc do
|
93
|
+
@line[:start] = @ts
|
94
|
+
@line[:num] += 1
|
95
|
+
end
|
96
|
+
|
97
|
+
%% write init;
|
98
|
+
%% write exec;
|
99
|
+
|
100
|
+
clean!
|
101
|
+
|
102
|
+
@tokens
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "liquidscript/icr/representable"
|
2
|
+
|
3
|
+
module Liquidscript
|
4
|
+
class Scanner
|
5
|
+
class Token
|
6
|
+
|
7
|
+
attr_accessor :type
|
8
|
+
attr_accessor :value
|
9
|
+
attr_reader :line
|
10
|
+
attr_reader :column
|
11
|
+
|
12
|
+
include Enumerable
|
13
|
+
include ICR::Representable
|
14
|
+
|
15
|
+
def initialize(type, value, line, column)
|
16
|
+
@type = type
|
17
|
+
@line = line
|
18
|
+
@column = column
|
19
|
+
@value = begin
|
20
|
+
value.pack("c*")
|
21
|
+
rescue NoMethodError, TypeError
|
22
|
+
value
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
[@type, @value]
|
28
|
+
end
|
29
|
+
|
30
|
+
def type?(type)
|
31
|
+
@type == type
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
class Template
|
3
|
+
|
4
|
+
def initialize(data)
|
5
|
+
@data = data
|
6
|
+
end
|
7
|
+
|
8
|
+
def render
|
9
|
+
@_render ||= begin
|
10
|
+
compiler = Compiler::ICR.new(Scanner.new(@data))
|
11
|
+
compiler.compile
|
12
|
+
Generator::Javascript.new(compiler).generate
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'liquidscript/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "liquidscript"
|
8
|
+
spec.version = Liquidscript::VERSION
|
9
|
+
spec.authors = ["Jeremy Rodi"]
|
10
|
+
spec.email = ["redjazz96@gmail.com"]
|
11
|
+
spec.summary = %q{A javascript-based language that compiles to javascript.}
|
12
|
+
spec.description = %q{A javascript-based language that compiles to javascript.}
|
13
|
+
spec.homepage = "https://github.com/redjazz96/liquidscript"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "yard"
|
25
|
+
|
26
|
+
spec.add_dependency "hashie", "~> 2.0"
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
data: |
|
2
|
+
module Something {
|
3
|
+
class SomeClass {
|
4
|
+
test: -> {}
|
5
|
+
}
|
6
|
+
}
|
7
|
+
|
8
|
+
compiled:
|
9
|
+
- :exec
|
10
|
+
- - :_context
|
11
|
+
- - :SomeClass
|
12
|
+
- :Something
|
13
|
+
- - :module
|
14
|
+
- - :identifier
|
15
|
+
- Something
|
16
|
+
- - - :class
|
17
|
+
- - :identifier
|
18
|
+
- SomeClass
|
19
|
+
- - - - :identifier
|
20
|
+
- test
|
21
|
+
- - :function
|
22
|
+
- - :exec
|
23
|
+
- - :_context
|
24
|
+
- []
|
25
|
+
- - :_arguments
|
26
|
+
- []
|
@@ -0,0 +1,31 @@
|
|
1
|
+
data: |
|
2
|
+
module Something {
|
3
|
+
class Test {
|
4
|
+
wee: -> {
|
5
|
+
console.log(2)
|
6
|
+
}
|
7
|
+
|
8
|
+
initialize: -> {
|
9
|
+
"this should be init"
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
compiled: |
|
15
|
+
var Test, Something;
|
16
|
+
|
17
|
+
Something = {};
|
18
|
+
Test = function Test() {
|
19
|
+
if(this.initialize) {
|
20
|
+
this.initialize.apply(this, arguments);
|
21
|
+
}
|
22
|
+
};
|
23
|
+
|
24
|
+
Test.prototype.wee = function() {
|
25
|
+
console.log(2)
|
26
|
+
};
|
27
|
+
|
28
|
+
Test.prototype.initialize = function() {
|
29
|
+
"this should be init"
|
30
|
+
};
|
31
|
+
Something.Test = Test;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
data: |
|
2
|
+
Test = require("some_module/test")
|
3
|
+
|
4
|
+
module SomeModule {
|
5
|
+
class Thing {
|
6
|
+
initialize: -> {
|
7
|
+
this.test = new Test()
|
8
|
+
}
|
9
|
+
|
10
|
+
do: (thing)-> {
|
11
|
+
return this.test.do(thing)
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
compiled: |
|
17
|
+
var Test, Thing, SomeModule;
|
18
|
+
Test = require("some_module/test");
|
19
|
+
SomeModule = {};
|
20
|
+
Thing = function Thing() {
|
21
|
+
if(this.initialize) {
|
22
|
+
this.initialize.apply(this, arguments);
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
Thing.prototype.initialize = function() {
|
27
|
+
this.test = new Test();
|
28
|
+
};
|
29
|
+
|
30
|
+
Thing.prototype.do = function(thing) {
|
31
|
+
return this.test.do(thing)
|
32
|
+
};
|
33
|
+
SomeModule.Thing = Thing;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
data: |
|
2
|
+
console = 2
|
3
|
+
func = ()-> {
|
4
|
+
console.log("hello world")
|
5
|
+
}
|
6
|
+
compiled:
|
7
|
+
- :exec
|
8
|
+
- - :_context
|
9
|
+
- - :console
|
10
|
+
- :func
|
11
|
+
- - :set
|
12
|
+
- - :_variable
|
13
|
+
- :console
|
14
|
+
- - :number
|
15
|
+
- "2"
|
16
|
+
- - :set
|
17
|
+
- - :_variable
|
18
|
+
- :func
|
19
|
+
- - :function
|
20
|
+
- - :exec
|
21
|
+
- - :_context
|
22
|
+
- []
|
23
|
+
- - :_arguments
|
24
|
+
- []
|
25
|
+
- - :call
|
26
|
+
- - :property
|
27
|
+
- - :_variable
|
28
|
+
- :console
|
29
|
+
- - :identifier
|
30
|
+
- log
|
31
|
+
- - :dstring
|
32
|
+
- hello world
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Liquidscript::Buffer do
|
4
|
+
|
5
|
+
subject { described_class.new "hello ", "world" }
|
6
|
+
|
7
|
+
its(:to_s) { should eq "hello world" }
|
8
|
+
its(:inspect) { should eq '"hello world"' }
|
9
|
+
|
10
|
+
it "appends a value" do
|
11
|
+
subject.append(", test")
|
12
|
+
expect(subject.to_s).to eq "hello world, test"
|
13
|
+
end
|
14
|
+
end
|