shift-lang 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/sft +5 -0
- data/bin/shift +5 -0
- data/lib/app_engine_templates/app.yaml +13 -0
- data/lib/app_engine_templates/pystache/__init__.py +8 -0
- data/lib/app_engine_templates/pystache/__init__.pyc +0 -0
- data/lib/app_engine_templates/pystache/loader.py +47 -0
- data/lib/app_engine_templates/pystache/loader.pyc +0 -0
- data/lib/app_engine_templates/pystache/template.py +177 -0
- data/lib/app_engine_templates/pystache/template.pyc +0 -0
- data/lib/app_engine_templates/pystache/view.py +94 -0
- data/lib/app_engine_templates/pystache/view.pyc +0 -0
- data/lib/heroku_templates/Gemfile +6 -0
- data/lib/heroku_templates/Procfile +1 -0
- data/lib/shift-lang/builder/db_model.rb +20 -0
- data/lib/shift-lang/builder/url_handler.rb +17 -0
- data/lib/shift-lang/builder.rb +103 -0
- data/lib/shift-lang/generator/javascript_generator.rb +410 -0
- data/lib/shift-lang/generator/javascript_templates.rb +37 -0
- data/lib/shift-lang/generator/python_generator.rb +330 -0
- data/lib/shift-lang/generator/python_templates.rb +44 -0
- data/lib/shift-lang/generator/ruby_generator.rb +334 -0
- data/lib/shift-lang/generator/ruby_templates.rb +50 -0
- data/lib/shift-lang/generator.rb +41 -0
- data/lib/shift-lang/parser/control_statement_parser.rb +17 -0
- data/lib/shift-lang/parser/db_query_parser.rb +20 -0
- data/lib/shift-lang/parser/keyword_parser.rb +52 -0
- data/lib/shift-lang/parser/operator_parser.rb +35 -0
- data/lib/shift-lang/parser/routing_expression_parser.rb +33 -0
- data/lib/shift-lang/parser/simple_expression_parser.rb +87 -0
- data/lib/shift-lang/parser/token_parser.rb +69 -0
- data/lib/shift-lang/parser/value_returning_expression_parser.rb +18 -0
- data/lib/shift-lang/parser/void_statement_parser.rb +12 -0
- data/lib/shift-lang/parser.rb +120 -0
- data/lib/shift-lang/version.rb +3 -0
- data/lib/shift-lang.rb +224 -0
- data/shift-lang.gemspec +19 -0
- metadata +106 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
module Shift
|
2
|
+
module Generator
|
3
|
+
module RubyTemplates
|
4
|
+
IMPORT_SINATRA_STATEMENT = "require 'sinatra'"
|
5
|
+
|
6
|
+
IMPORT_MUSTACHE_STATEMENT = "require 'mustache/sinatra'\n$mu_root = 'views/'"
|
7
|
+
|
8
|
+
IMPORT_DATAMAPPER_STATEMENT = "require 'data_mapper'\n"
|
9
|
+
|
10
|
+
MODEL_NAME_TEMPLATE = "class <%= model_name %>"
|
11
|
+
|
12
|
+
DATAMAPPER_INCLUDE_STATEMENT = "include DataMapper::Resource"
|
13
|
+
|
14
|
+
DB_STRING_PROPERTY = "Text"
|
15
|
+
|
16
|
+
DB_INTEGER_PROPERTY = "Integer"
|
17
|
+
|
18
|
+
UTILITY_FUNCTIONS = '
|
19
|
+
def read_file(file_name)
|
20
|
+
f = open($mu_root + file_name,"r")
|
21
|
+
template = f.read()
|
22
|
+
f.close()
|
23
|
+
template
|
24
|
+
end
|
25
|
+
|
26
|
+
def read_template(file_name, template_values = nil)
|
27
|
+
template = read_file(file_name)
|
28
|
+
if (template_values == nil)
|
29
|
+
template
|
30
|
+
else
|
31
|
+
Mustache.render(template, template_values)
|
32
|
+
end
|
33
|
+
end'
|
34
|
+
|
35
|
+
CONFIGURE_BLOCK = '
|
36
|
+
configure :development do
|
37
|
+
DataMapper.setup(:default, (ENV["DATABASE_URL"] || "sqlite3://#{Dir.pwd}/test1.db"))
|
38
|
+
DataMapper.finalize.auto_upgrade!
|
39
|
+
end'
|
40
|
+
|
41
|
+
WRITE_DATA_TEMPLATE = "response_result = <%= write_data %>"
|
42
|
+
|
43
|
+
WRITE_RESPONSE_TEMPLATE = '"#{response_result}"'
|
44
|
+
|
45
|
+
WRITE_FILE_TEMPLATE = "read_template(<%= file_name %><% if template_values %>, <%= template_values %><% end %>)"
|
46
|
+
|
47
|
+
REDIRECT_STATEMENT_TEMPLATE = "redirect(<%= url %>)"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'generator/python_generator'
|
2
|
+
require_relative 'generator/ruby_generator'
|
3
|
+
require_relative 'generator/javascript_generator'
|
4
|
+
|
5
|
+
module Shift
|
6
|
+
module Generator
|
7
|
+
def Generator::generatePython(files)
|
8
|
+
generator = Shift::Generator::PythonGenerator.new
|
9
|
+
|
10
|
+
files.each { | file | generator.get_data_from_file file }
|
11
|
+
|
12
|
+
if(generator.builder.clean)
|
13
|
+
generator.write_data
|
14
|
+
else
|
15
|
+
""
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def Generator::generateRuby(files)
|
19
|
+
generator = Shift::Generator::RubyGenerator.new
|
20
|
+
|
21
|
+
files.each { | file | generator.get_data_from_file file }
|
22
|
+
|
23
|
+
if(generator.builder.clean)
|
24
|
+
generator.write_data
|
25
|
+
else
|
26
|
+
""
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def Generator::generateJavaScript(files)
|
30
|
+
generator = Shift::Generator::JavaScriptGenerator.new
|
31
|
+
|
32
|
+
files.each { | file | generator.get_data_from_file file }
|
33
|
+
|
34
|
+
if(generator.builder.clean)
|
35
|
+
generator.write_data
|
36
|
+
else
|
37
|
+
""
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:if_statement) { if_keyword >> space >> (conditional_statement | boolean_valued_expression).as(:condition)}
|
8
|
+
|
9
|
+
rule(:for_statement) { for_keyword >> space >> primitives >> in_keyword >> primitives }
|
10
|
+
|
11
|
+
rule(:while_statement) { while_keyword >> space >> (conditional_statement | boolean_valued_expression).as(:condition) }
|
12
|
+
|
13
|
+
|
14
|
+
rule(:control_statement) { if_statement.as(:if_statement) | else_keyword.as(:else_statement) | for_statement.as(:for_statement) | while_statement.as(:while_statement) }
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:cud_keyword) { new_keyword | all_keyword | update_keyword | delete_keyword }
|
8
|
+
|
9
|
+
rule(:cud_query) { cud_keyword.as(:operation) >> space >> identifier.as(:model_name) }
|
10
|
+
|
11
|
+
rule(:find_by_id_query) { find_by_id_keyword.as(:operation) >> space >> identifier.as(:model_name) >> variables.as(:item_id) }
|
12
|
+
|
13
|
+
rule(:find_condition) { space? >> identifier.as(:attribute) >> space? >> query_find_operator.as(:operator) >> space? >> value_returning_expression.as(:value) >> space?}
|
14
|
+
|
15
|
+
rule(:find_query) { find_keyword.as(:operation) >> space >> identifier.as(:model_name) >> space >> where_keyword >> find_condition.as(:condition) >> (space? >> comma >> space? >> find_condition.as(:condition)).repeat(0) }
|
16
|
+
|
17
|
+
rule(:query) { find_query.as(:query) | find_by_id_query.as(:query) | cud_query.as(:query) }
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:read_keyword) { str('read') }
|
8
|
+
|
9
|
+
rule(:all_keyword) { str('all') }
|
10
|
+
|
11
|
+
rule(:new_keyword) { str('new') }
|
12
|
+
|
13
|
+
rule(:find_keyword) { str('find') }
|
14
|
+
|
15
|
+
rule(:where_keyword) { str('where') }
|
16
|
+
|
17
|
+
rule(:find_by_id_keyword) { str('find_by_id') }
|
18
|
+
|
19
|
+
rule(:update_keyword) { str('update') }
|
20
|
+
|
21
|
+
rule(:delete_keyword) { str('delete') }
|
22
|
+
|
23
|
+
rule(:write_keyword) { str('write') }
|
24
|
+
|
25
|
+
rule(:write_file_keyword) { str('write_file') }
|
26
|
+
|
27
|
+
rule(:redirect_keyword) { str('redirect') }
|
28
|
+
|
29
|
+
rule(:if_keyword) { str('if') }
|
30
|
+
|
31
|
+
rule(:else_keyword) { str('else') }
|
32
|
+
|
33
|
+
rule(:for_keyword) { str('for') }
|
34
|
+
|
35
|
+
rule(:in_keyword) { str('in') }
|
36
|
+
|
37
|
+
rule(:while_keyword) { str('while') }
|
38
|
+
|
39
|
+
rule(:get_keyword) { str('get') }
|
40
|
+
|
41
|
+
rule(:post_keyword) { str('post') }
|
42
|
+
|
43
|
+
rule(:model_keyword) { str('model') }
|
44
|
+
|
45
|
+
rule(:string_keyword) { str('string') }
|
46
|
+
|
47
|
+
rule(:integer_keyword) { str('integer') }
|
48
|
+
|
49
|
+
rule(:integer_cast_keyword) { str('int') }
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:addition_operator) { space? >> str('+') >> space? }
|
8
|
+
rule(:subtraction_operator) { space? >> str('-') >> space? }
|
9
|
+
rule(:multiplication_operator) { space? >> str('*') >> space? }
|
10
|
+
rule(:division_operator) { space? >> str('/') >> space? }
|
11
|
+
|
12
|
+
rule(:arithmetic_operator) { addition_operator | subtraction_operator | multiplication_operator | division_operator }
|
13
|
+
|
14
|
+
|
15
|
+
rule(:and_operator) { space? >> str('&&') >> space? }
|
16
|
+
rule(:or_operator) { space? >> str('||') >> space? }
|
17
|
+
rule(:not_operator) { space? >> str('!') }
|
18
|
+
|
19
|
+
rule(:boolean_operator) { and_operator | or_operator }
|
20
|
+
|
21
|
+
|
22
|
+
rule(:assignment_operator) { space? >> str("=") >> space? }
|
23
|
+
|
24
|
+
rule(:less_than_operator) { space? >> str("<") >> space? }
|
25
|
+
rule(:greater_than_operator) { space? >> str(">") >> space? }
|
26
|
+
rule(:equal_to_operator) { space? >> str("==") >> space? }
|
27
|
+
rule(:less_than_or_equal_to_operator) { space? >> str("<=") >> space? }
|
28
|
+
rule(:greater_than_or_equal_to_operator) { space? >> str(">=") >> space? }
|
29
|
+
rule(:not_equal_to_operator) { space? >> str("!=") >> space? }
|
30
|
+
|
31
|
+
rule(:conditional_operator) { less_than_or_equal_to_operator | greater_than_or_equal_to_operator | not_equal_to_operator | equal_to_operator | less_than_operator | greater_than_operator }
|
32
|
+
|
33
|
+
rule(:query_find_operator) { less_than_or_equal_to_operator | greater_than_or_equal_to_operator | not_equal_to_operator | assignment_operator | less_than_operator | greater_than_operator }
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:url_method) { get_keyword.as(:url_method) | post_keyword.as(:url_method) }
|
8
|
+
|
9
|
+
rule(:url_variable) { colon >> identifier.as(:url_variable) }
|
10
|
+
|
11
|
+
rule(:url_token) { (url_variable | identifier.as(:url_token)) >> fwd_slash.maybe }
|
12
|
+
|
13
|
+
rule(:url) { fwd_slash >> url_token.repeat(0) }
|
14
|
+
|
15
|
+
|
16
|
+
rule(:model_definition_statement) { model_keyword >> space >> identifier.as(:model_name) }
|
17
|
+
|
18
|
+
rule(:model_attribute_type) { string_keyword | integer_keyword }
|
19
|
+
|
20
|
+
rule(:model_attribute_definition_statement) { identifier.as(:attribute_name) >> space >> model_attribute_type.as(:attribute_type) }
|
21
|
+
|
22
|
+
rule(:model_definition) { model_definition_statement.as(:model_definition_statement) | model_attribute_definition_statement.as(:model_attribute_definition_statement) }
|
23
|
+
|
24
|
+
|
25
|
+
rule(:write_statement) { write_keyword >> space >> string_valued_expression.as(:write_statement_param) }
|
26
|
+
|
27
|
+
rule(:write_file_statement) { write_file_keyword >> space >> string_valued_expression.as(:file_name) >> (space? >> comma >> space? >> variables).as(:template_values).repeat(0) }
|
28
|
+
|
29
|
+
|
30
|
+
rule(:redirect_statement) { redirect_keyword >> space >> string_valued_expression.as(:redirect_statement_param) }
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:right_arithmetic_expression) { arithmetic_operator >> numeric_value }
|
8
|
+
|
9
|
+
rule(:simple_arithmetic_expression) { numeric_value >> arithmetic_operator >> numeric_value }
|
10
|
+
|
11
|
+
rule(:nested_arithmetic_expression) { simple_arithmetic_expression >> right_arithmetic_expression.repeat(0) }
|
12
|
+
|
13
|
+
rule(:simple_numeric_valued_expression) { nested_arithmetic_expression | number | variables }
|
14
|
+
|
15
|
+
rule(:parenthesized_arithmetic_expression) { lparen >> simple_numeric_valued_expression >> rparen }
|
16
|
+
|
17
|
+
rule(:parenthesized_right_arithmetic_expression) { arithmetic_operator >> parenthesized_arithmetic_expression }
|
18
|
+
|
19
|
+
rule(:nested_parenthesized_right_arithmetic_expression) { arithmetic_operator >> nested_parenthesized_arithmetic_expression }
|
20
|
+
|
21
|
+
rule(:simple_parenthesized_arithmetic_expression) { parenthesized_arithmetic_expression >> (parenthesized_right_arithmetic_expression | right_arithmetic_expression).repeat(0) }
|
22
|
+
|
23
|
+
rule(:nested_parenthesized_arithmetic_expression) { lparen >> simple_parenthesized_arithmetic_expression >> rparen }
|
24
|
+
|
25
|
+
rule(:nested_parenthesized_right_arithmetic_expression) { arithmetic_operator >> nested_parenthesized_arithmetic_expression }
|
26
|
+
|
27
|
+
rule(:arithmetic_expression) { (nested_parenthesized_arithmetic_expression | simple_parenthesized_arithmetic_expression | simple_numeric_valued_expression) >> (nested_parenthesized_right_arithmetic_expression | parenthesized_right_arithmetic_expression | right_arithmetic_expression).repeat(0)}
|
28
|
+
|
29
|
+
rule(:parenthesized_numeric_valued_expression) { lparen >> (arithmetic_expression | simple_numeric_valued_expression) >> rparen }
|
30
|
+
|
31
|
+
rule(:unparenthesized_numeric_valued_expression) { arithmetic_expression.as(:arithmetic_expression) | simple_numeric_valued_expression.as(:arithmetic_expression) }
|
32
|
+
|
33
|
+
rule(:numeric_valued_expression) { unparenthesized_numeric_valued_expression | parenthesized_numeric_valued_expression.as(:arithmetic_expression) }
|
34
|
+
|
35
|
+
|
36
|
+
rule(:boolean_operand) { conditional_statement | primitives }
|
37
|
+
|
38
|
+
rule(:right_boolean_expression) { boolean_operator >> boolean_operand }
|
39
|
+
|
40
|
+
rule(:simple_not_expression) { not_operator >> boolean_operand }
|
41
|
+
|
42
|
+
rule(:simple_binary_boolean_expression) { boolean_operand >> (and_operator | or_operator) >> boolean_operand }
|
43
|
+
|
44
|
+
rule(:simple_boolean_expression) { simple_binary_boolean_expression | simple_not_expression }
|
45
|
+
|
46
|
+
rule(:nested_boolean_expression) { simple_boolean_expression >> right_boolean_expression.repeat(0) }
|
47
|
+
|
48
|
+
rule(:parenthesized_simple_boolean_expression) { lparen >> simple_boolean_expression >> rparen }
|
49
|
+
|
50
|
+
rule(:parenthesized_nested_right_boolean_expression) { boolean_operator >> parenthesized_simple_boolean_expression }
|
51
|
+
|
52
|
+
rule(:parenthesized_nested_boolean_expression) { parenthesized_simple_boolean_expression >> parenthesized_nested_right_boolean_expression.repeat(0) }
|
53
|
+
|
54
|
+
rule(:parenthesized_boolean_expression) { parenthesized_nested_boolean_expression | parenthesized_simple_boolean_expression }
|
55
|
+
|
56
|
+
rule(:unparenthesized_boolean_valued_expression) { parenthesized_boolean_expression | nested_boolean_expression }
|
57
|
+
|
58
|
+
rule(:parenthesized_boolean_valued_expression) { lparen >> unparenthesized_boolean_valued_expression >> rparen }
|
59
|
+
|
60
|
+
rule(:not_expression) { not_operator >> (unparenthesized_boolean_valued_expression | parenthesized_boolean_valued_expression) }
|
61
|
+
|
62
|
+
rule(:boolean_valued_expression) { unparenthesized_boolean_valued_expression.as(:boolean_expression) | parenthesized_boolean_valued_expression.as(:boolean_expression) | not_expression.as(:boolean_expression)}
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
rule(:right_conditional_expression) { conditional_operator >> primitives }
|
67
|
+
|
68
|
+
rule(:simple_conditional_expression) { primitives >> conditional_operator >> primitives }
|
69
|
+
|
70
|
+
rule(:nested_conditional_expression) { simple_conditional_expression >> right_conditional_expression.repeat(0) }
|
71
|
+
|
72
|
+
rule(:parenthesized_simple_conditional_expression) { lparen >> simple_conditional_expression >> rparen }
|
73
|
+
|
74
|
+
rule(:parenthesized_nested_right_conditional_expression) { conditional_operator >> parenthesized_simple_conditional_expression }
|
75
|
+
|
76
|
+
rule(:parenthesized_nested_conditional_expression) { parenthesized_simple_conditional_expression >> parenthesized_nested_right_conditional_expression.repeat(0) }
|
77
|
+
|
78
|
+
rule(:parenthesized_conditional_expression) { parenthesized_nested_conditional_expression | parenthesized_simple_conditional_expression }
|
79
|
+
|
80
|
+
rule(:unparenthesized_conditional_statement) { parenthesized_conditional_expression | nested_conditional_expression }
|
81
|
+
|
82
|
+
rule(:parenthesized_conditional_statement) { lparen >> unparenthesized_conditional_statement >> rparen }
|
83
|
+
|
84
|
+
rule(:conditional_statement) { parenthesized_conditional_statement | unparenthesized_conditional_statement }
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:dot) { str(".") }
|
8
|
+
rule(:comma) { str(",") }
|
9
|
+
rule(:space) { str(" ") }
|
10
|
+
rule(:space?) { space.maybe }
|
11
|
+
|
12
|
+
rule(:colon) { str(":") }
|
13
|
+
rule(:fwd_slash) { str("/") }
|
14
|
+
|
15
|
+
rule(:single_quotes) { str("'") }
|
16
|
+
rule(:double_quotes) { str('"') }
|
17
|
+
|
18
|
+
rule(:lparen) { str("(") }
|
19
|
+
rule(:rparen) { str(")") }
|
20
|
+
|
21
|
+
rule(:left_square_bracket) { str('[') }
|
22
|
+
rule(:right_square_bracket) { str(']') }
|
23
|
+
|
24
|
+
rule(:integer) { match('[0-9]').repeat(1) }
|
25
|
+
rule(:floating_point_number) { integer >> dot >> integer }
|
26
|
+
|
27
|
+
rule(:number) { space? >> (floating_point_number | integer) >> space? }
|
28
|
+
|
29
|
+
rule(:word) { space? >> match('[\w]').repeat(1) >> space? }
|
30
|
+
|
31
|
+
rule :single_quoted_string do
|
32
|
+
single_quotes >>
|
33
|
+
(
|
34
|
+
(str('\\') >> any) |
|
35
|
+
(single_quotes.absent? >> any)
|
36
|
+
).repeat >>
|
37
|
+
single_quotes
|
38
|
+
end
|
39
|
+
|
40
|
+
rule :double_quoted_string do
|
41
|
+
double_quotes >>
|
42
|
+
(
|
43
|
+
(str('\\') >> any) |
|
44
|
+
(double_quotes.absent? >> any)
|
45
|
+
).repeat >>
|
46
|
+
double_quotes
|
47
|
+
end
|
48
|
+
rule(:string_value) { single_quoted_string | double_quoted_string }
|
49
|
+
|
50
|
+
rule(:identifier) { match('[A-Za-z]') >> match['[A-Za-z0-9_]'].repeat(0) }
|
51
|
+
|
52
|
+
rule(:hash_attribute) { string_value | identifier }
|
53
|
+
rule(:hash_value) { identifier >> left_square_bracket >> hash_attribute >> right_square_bracket }
|
54
|
+
|
55
|
+
rule(:object_value) { identifier >> dot >> identifier }
|
56
|
+
|
57
|
+
rule(:variables) { space? >> (object_value.as(:object_value) | hash_value.as(:hash_value) | identifier.as(:identifier)) >> space? }
|
58
|
+
|
59
|
+
rule(:string_valued_expression) { read_statement.as(:read_statement) | string_value.as(:string) | variables }
|
60
|
+
|
61
|
+
rule(:numeric_value) { number | object_value | hash_value | identifier }
|
62
|
+
|
63
|
+
rule(:simple_primitives) { space? >> (number | string_value | object_value | hash_value | identifier) >> space? }
|
64
|
+
|
65
|
+
rule(:parenthesized_primitives) { lparen >> simple_primitives >> rparen }
|
66
|
+
|
67
|
+
rule(:primitives) { parenthesized_primitives | simple_primitives }
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:read_statement) { read_keyword >> space >> string_valued_expression.as(:read_statement_param) }
|
8
|
+
|
9
|
+
rule(:string_concatenation_right_expression) { addition_operator >> space? >> string_valued_expression }
|
10
|
+
|
11
|
+
rule(:string_concatenation_expression) { string_valued_expression >> space? >> string_concatenation_right_expression.repeat(0) }
|
12
|
+
|
13
|
+
rule(:integer_casted_expression) { integer_cast_keyword.as(:int) >> space? >> lparen >> space? >> value_returning_expression >> space? >> rparen }
|
14
|
+
|
15
|
+
rule(:value_returning_expression) { query | read_statement.as(:read_statement) | boolean_valued_expression | conditional_statement.as(:conditional_statement) | string_concatenation_expression | string_valued_expression | numeric_valued_expression }
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
module Shift
|
4
|
+
module Parser
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
rule(:assignment_statement) { variables.as(:left) >> assignment_operator >> (integer_casted_expression | value_returning_expression).as(:right)}
|
8
|
+
|
9
|
+
rule(:void_statements) { url.as(:url) | url_method | model_definition | control_statement | assignment_statement.as(:assignment_statement) | write_file_statement.as(:write_file_statement) | write_statement.as(:write_statement) | redirect_statement.as(:redirect_statement) }
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
|
3
|
+
require_relative 'parser/token_parser.rb'
|
4
|
+
require_relative 'parser/keyword_parser.rb'
|
5
|
+
require_relative 'parser/operator_parser.rb'
|
6
|
+
require_relative 'parser/simple_expression_parser'
|
7
|
+
require_relative 'parser/db_query_parser'
|
8
|
+
require_relative 'parser/value_returning_expression_parser'
|
9
|
+
require_relative 'parser/control_statement_parser'
|
10
|
+
require_relative 'parser/routing_expression_parser'
|
11
|
+
require_relative 'parser/void_statement_parser'
|
12
|
+
|
13
|
+
module Shift
|
14
|
+
class ShiftParser < Parslet::Parser
|
15
|
+
include Shift::Parser
|
16
|
+
|
17
|
+
rule(:expression) { void_statements | integer_casted_expression | value_returning_expression}
|
18
|
+
root(:expression)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
=begin
|
23
|
+
parser = Shift::ShiftParser.new
|
24
|
+
|
25
|
+
p parser.parse("123")
|
26
|
+
p parser.parse("123.456")
|
27
|
+
p parser.parse("'abc'")
|
28
|
+
p parser.parse('"def"')
|
29
|
+
p parser.parse('"Hello World"')
|
30
|
+
p parser.parse("test")
|
31
|
+
p parser.parse("data[test]")
|
32
|
+
p parser.parse("data['test']")
|
33
|
+
p parser.parse("data.test")
|
34
|
+
|
35
|
+
p parser.parse("5+5+5")
|
36
|
+
p parser.parse("5*5")
|
37
|
+
p parser.parse("(5+5)")
|
38
|
+
p parser.parse("(5)")
|
39
|
+
p parser.parse("(5+5)+5")
|
40
|
+
p parser.parse("(5+5)+(5)")
|
41
|
+
p parser.parse("(5+5)*(5-5)")
|
42
|
+
p parser.parse("(5+5)*(5-5)-(2+2)")
|
43
|
+
p parser.parse("(5+5)* (5-5)")
|
44
|
+
p parser.parse("((5 + 5) * (10 - 10))")
|
45
|
+
p parser.parse("((5 + 5) * (10 - 10)) * (5 + 4)")
|
46
|
+
p parser.parse("((5 + 5) * (10 - 10)) * ((5 + 4) * (5+5))")
|
47
|
+
p parser.parse("(((5 + 5) * (10 - 10)) * ((5 + 4) * (5+5)))")
|
48
|
+
|
49
|
+
p parser.parse("a && b")
|
50
|
+
p parser.parse("a && b || c")
|
51
|
+
p parser.parse("(a && b)")
|
52
|
+
p parser.parse("(a && b) || (c || d)")
|
53
|
+
p parser.parse("(a && b) || (c || d) || (e && f)")
|
54
|
+
p parser.parse("((a && b) || (c || d) || (e && f))")
|
55
|
+
|
56
|
+
|
57
|
+
p parser.parse("a == b")
|
58
|
+
p parser.parse("a <= b")
|
59
|
+
p parser.parse("a >= b")
|
60
|
+
p parser.parse("a != b")
|
61
|
+
p parser.parse("a < b")
|
62
|
+
p parser.parse("a > b")
|
63
|
+
p parser.parse("(a == b)")
|
64
|
+
|
65
|
+
p parser.parse("(a == b) && (c == d)")
|
66
|
+
p parser.parse("(a == b) || (c == d)")
|
67
|
+
p parser.parse("!(c == d)")
|
68
|
+
p parser.parse("!((a == b) || (c == d) && (e == f))")
|
69
|
+
|
70
|
+
|
71
|
+
p parser.parse("read abc")
|
72
|
+
p parser.parse("read 'abc'")
|
73
|
+
p parser.parse("read read 'abc'")
|
74
|
+
|
75
|
+
p parser.parse("all Todo")
|
76
|
+
p parser.parse("new Todo")
|
77
|
+
p parser.parse("update Todo")
|
78
|
+
p parser.parse("delete Todo")
|
79
|
+
p parser.parse("find_by_id Todo data")
|
80
|
+
p parser.parse("find_by_id Todo data['id']")
|
81
|
+
|
82
|
+
p parser.parse("a = 5")
|
83
|
+
p parser.parse("a = 5 + 10")
|
84
|
+
p parser.parse("a = b")
|
85
|
+
p parser.parse("a = read 'test'")
|
86
|
+
|
87
|
+
p parser.parse("write 'test'")
|
88
|
+
p parser.parse('write_file "test.html"')
|
89
|
+
|
90
|
+
p parser.parse("redirect '/'")
|
91
|
+
|
92
|
+
# NOTE: Control statements do not have parenthesis
|
93
|
+
|
94
|
+
p parser.parse("if a == b")
|
95
|
+
p parser.parse("if (a == b)")
|
96
|
+
p parser.parse("if ((a == b) && (c == d))")
|
97
|
+
p parser.parse("else")
|
98
|
+
p parser.parse("for todo in todos")
|
99
|
+
p parser.parse("while (a == b)")
|
100
|
+
p parser.parse("while !((a == 'b') && (c == d))")
|
101
|
+
|
102
|
+
p parser.parse("get")
|
103
|
+
p parser.parse("post")
|
104
|
+
|
105
|
+
p parser.parse("/")
|
106
|
+
p parser.parse("/todos")
|
107
|
+
p parser.parse("/todos/new")
|
108
|
+
p parser.parse("/todos/:id/")
|
109
|
+
p parser.parse("/todos/:id/edit")
|
110
|
+
|
111
|
+
p parser.parse("model Todo")
|
112
|
+
|
113
|
+
p parser.parse("entry string")
|
114
|
+
p parser.parse("priority integer")
|
115
|
+
|
116
|
+
p parser.parse("int(5)")
|
117
|
+
p parser.parse("int(a)")
|
118
|
+
|
119
|
+
p parser.parse("'a'+'b' + c")
|
120
|
+
=end
|