nasl 0.0.1

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 (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