nasl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.gitignore +9 -0
  2. data/Gemfile +4 -0
  3. data/Rakefile +8 -0
  4. data/bin/nasl-parse +33 -0
  5. data/lib/nasl/cli.rb +94 -0
  6. data/lib/nasl/command.rb +96 -0
  7. data/lib/nasl/commands/benchmark.rb +55 -0
  8. data/lib/nasl/commands/parse.rb +55 -0
  9. data/lib/nasl/commands/test.rb +37 -0
  10. data/lib/nasl/commands/tokenize.rb +46 -0
  11. data/lib/nasl/commands/xml.rb +41 -0
  12. data/lib/nasl/context.rb +102 -0
  13. data/lib/nasl/grammar.racc +513 -0
  14. data/lib/nasl/grammar.tab.rb +1650 -0
  15. data/lib/nasl/parser/argument.rb +50 -0
  16. data/lib/nasl/parser/assigment.rb +45 -0
  17. data/lib/nasl/parser/block.rb +41 -0
  18. data/lib/nasl/parser/break.rb +32 -0
  19. data/lib/nasl/parser/call.rb +48 -0
  20. data/lib/nasl/parser/continue.rb +32 -0
  21. data/lib/nasl/parser/decrement.rb +48 -0
  22. data/lib/nasl/parser/empty.rb +32 -0
  23. data/lib/nasl/parser/export.rb +41 -0
  24. data/lib/nasl/parser/expression.rb +56 -0
  25. data/lib/nasl/parser/for.rb +47 -0
  26. data/lib/nasl/parser/foreach.rb +45 -0
  27. data/lib/nasl/parser/function.rb +45 -0
  28. data/lib/nasl/parser/global.rb +41 -0
  29. data/lib/nasl/parser/identifier.rb +43 -0
  30. data/lib/nasl/parser/if.rb +45 -0
  31. data/lib/nasl/parser/import.rb +41 -0
  32. data/lib/nasl/parser/include.rb +41 -0
  33. data/lib/nasl/parser/increment.rb +48 -0
  34. data/lib/nasl/parser/integer.rb +70 -0
  35. data/lib/nasl/parser/ip.rb +43 -0
  36. data/lib/nasl/parser/local.rb +41 -0
  37. data/lib/nasl/parser/lvalue.rb +43 -0
  38. data/lib/nasl/parser/node.rb +73 -0
  39. data/lib/nasl/parser/repeat.rb +43 -0
  40. data/lib/nasl/parser/repetition.rb +43 -0
  41. data/lib/nasl/parser/return.rb +41 -0
  42. data/lib/nasl/parser/string.rb +48 -0
  43. data/lib/nasl/parser/tree.rb +59 -0
  44. data/lib/nasl/parser/undefined.rb +35 -0
  45. data/lib/nasl/parser/while.rb +43 -0
  46. data/lib/nasl/parser.rb +45 -0
  47. data/lib/nasl/test.rb +98 -0
  48. data/lib/nasl/token.rb +69 -0
  49. data/lib/nasl/tokenizer.rb +327 -0
  50. data/lib/nasl/version.rb +3 -0
  51. data/lib/nasl.rb +52 -0
  52. data/nasl.gemspec +26 -0
  53. data/test/test_helper.rb +6 -0
  54. data/test/unit/parser/test_assignment.rb +111 -0
  55. data/test/unit/parser/test_blank.rb +44 -0
  56. data/test/unit/parser/test_block.rb +35 -0
  57. data/test/unit/parser/test_constant.rb +65 -0
  58. data/test/unit/parser/test_empty.rb +36 -0
  59. data/test/unit/parser/test_expressions.rb +57 -0
  60. data/test/unit/parser/test_function.rb +82 -0
  61. data/test/unit/parser/test_if.rb +85 -0
  62. data/test/unit/parser/test_include.rb +37 -0
  63. data/test/unit/parser/test_incr_decr.rb +51 -0
  64. data/test/unit/parser/test_ip.rb +33 -0
  65. data/test/unit/parser/test_return.rb +51 -0
  66. data/test/unit/parser/test_string.rb +46 -0
  67. data/test/unit/parser/test_whitespace.rb +56 -0
  68. data/test/unit/test_context.rb +240 -0
  69. data/test/unit/tokenizer/test_empty.rb +53 -0
  70. data/test/unit/tokenizer/test_integer.rb +68 -0
  71. data/test/unit/tokenizer/test_string.rb +94 -0
  72. metadata +161 -0
