fdlint 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +14 -0
  3. data/README.md +68 -0
  4. data/Rakefile +92 -0
  5. data/bin/fdlint +17 -0
  6. data/lib/base_parser.rb +143 -0
  7. data/lib/cmd_runner.rb +145 -0
  8. data/lib/context.rb +31 -0
  9. data/lib/css/parser.rb +186 -0
  10. data/lib/css/reader.rb +30 -0
  11. data/lib/css/rule/check_compression_rule.rb +48 -0
  12. data/lib/css/rule/checklist.rb +45 -0
  13. data/lib/css/struct.rb +111 -0
  14. data/lib/encoding_error.rb +6 -0
  15. data/lib/file_validator.rb +38 -0
  16. data/lib/helper/code_type.rb +50 -0
  17. data/lib/helper/color_string.rb +44 -0
  18. data/lib/helper/file_reader.rb +22 -0
  19. data/lib/helper/strenc.rb +65 -0
  20. data/lib/html/parser.rb +212 -0
  21. data/lib/html/query.rb +96 -0
  22. data/lib/html/rule/check_tag_rule.rb +80 -0
  23. data/lib/html/struct.rb +291 -0
  24. data/lib/js/expr/expr.rb +66 -0
  25. data/lib/js/expr/left_hand.rb +63 -0
  26. data/lib/js/expr/operate.rb +92 -0
  27. data/lib/js/expr/primary.rb +166 -0
  28. data/lib/js/parser.rb +116 -0
  29. data/lib/js/rule/all.rb +35 -0
  30. data/lib/js/rule/checklist.rb +41 -0
  31. data/lib/js/rule/file_checker.rb +42 -0
  32. data/lib/js/rule/helper.rb +96 -0
  33. data/lib/js/rule/no_global.rb +87 -0
  34. data/lib/js/stat/if.rb +25 -0
  35. data/lib/js/stat/iter.rb +85 -0
  36. data/lib/js/stat/stat.rb +117 -0
  37. data/lib/js/stat/switch.rb +65 -0
  38. data/lib/js/stat/try.rb +28 -0
  39. data/lib/js/stat/var.rb +40 -0
  40. data/lib/js/struct.rb +248 -0
  41. data/lib/log_entry.rb +49 -0
  42. data/lib/node.rb +28 -0
  43. data/lib/parse_error.rb +13 -0
  44. data/lib/parser_visitable.rb +138 -0
  45. data/lib/position_info.rb +46 -0
  46. data/lib/printer/base_printer.rb +24 -0
  47. data/lib/printer/console_printer.rb +66 -0
  48. data/lib/printer/nocolor_printer.rb +27 -0
  49. data/lib/printer/vim_printer.rb +19 -0
  50. data/lib/rule.rb +241 -0
  51. data/lib/rule_helper.rb +14 -0
  52. data/lib/runner.rb +225 -0
  53. data/rules.d/css.rule +127 -0
  54. data/rules.d/html.dtd.rule +22 -0
  55. data/rules.d/html.prop.rule +51 -0
  56. data/rules.d/html.tag.rule +136 -0
  57. data/rules.d/js.file.rule +13 -0
  58. data/rules.d/js.jquery.rule +56 -0
  59. data/rules.d/js.mergefile.rule +71 -0
  60. data/rules.d/js.rule +84 -0
  61. data/test/all_tests.rb +84 -0
  62. data/test/cli/cli_test.rb +70 -0
  63. data/test/cli/log_level_test.rb +51 -0
  64. data/test/cli/output_format_test.rb +47 -0
  65. data/test/cli/type_test.rb +77 -0
  66. data/test/css/mac_line_end_support_test.rb +38 -0
  67. data/test/css/parser_test.rb +276 -0
  68. data/test/css/rule/check_encoding_test.rb +66 -0
  69. data/test/css/rule/check_list_rule_test.rb +167 -0
  70. data/test/css/rule/compression_test.rb +53 -0
  71. data/test/css/rule/file_name_test.rb +76 -0
  72. data/test/fixtures/css/broken.css +4 -0
  73. data/test/fixtures/css/cbu/36.css +52 -0
  74. data/test/fixtures/css/cbu/china_top.css +324 -0
  75. data/test/fixtures/css/cbu/default-merge.css +3 -0
  76. data/test/fixtures/css/cbu/default.css +13 -0
  77. data/test/fixtures/css/cbu/diy-merge.css +25 -0
  78. data/test/fixtures/css/cbu/fns-v1.css +27 -0
  79. data/test/fixtures/css/cbu/index_v0.1.css +12 -0
  80. data/test/fixtures/css/cbu/merge.css +11 -0
  81. data/test/fixtures/css/cbu/min.css +2 -0
  82. data/test/fixtures/css/cbu/my_home_admin.css +126 -0
  83. data/test/fixtures/css/cbu/nav.css +95 -0
  84. data/test/fixtures/css/cbu/pic_list.css +386 -0
  85. data/test/fixtures/css/cbu/quote-edit.css +18 -0
  86. data/test/fixtures/css/cbu/selloffer.shopwindow.css +1 -0
  87. data/test/fixtures/css/cbu/v1.css +9 -0
  88. data/test/fixtures/css/css3.css +30 -0
  89. data/test/fixtures/css/empty-min.css +0 -0
  90. data/test/fixtures/css/empty.css +0 -0
  91. data/test/fixtures/css/font-family.css +4 -0
  92. data/test/fixtures/css/gb-good.css +14 -0
  93. data/test/fixtures/css/gb_using_star.css +4 -0
  94. data/test/fixtures/css/import.css +18 -0
  95. data/test/fixtures/css/mac-line-sep-err-min.css +1 -0
  96. data/test/fixtures/css/mac-line-sep-err.css +1 -0
  97. data/test/fixtures/css/mac-line-sep-good-min.css +1 -0
  98. data/test/fixtures/css/mac-line-sep-good.css +1 -0
  99. data/test/fixtures/css/multi-encoding-in-a-file.css +0 -0
  100. data/test/fixtures/css/simple.css +1 -0
  101. data/test/fixtures/css/using_expr.css +8 -0
  102. data/test/fixtures/css/using_hack.css +21 -0
  103. data/test/fixtures/css/using_id.css +1 -0
  104. data/test/fixtures/css/using_star.css +4 -0
  105. data/test/fixtures/css/utf8_good.css +6 -0
  106. data/test/fixtures/css/utf8_good_declaring_charset.css +7 -0
  107. data/test/fixtures/css/utf8_using_star.css +5 -0
  108. data/test/fixtures/html/1-1.html +120 -0
  109. data/test/fixtures/html/1-2.html +120 -0
  110. data/test/fixtures/html/cms.html +373 -0
  111. data/test/fixtures/html/css_out_of_head.html +9 -0
  112. data/test/fixtures/html/fdev-template.html +22 -0
  113. data/test/fixtures/html/google.com.html +33 -0
  114. data/test/fixtures/html/mixed_log_levels.html +4 -0
  115. data/test/fixtures/html/mixed_types.html +13 -0
  116. data/test/fixtures/html/no_dtd.html +6 -0
  117. data/test/fixtures/html/readme.html +94 -0
  118. data/test/fixtures/html/review.board.html +163 -0
  119. data/test/fixtures/html/syntax_err.html +3 -0
  120. data/test/fixtures/html/train/detail/345/233/276/346/226/207/347/273/223/345/220/210.html +208 -0
  121. data/test/fixtures/html/train/detail/347/232/204Flash.html +212 -0
  122. data/test/fixtures/html/train/detail/347/232/204Vedio.html +212 -0
  123. data/test/fixtures/html/train/index.html +37 -0
  124. data/test/fixtures/html/train/test.html +1 -0
  125. data/test/fixtures/html/train//344/277/256/346/224/271/344/270/200/347/272/247/345/210/206/347/261/273.html +112 -0
  126. data/test/fixtures/html/train//344/277/256/346/224/271/345/255/220/345/210/206/347/261/273.html +108 -0
  127. data/test/fixtures/html/train//344/277/256/346/224/271/350/257/276/347/250/213.html +195 -0
  128. data/test/fixtures/html/train//345/215/232/345/256/242/350/256/276/347/275/256.html +142 -0
  129. data/test/fixtures/html/train//346/265/217/350/247/210/350/256/260/345/275/225.html +191 -0
  130. data/test/fixtures/html/train//346/267/273/345/212/240/344/270/200/347/272/247/345/210/206/347/261/273.html +113 -0
  131. data/test/fixtures/html/train//346/267/273/345/212/240/345/255/220/345/210/206/347/261/273.html +112 -0
  132. data/test/fixtures/html/train//346/267/273/345/212/240/350/257/276/347/250/213.html +195 -0
  133. data/test/fixtures/html/train//347/231/273/345/275/225.html +20 -0
  134. data/test/fixtures/html/train//347/256/241/347/220/206/345/210/206/347/261/273.html +210 -0
  135. data/test/fixtures/html/train//347/256/241/347/220/206/345/217/215/351/246/210.html +222 -0
  136. data/test/fixtures/html/train//347/256/241/347/220/206/350/257/276/347/250/213.html +284 -0
  137. data/test/fixtures/html/train//347/256/241/347/220/206/350/264/246/346/210/267.html +107 -0
  138. data/test/fixtures/html/train//347/275/221/344/270/212/345/237/271/350/256/255home/351/241/265.html +354 -0
  139. data/test/fixtures/html/train//347/275/221/345/225/206/345/237/271/350/256/255list/351/241/265.html +255 -0
  140. data/test/fixtures/html/train//350/256/276/347/275/256/351/246/226/351/241/265/346/216/250/350/215/220.html +168 -0
  141. data/test/fixtures/html/train//350/257/264/346/230/216.txt +3 -0
  142. data/test/fixtures/html/train//351/246/226/351/241/265/345/271/277/345/221/212/350/256/276/347/275/256.html +297 -0
  143. data/test/fixtures/html/unescaped.html +2 -0
  144. data/test/fixtures/html/view.vm +916 -0
  145. data/test/fixtures/js/jquery-1.7.js +9300 -0
  146. data/test/fixtures/js/scope-test.js +22 -0
  147. data/test/helper.rb +41 -0
  148. data/test/html/mixed_type_test.rb +35 -0
  149. data/test/html/parser/parse_comment_test.rb +47 -0
  150. data/test/html/parser/parse_dtd_test.rb +46 -0
  151. data/test/html/parser/parse_script_tag_test.rb +55 -0
  152. data/test/html/parser/parse_with_auto_close_tag_test.rb +41 -0
  153. data/test/html/parser/parse_with_diff_case_test.rb +38 -0
  154. data/test/html/parser/parse_with_emtpy_test.rb +22 -0
  155. data/test/html/parser/parse_with_multi_children_test.rb +27 -0
  156. data/test/html/parser/parse_with_multi_line_test.rb +41 -0
  157. data/test/html/parser/parse_with_prop_test.rb +88 -0
  158. data/test/html/parser/parse_with_script_tag_test.rb +26 -0
  159. data/test/html/parser/parse_with_selfclosing_test.rb +39 -0
  160. data/test/html/parser/parse_with_simple_tag_test.rb +44 -0
  161. data/test/html/parser/parse_with_simple_tree_test.rb +40 -0
  162. data/test/html/parser/parse_with_style_tag_test.rb +22 -0
  163. data/test/html/parser/parse_with_text_test.rb +45 -0
  164. data/test/html/parser_test.rb +52 -0
  165. data/test/html/query_test.rb +52 -0
  166. data/test/html/rule/check_block_level_element_test.rb +52 -0
  167. data/test/html/rule/check_button_test.rb +45 -0
  168. data/test/html/rule/check_class_count_test.rb +36 -0
  169. data/test/html/rule/check_css_in_head_test.rb +53 -0
  170. data/test/html/rule/check_dtd_test.rb +46 -0
  171. data/test/html/rule/check_form_element_name_test.rb +49 -0
  172. data/test/html/rule/check_head_contain_meta_and_title_test.rb +52 -0
  173. data/test/html/rule/check_html_template_test.rb +103 -0
  174. data/test/html/rule/check_hyperlink_with_target_test.rb +40 -0
  175. data/test/html/rule/check_hyperlink_with_title_test.rb +43 -0
  176. data/test/html/rule/check_id_n_class_downcase_test.rb +40 -0
  177. data/test/html/rule/check_img_with_alt_prop_test.rb +33 -0
  178. data/test/html/rule/check_no_import_css_test.rb +36 -0
  179. data/test/html/rule/check_prop_have_value_test.rb +32 -0
  180. data/test/html/rule/check_prop_seperator_test.rb +32 -0
  181. data/test/html/rule/check_style_prop_test.rb +30 -0
  182. data/test/html/rule/check_tag_closed_test.rb +59 -0
  183. data/test/html/rule/check_tag_downcase_test.rb +51 -0
  184. data/test/html/rule/check_unescape_char_test.rb +35 -0
  185. data/test/html/rule/check_unique_import_test.rb +56 -0
  186. data/test/html/rule_test.rb +62 -0
  187. data/test/js/expr/expr.rb +57 -0
  188. data/test/js/expr/left_hand.rb +25 -0
  189. data/test/js/expr/operate.rb +145 -0
  190. data/test/js/expr/primary.rb +89 -0
  191. data/test/js/parser_test.rb +98 -0
  192. data/test/js/rule/alert_check_test.rb +37 -0
  193. data/test/js/rule/all_test.rb +23 -0
  194. data/test/js/rule/base_test.rb +34 -0
  195. data/test/js/rule/file_checker_test.rb +131 -0
  196. data/test/js/rule/jq_check_test.rb +90 -0
  197. data/test/js/rule/nest_try_catch_test.rb +71 -0
  198. data/test/js/rule/new_object_and_new_array_test.rb +38 -0
  199. data/test/js/rule/no_eval_test.rb +34 -0
  200. data/test/js/rule/no_global_test.rb +88 -0
  201. data/test/js/rule/private_method_check_test.rb +58 -0
  202. data/test/js/rule/semicolon_test.rb +63 -0
  203. data/test/js/rule/stat_if_with_brace_test.rb +68 -0
  204. data/test/js/rule/stat_if_with_muti_else_test.rb +68 -0
  205. data/test/js/rule/use_strict_equal_test.rb +44 -0
  206. data/test/js/rule_test.rb +47 -0
  207. data/test/js/stat/if.rb +26 -0
  208. data/test/js/stat/iter.rb +115 -0
  209. data/test/js/stat/stat.rb +91 -0
  210. data/test/js/stat/switch.rb +37 -0
  211. data/test/js/stat/try.rb +32 -0
  212. data/test/js/stat/var.rb +38 -0
  213. data/test/parser_visitable_test.rb +102 -0
  214. data/test/position_info_test.rb +66 -0
  215. data/test/rule_dsl/dsl_basic_test.rb +91 -0
  216. data/test/rule_dsl/importing_test.rb +48 -0
  217. data/test/runner/log_level_test.rb +58 -0
  218. metadata +317 -0