@@ -0,0 +1,59 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'builder'
28
+
29
+ module Nasl
30
+ class Tree < Array
31
+ def all(cls)
32
+ (@all[Nasl.const_get(cls).to_s] ||= [])
33
+ end
34
+
35
+ def register(node)
36
+ (@all[node.class.name] ||= []) << node
37
+ @parent.register(node) unless @parent.nil?
38
+ end
39
+
40
+ def initialize(parent=nil)
41
+ @parent = parent
42
+ @all = {}
43
+ end
44
+
45
+ def to_s
46
+ text = ''
47
+
48
+ xml = Builder::XmlMarkup.new(:target=>text, :indent=>2)
49
+
50
+ if empty?
51
+ xml.tree
52
+ else
53
+ xml.tree { self.map { |node| node.to_xml(xml) } }
54
+ end
55
+
56
+ text
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,35 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'nasl/parser/node'
28
+
29
+ module Nasl
30
+ class Undefined < Node
31
+ def to_xml(xml)
32
+ xml.null
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,43 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'nasl/parser/node'
28
+
29
+ module Nasl
30
+ class While < Node
31
+ attr_reader :body, :cond
32
+
33
+ def initialize(tree, *tokens)
34
+ super
35
+
36
+ @cond = @tokens[2]
37
+ @body = @tokens[4]
38
+
39
+ @attributes << :cond
40
+ @attributes << :body
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,45 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'racc/parser'
28
+ require 'nasl/grammar.tab'
29
+ require 'nasl/parser/tree'
30
+
31
+ module Nasl
32
+ class ParseException < Exception
33
+ end
34
+
35
+ class Parser
36
+ def initialize
37
+ @grammar = Grammar.new
38
+ @env = Tree.new
39
+ end
40
+
41
+ def parse(code, path="(unknown)")
42
+ @grammar.parse(@env, code, path)
43
+ end
44
+ end
45
+ end
data/lib/nasl/test.rb ADDED
@@ -0,0 +1,98 @@
1
+ ################################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ require 'nasl/parser'
28
+ require 'test/unit'
29
+
30
+ module Nasl
31
+ module Test
32
+ def self.initialize!(args)
33
+ # Run all tests by default.
34
+ args = ['unit/*', 'unit/*/*'] if args.empty?
35
+
36
+ # Run each test or category of tests specified on the command line.
37
+ args.each do |test|
38
+ Dir.glob(Nasl.test + (test + '.rb')).each { |f| load(f) }
39
+ end
40
+ end
41
+
42
+ def flatten(tree)
43
+ tree.chomp.split(/\n/).map(&:strip).join
44
+ end
45
+
46
+ def parse(code)
47
+ begin
48
+ tree = Nasl::Parser.new.parse(code)
49
+ msg = ''
50
+ rescue Racc::ParseError => e
51
+ tree = nil
52
+ msg = e
53
+ end
54
+
55
+ return tree, msg
56
+ end
57
+
58
+ def tokenize(code)
59
+ Nasl::Tokenizer.new(code, "(test)")
60
+ end
61
+
62
+ def context(code)
63
+ Nasl::Context.new(code, "(test)")
64
+ end
65
+
66
+ def fail(code)
67
+ tree, msg = parse(code)
68
+
69
+ assert_nil(tree, msg)
70
+ end
71
+
72
+ def fail_parse(code)
73
+ assert_raise(ParseException) { Nasl::Parser.new.parse(code) }
74
+ end
75
+
76
+ def fail_token(code)
77
+ assert_raise(TokenException) { Nasl::Parser.new.parse(code) }
78
+ end
79
+
80
+ def pass(code)
81
+ tree, msg = parse(code)
82
+
83
+ assert_not_nil(tree, msg)
84
+ end
85
+
86
+ def diff(code, kg_tree)
87
+ tree, msg = parse(code)
88
+ assert_not_nil(tree, msg)
89
+ assert_not_equal(flatten(kg_tree), flatten(tree.to_s)) if !tree.nil?
90
+ end
91
+
92
+ def same(code, kg_tree)
93
+ tree, msg = parse(code)
94
+ assert_not_nil(tree, msg)
95
+ assert_equal(flatten(kg_tree), flatten(tree.to_s)) if !tree.nil?
96
+ end
97
+ end
98
+ end
data/lib/nasl/token.rb ADDED
@@ -0,0 +1,69 @@
1
+ ###############################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Nasl
28
+ class Token
29
+ attr_reader :body, :name, :region, :type
30
+
31
+ def initialize(type, body, region, ctx)
32
+ @type = type
33
+ @body = body
34
+ @region = region
35
+ @ctx = ctx
36
+ end
37
+
38
+ def context(*args)
39
+ @ctx.context(@region, *args)
40
+ end
41
+
42
+ def name
43
+ case @type
44
+ when *[:BREAK, :CONTINUE, :ELSE, :EXPORT, :FOR, :FOREACH, :FUNCTION,
45
+ :GLOBAL, :IF, :IMPORT, :INCLUDE, :LOCAL, :REPEAT, :RETURN, :UNTIL,
46
+ :REP, :WHILE]
47
+ "a keyword"
48
+ when :UNDEF
49
+ "an undefined constant"
50
+ when *[:FALSE, :TRUE]
51
+ "a boolean constant"
52
+ when :IDENT
53
+ "an identifier"
54
+ when *[:DATA, :STRING]
55
+ "a string"
56
+ when *[:INT_DEC, :INT_HEX, :INT_OCT]
57
+ "an integer"
58
+ when :EOF
59
+ "the end of the file"
60
+ else
61
+ "an operator"
62
+ end
63
+ end
64
+
65
+ def to_s
66
+ @body
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,327 @@
1
+ ###############################################################################
2
+ # Copyright (c) 2011, Mak Kolybabi
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice, this
9
+ # list of conditions and the following disclaimer.
10
+ #
11
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
+ ################################################################################
26
+
27
+ module Nasl
28
+ class TokenException < Exception
29
+ end
30
+
31
+ class Tokenizer
32
+ @@initialized = false
33
+
34
+ @@keywords = {
35
+ 'break' => :BREAK,
36
+ 'continue' => :CONTINUE,
37
+ 'else' => :ELSE,
38
+ 'export' => :EXPORT,
39
+ 'for' => :FOR,
40
+ 'foreach' => :FOREACH,
41
+ 'function' => :FUNCTION,
42
+ 'global_var' => :GLOBAL,
43
+ 'if' => :IF,
44
+ 'import' => :IMPORT,
45
+ 'include' => :INCLUDE,
46
+ 'local_var' => :LOCAL,
47
+ 'repeat' => :REPEAT,
48
+ 'return' => :RETURN,
49
+ 'until' => :UNTIL,
50
+ 'x' => :REP,
51
+ 'while' => :WHILE,
52
+
53
+ 'FALSE' => :FALSE,
54
+ 'NULL' => :UNDEF,
55
+ 'TRUE' => :TRUE
56
+ }
57
+
58
+ @@operators = [
59
+ ["><", :SUBSTR_EQ],
60
+ [">!<", :SUBSTR_NE],
61
+
62
+ ["=~", :REGEX_EQ],
63
+ ["!~", :REGEX_NE],
64
+
65
+ ["==", :CMP_EQ],
66
+ ["!=", :CMP_NE],
67
+ ["<=", :CMP_LE],
68
+ [">=", :CMP_GE],
69
+
70
+ ["=", :ASS_EQ],
71
+ ["+=", :ADD_EQ],
72
+ ["-=", :SUB_EQ],
73
+ ["*=", :MUL_EQ],
74
+ ["/=", :DIV_EQ],
75
+ ["%=", :MOD_EQ],
76
+ [">>=", :SRL_EQ],
77
+ [">>>=", :SRA_EQ],
78
+ ["<<=", :SLL_EQ],
79
+
80
+ ["||", :OR],
81
+ ["&&", :AND],
82
+ ["!", :NOT],
83
+
84
+ ["|", :BIT_OR],
85
+ ["^", :BIT_XOR],
86
+ ["&", :BIT_AND],
87
+ [">>>", :BIT_SRA],
88
+ [">>", :BIT_SRL],
89
+ ["<<", :BIT_SLL],
90
+
91
+ ["<", :CMP_LT],
92
+ [">", :CMP_GT],
93
+
94
+ ["++", :INCR],
95
+ ["--", :DECR],
96
+
97
+ ["**", :EXP],
98
+
99
+ ["+", :ADD],
100
+ ["-", :SUB],
101
+ ["*", :MUL],
102
+ ["/", :DIV],
103
+ ["%", :MOD],
104
+
105
+ ["~", :BIT_NOT],
106
+
107
+ [".", :PERIOD],
108
+ [",", :COMMA],
109
+ [":", :COLON],
110
+ [";", :SEMICOLON],
111
+ ["(", :LPAREN],
112
+ [")", :RPAREN],
113
+ ["[", :LBRACK],
114
+ ["]", :RBRACK],
115
+ ["{", :LBRACE],
116
+ ["}", :RBRACE]
117
+ ]
118
+
119
+ def initialize!
120
+ return if @@initialized
121
+
122
+ # Convert the operators into a regex-compatible form.
123
+ @@operators = @@operators.map do |op, type|
124
+ [Regexp.new("^#{Regexp.escape(op)}"), op, type]
125
+ end
126
+
127
+ @@initialized = true
128
+ end
129
+
130
+ def initialize(code, path)
131
+ @code = code
132
+
133
+ # Perform one-time initialization of tokenizer data structures.
134
+ initialize!
135
+
136
+ # Create a context object that will be shared amongst all tokens for this
137
+ # code.
138
+ @ctx = Context.new(@code, path)
139
+
140
+ reset
141
+ end
142
+
143
+ def consume(num=1)
144
+ # Update the index of the character we're currently looking at.
145
+ @point += num
146
+
147
+ # Update the flag that indicates whether we've reached the file's end.
148
+ @eof = (@point >= @code.length)
149
+
150
+ # Update the the character we're examining currently.
151
+ @char = @code[@point]
152
+
153
+ # Extract the remainder of the line.
154
+ @line = @code[@point..@ctx.eol(@point)]
155
+ end
156
+
157
+ def reset
158
+ # Set tokenizer to initial state, ready to tokenize the code from the
159
+ # start.
160
+ @point = 0
161
+ consume(0)
162
+ skip
163
+
164
+ # Return tokenizer to allow method chaining.
165
+ self
166
+ end
167
+
168
+ def skip
169
+ while true do
170
+ whitespace = @line[/^(\s+|\s*#.*$)/]
171
+ return if whitespace.nil?
172
+ consume(whitespace.length)
173
+ end
174
+ end
175
+
176
+ def die(msg)
177
+ # We want the default context for token errors to be all lines that
178
+ # contain the region.
179
+ region = @ctx.bol(@mark)..@ctx.eol(@point)
180
+ bt = @ctx.context(@mark..@point + 1, region)
181
+
182
+ # Raise an exception with the context as our backtrace.
183
+ raise TokenException, msg, bt
184
+ end
185
+
186
+ def get_identifier
187
+ # Identifiers are composed of letters, digits, and underscores.
188
+ ident = @line[/^[_a-z][_a-z0-9]*/i]
189
+ consume(ident.length)
190
+
191
+ # Assume that we've got an identifier until proven otherwise.
192
+ type = :IDENT
193
+
194
+ # Identifiers may be prefixed with keywords. One example of a valid
195
+ # identifier is "break_". To ensure that we catch these cases, we
196
+ # initially parse all keywords as identifiers and then convert them as
197
+ # needed.
198
+ type = @@keywords[ident] if @@keywords.has_key? ident
199
+
200
+ return [type, ident]
201
+ end
202
+
203
+ def get_integer
204
+ # Try and parse the integer in any of three bases.
205
+ if @line =~ /^0x/i
206
+ # Hex integers start with "0x".
207
+ type = :INT_HEX
208
+ name = "hex"
209
+ regex1 = /^0x\w+/i
210
+ regex2 = /^0x[a-f0-9]+/i
211
+ elsif @line =~ /^0\w+/
212
+ # Octal integers start with "0".
213
+ type = :INT_OCT
214
+ name = "octal"
215
+ regex1 = /^0\w+/
216
+ regex2 = /^0[0-7]+/
217
+ else
218
+ # Anything else is a decimal integer.
219
+ type = :INT_DEC
220
+ name = "decimal"
221
+ regex1 = /^\w*/
222
+ regex2 = /^[0-9]+/
223
+ end
224
+
225
+ # First match with an overly permissive regex, and then match with the
226
+ # proper regex. If the permissive and restrictive versions don't match,
227
+ # then there's an error in the input.
228
+ permissive = @line[regex1]
229
+ restrictive = @line[regex2]
230
+
231
+ if permissive.nil? || restrictive.nil? || permissive != restrictive
232
+ # NASL interprets integers with a leading zero as octal if the only
233
+ # contain octal digits, and considers the integers as decimal otherwise.
234
+ type = :INT_DEC
235
+ regex2 = /^[0-9]+/
236
+ restrictive = @line[regex2]
237
+ end
238
+
239
+ if permissive.nil? || restrictive.nil? || permissive != restrictive
240
+ die("Invalid #{name} literal")
241
+ end
242
+
243
+ # If there was no problem, we use the restrictive version as the body of
244
+ # our integer.
245
+ integer = restrictive
246
+
247
+ consume(integer.length)
248
+
249
+ return [type, integer]
250
+ end
251
+
252
+ def get_string
253
+ unparsed = @code[@point..-1]
254
+
255
+ if @char == "'"
256
+ type = :DATA
257
+
258
+ # Single-quoted strings cannot have single-quotes stuffed inside them.
259
+ contents = unparsed[/\A'(\\.|[^'\\])*'/m]
260
+ die("Unterminated single-quoted string") if contents.nil?
261
+ else
262
+ type = :STRING
263
+
264
+ # Double-quoted strings cannot have double quotes stuffed inside them.
265
+ contents = unparsed[/\A"[^"]*"/m]
266
+ die("Unterminated double-quoted string") if contents.nil?
267
+ end
268
+
269
+ # Move the point forward over the string.
270
+ consume(contents.length)
271
+
272
+ # Remove the bounding quotes.
273
+ contents = contents[1..-2]
274
+
275
+ return [type, contents]
276
+ end
277
+
278
+ def get_operator
279
+ # These are all of the operators defined in NASL. Their order is vitally
280
+ # important.
281
+ @@operators.each do |regex, op, type|
282
+ next if @line !~ regex
283
+ consume(op.length)
284
+ return [type, op]
285
+ end
286
+
287
+ return nil
288
+ end
289
+
290
+ def get_token
291
+ # Make sure we're not at the end of the file.
292
+ return [false, Token.new(:EOF, "$", @point...@point, @ctx)] if @eof
293
+
294
+ # Save our starting point, which to use Emacs terminology is called the
295
+ # 'mark'.
296
+ @mark = @point
297
+
298
+ # Try to parse token at the point.
299
+ token = if @char =~ /[_a-z]/i
300
+ get_identifier
301
+ elsif @char =~ /['"]/
302
+ get_string
303
+ elsif @char =~ /[0-9]/
304
+ get_integer
305
+ else
306
+ get_operator
307
+ end
308
+
309
+ # Everything in the language is enumerated by the above functions, so if
310
+ # we get here without a token parsed, the input file is invalid.
311
+ die("Invalid character ('#@char')") if token.nil?
312
+ skip
313
+
314
+ return [token.first, Token.new(*token, @mark...@point, @ctx)]
315
+ end
316
+
317
+ def get_tokens
318
+ tokens = []
319
+
320
+ until @eof
321
+ tokens << get_token
322
+ end
323
+
324
+ return tokens
325
+ end
326
+ end
327
+ end
@@ -0,0 +1,3 @@
1
+ module Nasl
2
+ VERSION = '0.0.1'
3
+ end