@@ -0,0 +1,117 @@
1
+ require_relative 'var'
2
+ require_relative 'if'
3
+ require_relative 'switch'
4
+ require_relative 'iter'
5
+ require_relative 'try'
6
+
7
+ module XRay
8
+ module JS
9
+ module Stat
10
+
11
+ module Stat
12
+
13
+ include Var, If, Switch, Iter, Try
14
+
15
+ def parse_statement
16
+ # 在1.8下map是无序的,所以这里只能用数组来实现
17
+ map = [
18
+ /\{/, 'block',
19
+ /\;/, 'empty',
20
+ /var\b/, 'var',
21
+ /if\b/, 'if',
22
+ /switch\b/, 'switch',
23
+ /do\b/, 'dowhile',
24
+ /while\b/, 'while',
25
+ /for\b/, 'for',
26
+ /continue\b/, 'continue',
27
+ /break\b/, 'break',
28
+ /return\b/, 'return',
29
+ /throw\b/, 'throw',
30
+ /try\b/, 'try',
31
+ /./, 'expression'
32
+ ]
33
+
34
+ 0.upto(map.size / 2 - 1) do |i|
35
+ if check(map[i * 2])
36
+ return self.send('parse_stat_' + map[i * 2 + 1])
37
+ end
38
+ end
39
+ end
40
+
41
+ def parse_stat_block
42
+ log 'parse stat block'
43
+
44
+ pos = skip /\{/
45
+ stats = batch(:parse_statement, /\}/)
46
+ skip /\}/
47
+
48
+ create_element BlockStatement, Elements.new(stats), pos
49
+ end
50
+
51
+ def parse_stat_empty
52
+ log 'parse stat empty'
53
+ pos = skip /;/
54
+
55
+ stat = create_element Statement, 'empty'
56
+ stat.end_with_semicolon = true
57
+ stat
58
+ end
59
+
60
+ def parse_stat_expression
61
+ log 'parse stat expression'
62
+
63
+ expr = parse_expression
64
+ stat = create_element ExpressionStatement, expr
65
+ after_parse_statement stat
66
+ end
67
+
68
+ def parse_stat_continue
69
+ log 'parse stat continue'
70
+ parse_stat_simple /continue/, :parse_expr_identifier
71
+ end
72
+
73
+ def parse_stat_break
74
+ log 'parse stat break'
75
+ parse_stat_simple /break/, :parse_expr_identifier
76
+ end
77
+
78
+ def parse_stat_return
79
+ log 'parse stat return'
80
+ parse_stat_simple /return/, :parse_expression
81
+ end
82
+
83
+ def parse_stat_throw
84
+ log 'parse stat throw'
85
+ parse_stat_simple /throw/, :parse_expression
86
+ end
87
+
88
+ def parse_stat_label
89
+ log 'parse stat label'
90
+ raise 'not impelments'
91
+ end
92
+
93
+ def after_parse_statement(stat)
94
+ skip /[ \t]*/, true
95
+ colon = !!check(/;/, true)
96
+ stat.end_with_semicolon = colon
97
+ colon ? skip(/;/, true) :
98
+ (eos? || check(/\}/)) ? nil : skip(/\n/, true)
99
+ stat
100
+ end
101
+
102
+ private
103
+
104
+ def parse_stat_simple(pattern, action)
105
+ type = scan pattern
106
+ skip /[ \t]*/, true
107
+ left = (eos? || check(/[;\n}]/, true)) ? nil : self.send(action)
108
+
109
+ stat = create_element Statement, type.text, left, nil, type.position
110
+ after_parse_statement stat
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,65 @@
1
+ module XRay
2
+ module JS
3
+ module Stat
4
+
5
+ module Switch
6
+ def parse_stat_switch
7
+ log 'parse stat switch'
8
+
9
+ pos = skip /switch\s*\(/
10
+ expression = parse_expression
11
+ skip /\)/
12
+ block = parse_stat_caseblock
13
+
14
+ create_element SwitchStatement, expression, block, pos
15
+ end
16
+
17
+ def parse_stat_caseblock
18
+ log 'parse stat caseblock'
19
+
20
+ pos = skip /\{/
21
+ case_clauses = check(/case\b/) ? parse_stat_caseclauses : nil
22
+ default_clause = check(/default\b/) ? parse_stat_defaultclause : nil
23
+ bottom_case_clauses = check(/case\b/) ? parse_stat_caseclauses : nil
24
+ skip /\}/
25
+
26
+ create_element CaseBlockStatement, case_clauses, default_clause,
27
+ bottom_case_clauses, pos
28
+ end
29
+
30
+ def parse_stat_caseclauses
31
+ log 'parse stat caseclauses'
32
+ stats = batch(:parse_stat_caseclause, /default\b|\}/)
33
+ create_element Elements, stats
34
+ end
35
+
36
+ def parse_stat_caseclause
37
+ log 'parse stat caseclause'
38
+
39
+ pos = skip /case/
40
+ expr = parse_expression
41
+ skip /:/
42
+ stats = parse_statement_list
43
+ create_element Statement, 'caseclause', expr, stats, pos
44
+ end
45
+
46
+ def parse_stat_defaultclause
47
+ log 'parse stat defaultclause'
48
+
49
+ pos = skip /default\s*:/
50
+ stats = parse_statement_list
51
+ create_element Statement, 'defaultclause', stats, nil, pos
52
+ end
53
+
54
+ private
55
+
56
+ def parse_statement_list
57
+ elms = batch(:parse_statement, /case\b|default\b|\}/)
58
+ Elements.new elms
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,28 @@
1
+ module XRay
2
+ module JS
3
+ module Stat
4
+
5
+ module Try
6
+ def parse_stat_try
7
+ pos = skip /try/
8
+ try_part = parse_stat_block
9
+
10
+ catch_part = if check /catch\b/
11
+ catch_pos = skip /catch\s*\(/
12
+ id = parse_expr_identifier
13
+ skip /\)/
14
+ create_element Statement, 'catch', id, parse_stat_block, catch_pos
15
+ end
16
+
17
+ finally_part = if check /finally\b/
18
+ skip /finally/
19
+ parse_stat_block
20
+ end
21
+
22
+ create_element TryStatement, try_part, catch_part, finally_part, pos
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,40 @@
1
+ module XRay
2
+ module JS
3
+ module Stat
4
+
5
+ module Var
6
+ def parse_stat_var
7
+ log 'parse stat var'
8
+
9
+ pos = skip /var/
10
+
11
+ decs = parse_stat_var_declarationlist
12
+ stat = create_element VarStatement, decs, pos
13
+ after_parse_statement stat
14
+ end
15
+
16
+ def parse_stat_var_declarationlist
17
+ log 'parse stat var declarationlist'
18
+ decs = []
19
+ decs << parse_stat_var_declaration
20
+ while check /,/
21
+ skip /,/
22
+ decs << parse_stat_var_declaration
23
+ end
24
+ create_element Elements, decs
25
+ end
26
+
27
+ def parse_stat_var_declaration
28
+ log 'parse stat var declaration'
29
+ name = parse_expr_identifier
30
+ expr = if check(/\=/)
31
+ skip /\=/
32
+ parse_expr_assignment
33
+ end
34
+ create_element Statement, 'var=', name, expr
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
data/lib/js/struct.rb ADDED
@@ -0,0 +1,248 @@
1
+ require_relative '../node'
2
+
3
+ module XRay
4
+ module JS
5
+ Node = XRay::Node
6
+
7
+ class Element < Node
8
+ attr_reader :type, :left, :right
9
+
10
+ def initialize(type, left = nil, right = nil, position = nil)
11
+ @type, @left, @right, @position = type, left, right, position
12
+ end
13
+
14
+ def text
15
+ "(#{type},#{left},#{right})"
16
+ end
17
+
18
+ def position
19
+ @position ? @position :
20
+ left ? left.position :
21
+ right ? right.position : nil
22
+ end
23
+
24
+ def contains?(target)
25
+ return true if target == @type
26
+ left && left.respond_to?(:contains?) && left.contains?(target) or
27
+ right && right.respond_to?(:contains?) && right.contains?(target)
28
+ end
29
+
30
+ end
31
+
32
+ class Elements < Node
33
+ attr_reader :elements, :type
34
+
35
+ def initialize(elements, position = nil)
36
+ @elements, @position = elements, position
37
+ @type = 'elements'
38
+ end
39
+
40
+ def text
41
+ "[#{elements.collect(&:text).join(',')}]"
42
+ end
43
+
44
+ def position
45
+ @position ? @position :
46
+ elements.empty? ? nil : elements[0].position
47
+ end
48
+
49
+ def method_missing(m, *args, &block)
50
+ @elements.send m, *args, &block
51
+ end
52
+
53
+ def contains?( target )
54
+ @elements.any? {|elm| elm.contains? target }
55
+ end
56
+
57
+ alias :contain? :contains?
58
+ end
59
+
60
+ class Program < Element
61
+ alias :elements :left
62
+
63
+ def initialize(elements)
64
+ super 'program', elements
65
+ end
66
+
67
+ end
68
+
69
+ class FunctionDeclaraion < Element
70
+ attr_reader :body
71
+ alias :name :left
72
+ alias :parameters :right
73
+
74
+ def initialize(name, parameters, body, pos)
75
+ super 'function', name, parameters, pos
76
+ @body = body
77
+ end
78
+ end
79
+
80
+ class Statement < Element
81
+
82
+ def end_with_semicolon=(end_with_semicolon)
83
+ @end_with_semicolon = !!end_with_semicolon
84
+ end
85
+
86
+ def end_with_semicolon?
87
+ @end_with_semicolon || false
88
+ end
89
+
90
+ end
91
+
92
+ class VarStatement < Statement
93
+ alias :declarations :left
94
+
95
+ def initialize(declarations, position)
96
+ super 'var', declarations, nil, position
97
+ end
98
+ end
99
+
100
+ class BlockStatement < Statement
101
+ alias :elements :left
102
+
103
+ def initialize(elements, pos)
104
+ super 'block', elements, nil, pos
105
+ end
106
+ end
107
+
108
+ class IfStatement < Statement
109
+ attr_reader :false_part
110
+ alias :condition :left
111
+ alias :true_part :right
112
+
113
+ def initialize(condition, true_part, false_part, position)
114
+ super 'if', condition, true_part, position
115
+ @false_part = false_part
116
+ end
117
+ end
118
+
119
+ class SwitchStatement < Statement
120
+ alias :expression :left
121
+ alias :case_block :right
122
+
123
+ def initialize(expression, case_block, position)
124
+ super 'switch', expression, case_block, position
125
+ end
126
+ end
127
+
128
+ class CaseBlockStatement < Statement
129
+ attr_reader :bottom_case_clauses
130
+ alias :case_clauses :left
131
+ alias :default_clause :right
132
+
133
+ def initialize(case_clauses, default_clause, bottom_case_clauses, position)
134
+ super 'caseblock', case_clauses, default_clause, position
135
+ @bottom_case_clauses = bottom_case_clauses
136
+ end
137
+ end
138
+
139
+ class DowhileStatement < Statement
140
+ alias :body :left
141
+ alias :condition :right
142
+
143
+ def initialize(body, condition, pos)
144
+ super 'dowhile', body, condition, pos
145
+ end
146
+ end
147
+
148
+ class WhileStatement < Statement
149
+ alias :condition :left
150
+ alias :body :right
151
+
152
+ def initialize(condition, body, pos)
153
+ super 'while', condition, body, pos
154
+ end
155
+ end
156
+
157
+ class ForStatement < Statement
158
+ alias :condition :left
159
+ alias :body :right
160
+
161
+ def initialize(condition, body, pos)
162
+ super 'for', condition, body, pos
163
+ end
164
+ end
165
+
166
+ class ForConditionElement < Element
167
+ attr_reader :third
168
+ alias :first :left
169
+ alias :second :right
170
+
171
+ def initialize(type, first, second, third, pos)
172
+ super type, first, second
173
+ @third = third
174
+ end
175
+
176
+ end
177
+
178
+ class TryStatement < Statement
179
+ attr_reader :finally_part
180
+ alias :try_part :left
181
+ alias :catch_part :right
182
+
183
+ def initialize(try_part, catch_part, finally_part, pos)
184
+ super 'try', try_part, catch_part, pos
185
+ @finally_part = finally_part
186
+ end
187
+ end
188
+
189
+ class ExpressionStatement < Statement
190
+ alias :expression :left
191
+
192
+ def initialize(expression)
193
+ super 'expression', expression
194
+ end
195
+ end
196
+
197
+ class Expression < Element
198
+ def left_hand?
199
+ @left_hand || false
200
+ end
201
+
202
+ def left_hand=(left_hand)
203
+ @left_hand = left_hand
204
+ end
205
+ end
206
+
207
+ class PrimaryExpression < Expression
208
+
209
+ def initialize(type, expr, position = nil)
210
+ super type, expr, nil, position
211
+ end
212
+
213
+ def text
214
+ node.text
215
+ end
216
+
217
+ def node
218
+ left
219
+ end
220
+ end
221
+
222
+ class ConditionExpression < Expression
223
+ attr_reader :condition
224
+
225
+ def initialize(condition, left, right)
226
+ super '?:', left, right, condition.position
227
+ @condition = condition
228
+ end
229
+
230
+ def text
231
+ "(#{type},#{condition},#{left},#{right})"
232
+ end
233
+
234
+ end
235
+
236
+ class FunctionExpression < Expression
237
+ attr_reader :body
238
+ alias :name :left
239
+ alias :parameters :right
240
+
241
+ def initialize(func)
242
+ super 'function', func.name, func.parameters, func.position
243
+ @body = func.body
244
+ end
245
+ end
246
+
247
+ end
248
+ end
data/lib/log_entry.rb ADDED
@@ -0,0 +1,49 @@
1
+ require_relative 'helper/color_string'
2
+
3
+ module XRay
4
+
5
+ LogEntry = Struct.new(:message, :level, :row, :column)
6
+
7
+ class LogEntry
8
+
9
+ def initialize(message, level, row = 0, colmn = 0)
10
+ super
11
+ end
12
+
13
+ def to_s
14
+ pos = row.nil? ? "" : "[#{row},#{column}]"
15
+ "[#{level.to_s.upcase}] #{pos} #{message}"
16
+ end
17
+
18
+ def to_color_s
19
+ t = self.to_s
20
+ if warn?
21
+ t.yellow
22
+ elsif fatal?
23
+ t.white.red_bg
24
+ elsif error?
25
+ t.red
26
+ else
27
+ t
28
+ end
29
+ end
30
+
31
+ def error?
32
+ level == :error
33
+ end
34
+
35
+ def warn?
36
+ level == :warn
37
+ end
38
+
39
+ def fatal?
40
+ level == :fatal
41
+ end
42
+
43
+ def info?
44
+ level == :info
45
+ end
46
+
47
+ end
48
+
49
+ end
data/lib/node.rb ADDED
@@ -0,0 +1,28 @@
1
+ require_relative 'context'
2
+
3
+ module XRay
4
+
5
+ class Node
6
+
7
+ attr_accessor :text, :position
8
+
9
+ def initialize(text = '', position = nil)
10
+
11
+ if text.is_a? Node
12
+ @text, @position = text.text, text.position
13
+ else
14
+ @text, @position = (text || '').strip, position
15
+ end
16
+ end
17
+
18
+ def =~(other)
19
+ text =~ other
20
+ end
21
+
22
+ def to_s
23
+ text
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,13 @@
1
+ module XRay
2
+
3
+ class ParseError < RuntimeError
4
+ attr_reader :position
5
+
6
+ def initialize(msg = nil, position = nil)
7
+ super msg
8
+ @position = position
9
+ end
10
+
11
+ end
12
+
13
+ end