diff options
Diffstat (limited to 'test/racc/assets/nasl.y')
-rw-r--r-- | test/racc/assets/nasl.y | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/test/racc/assets/nasl.y b/test/racc/assets/nasl.y new file mode 100644 index 0000000000..e68dd699f8 --- /dev/null +++ b/test/racc/assets/nasl.y @@ -0,0 +1,626 @@ +################################################################################ +# Copyright (c) 2011-2014, Tenable Network Security +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +class Nasl::Grammar + +preclow + right ASS_EQ ADD_EQ SUB_EQ MUL_EQ DIV_EQ MOD_EQ SLL_EQ SRA_EQ SRL_EQ + left OR + left AND + left CMP_LT CMP_GT CMP_EQ CMP_NE CMP_GE CMP_LE SUBSTR_EQ SUBSTR_NE REGEX_EQ REGEX_NE + left BIT_OR + left BIT_XOR + left AMPERSAND + left BIT_SRA BIT_SRL BIT_SLL + left ADD SUB + left MUL DIV MOD + right NOT + right UMINUS BIT_NOT + right EXP + right INCR DECR +prechigh + +# Tell the parser generator that we don't wish to use the result variable in the +# action section of rules. Instead, the result of the rule will be the value of +# evaluating the action block. +options no_result_var + +# Tell the parser generator that we expect one shift/reduce conflict due to the +# well-known dangling else problem. We could make the grammar solve this +# problem, but this is how the NASL YACC file solves it, so we'll follow suit. +expect 1 + +rule + ############################################################################## + # Aggregate Statements + ############################################################################## + + start : roots + { val[0] } + | /* Blank */ + { [] } + ; + + roots : root roots + { [val[0]] + val[1] } + | root + { [val[0]] } + ; + + root : COMMENT export + { c(*val) } + | export + { val[0] } + | COMMENT function + { c(*val) } + | function + { val[0] } + | statement + { val[0] } + ; + + statement : simple + { val[0] } + | compound + { val[0] } + ; + + ############################################################################## + # Root Statements + ############################################################################## + + export : EXPORT function + { n(:Export, *val) } + ; + + function : FUNCTION ident LPAREN params RPAREN block + { n(:Function, *val) } + | FUNCTION ident LPAREN RPAREN block + { n(:Function, *val) } + ; + + simple : assign + { val[0] } + | break + { val[0] } + | call + { val[0] } + | continue + { val[0] } + | decr + { val[0] } + | empty + { val[0] } + | COMMENT global + { c(*val) } + | global + { val[0] } + | import + { val[0] } + | include + { val[0] } + | incr + { val[0] } + | local + { val[0] } + | rep + { val[0] } + | return + { val[0] } + ; + + compound : block + { val[0] } + | for + { val[0] } + | foreach + { val[0] } + | if + { val[0] } + | repeat + { val[0] } + | while + { val[0] } + ; + + ############################################################################## + # Simple Statements + ############################################################################## + + assign : assign_exp SEMICOLON + { val[0] } + ; + + break : BREAK SEMICOLON + { n(:Break, *val) } + ; + + call : call_exp SEMICOLON + { val[0] } + ; + + continue : CONTINUE SEMICOLON + { n(:Continue, *val) } + ; + + decr : decr_exp SEMICOLON + { val[0] } + ; + + empty : SEMICOLON + { n(:Empty, *val) } + ; + + global : GLOBAL var_decls SEMICOLON + { n(:Global, *val) } + ; + + incr : incr_exp SEMICOLON + { val[0] } + ; + + import : IMPORT LPAREN string RPAREN SEMICOLON + { n(:Import, *val) } + ; + + include : INCLUDE LPAREN string RPAREN SEMICOLON + { n(:Include, *val) } + ; + + local : LOCAL var_decls SEMICOLON + { n(:Local, *val) } + ; + + rep : call_exp REP expr SEMICOLON + { n(:Repetition, *val[0..-1]) } + ; + + return : RETURN expr SEMICOLON + { n(:Return, *val) } + | RETURN ref SEMICOLON + { n(:Return, *val) } + | RETURN SEMICOLON + { n(:Return, *val) } + ; + + ############################################################################## + # Compound Statements + ############################################################################## + + block : LBRACE statements RBRACE + { n(:Block, *val) } + | LBRACE RBRACE + { n(:Block, *val) } + ; + + for : FOR LPAREN field SEMICOLON expr SEMICOLON field RPAREN statement + { n(:For, *val) } + ; + + foreach : FOREACH ident LPAREN expr RPAREN statement + { n(:Foreach, val[0], val[1], val[3], val[5]) } + | FOREACH LPAREN ident IN expr RPAREN statement + { n(:Foreach, val[0], val[2], val[4], val[6]) } + ; + + if : IF LPAREN expr RPAREN statement + { n(:If, *val) } + | IF LPAREN expr RPAREN statement ELSE statement + { n(:If, *val) } + ; + + repeat : REPEAT statement UNTIL expr SEMICOLON + { n(:Repeat, *val) } + ; + + while : WHILE LPAREN expr RPAREN statement + { n(:While, *val) } + ; + + ############################################################################## + # Expressions + ############################################################################## + + assign_exp : lval ASS_EQ expr + { n(:Assignment, *val) } + | lval ASS_EQ ref + { n(:Assignment, *val) } + | lval ADD_EQ expr + { n(:Assignment, *val) } + | lval SUB_EQ expr + { n(:Assignment, *val) } + | lval MUL_EQ expr + { n(:Assignment, *val) } + | lval DIV_EQ expr + { n(:Assignment, *val) } + | lval MOD_EQ expr + { n(:Assignment, *val) } + | lval SRL_EQ expr + { n(:Assignment, *val) } + | lval SRA_EQ expr + { n(:Assignment, *val) } + | lval SLL_EQ expr + { n(:Assignment, *val) } + ; + + call_exp : lval LPAREN args RPAREN + { n(:Call, *val) } + | lval LPAREN RPAREN + { n(:Call, *val) } + ; + + decr_exp : DECR lval + { n(:Decrement, val[0]) } + | lval DECR + { n(:Decrement, val[0]) } + ; + + incr_exp : INCR lval + { n(:Increment, val[0]) } + | lval INCR + { n(:Increment, val[0]) } + ; + + expr : LPAREN expr RPAREN + { n(:Expression, *val) } + | expr AND expr + { n(:Expression, *val) } + | NOT expr + { n(:Expression, *val) } + | expr OR expr + { n(:Expression, *val) } + | expr ADD expr + { n(:Expression, *val) } + | expr SUB expr + { n(:Expression, *val) } + | SUB expr =UMINUS + { n(:Expression, *val) } + | BIT_NOT expr + { n(:Expression, *val) } + | expr MUL expr + { n(:Expression, *val) } + | expr EXP expr + { n(:Expression, *val) } + | expr DIV expr + { n(:Expression, *val) } + | expr MOD expr + { n(:Expression, *val) } + | expr AMPERSAND expr + { n(:Expression, *val) } + | expr BIT_XOR expr + { n(:Expression, *val) } + | expr BIT_OR expr + { n(:Expression, *val) } + | expr BIT_SRA expr + { n(:Expression, *val) } + | expr BIT_SRL expr + { n(:Expression, *val) } + | expr BIT_SLL expr + { n(:Expression, *val) } + | incr_exp + { val[0] } + | decr_exp + { val[0] } + | expr SUBSTR_EQ expr + { n(:Expression, *val) } + | expr SUBSTR_NE expr + { n(:Expression, *val) } + | expr REGEX_EQ expr + { n(:Expression, *val) } + | expr REGEX_NE expr + { n(:Expression, *val) } + | expr CMP_LT expr + { n(:Expression, *val) } + | expr CMP_GT expr + { n(:Expression, *val) } + | expr CMP_EQ expr + { n(:Expression, *val) } + | expr CMP_NE expr + { n(:Expression, *val) } + | expr CMP_GE expr + { n(:Expression, *val) } + | expr CMP_LE expr + { n(:Expression, *val) } + | assign_exp + { val[0] } + | string + { val[0] } + | call_exp + { val[0] } + | lval + { val[0] } + | ip + { val[0] } + | int + { val[0] } + | undef + { val[0] } + | list_expr + { val[0] } + | array_expr + { val[0] } + ; + + ############################################################################## + # Named Components + ############################################################################## + + arg : ident COLON expr + { n(:Argument, *val) } + | ident COLON ref + { n(:Argument, *val) } + | expr + { n(:Argument, *val) } + | ref + { n(:Argument, *val) } + ; + + kv_pair : string COLON expr + { n(:KeyValuePair, *val) } + | int COLON expr + { n(:KeyValuePair, *val) } + | ident COLON expr + { n(:KeyValuePair, *val) } + | string COLON ref + { n(:KeyValuePair, *val) } + | int COLON ref + { n(:KeyValuePair, *val) } + | ident COLON ref + { n(:KeyValuePair, *val) } + ; + + kv_pairs : kv_pair COMMA kv_pairs + { [val[0]] + val[2] } + | kv_pair COMMA + { [val[0]] } + | kv_pair + { [val[0]] } + ; + + lval : ident indexes + { n(:Lvalue, *val) } + | ident + { n(:Lvalue, *val) } + ; + + ref : AT_SIGN ident + { n(:Reference, val[1]) } + ; + + ############################################################################## + # Anonymous Components + ############################################################################## + + args : arg COMMA args + { [val[0]] + val[2] } + | arg + { [val[0]] } + ; + + array_expr : LBRACE kv_pairs RBRACE + { n(:Array, *val) } + | LBRACE RBRACE + { n(:Array, *val) } + ; + + field : assign_exp + { val[0] } + | call_exp + { val[0] } + | decr_exp + { val[0] } + | incr_exp + { val[0] } + | /* Blank */ + { nil } + ; + + index : LBRACK expr RBRACK + { val[1] } + | PERIOD ident + { val[1] } + ; + + indexes : index indexes + { [val[0]] + val[1] } + | index + { [val[0]] } + ; + + list_elem : expr + { val[0] } + | ref + { val[0] } + ; + + list_elems : list_elem COMMA list_elems + { [val[0]] + val[2] } + | list_elem + { [val[0]] } + ; + + list_expr : LBRACK list_elems RBRACK + { n(:List, *val) } + | LBRACK RBRACK + { n(:List, *val) } + ; + + param : AMPERSAND ident + { n(:Parameter, val[1], 'reference') } + | ident + { n(:Parameter, val[0], 'value') } + ; + + params : param COMMA params + { [val[0]] + val[2] } + | param + { [val[0]] } + ; + + statements : statement statements + { [val[0]] + val[1] } + | statement + { [val[0]] } + ; + + var_decl : ident ASS_EQ expr + { n(:Assignment, *val) } + | ident ASS_EQ ref + { n(:Assignment, *val) } + | ident + { val[0] } + ; + + var_decls : var_decl COMMA var_decls + { [val[0]] + val[2] } + | var_decl + { [val[0]] } + ; + + ############################################################################## + # Literals + ############################################################################## + + ident : IDENT + { n(:Identifier, *val) } + | REP + { n(:Identifier, *val) } + | IN + { n(:Identifier, *val) } + ; + + int : INT_DEC + { n(:Integer, *val) } + | INT_HEX + { n(:Integer, *val) } + | INT_OCT + { n(:Integer, *val) } + | FALSE + { n(:Integer, *val) } + | TRUE + { n(:Integer, *val) } + ; + + ip : int PERIOD int PERIOD int PERIOD int + { n(:Ip, *val) } + + string : DATA + { n(:String, *val) } + | STRING + { n(:String, *val) } + ; + + undef : UNDEF + { n(:Undefined, *val) } + ; +end + +---- header ---- + +require 'nasl/parser/tree' + +require 'nasl/parser/argument' +require 'nasl/parser/array' +require 'nasl/parser/assigment' +require 'nasl/parser/block' +require 'nasl/parser/break' +require 'nasl/parser/call' +require 'nasl/parser/comment' +require 'nasl/parser/continue' +require 'nasl/parser/decrement' +require 'nasl/parser/empty' +require 'nasl/parser/export' +require 'nasl/parser/expression' +require 'nasl/parser/for' +require 'nasl/parser/foreach' +require 'nasl/parser/function' +require 'nasl/parser/global' +require 'nasl/parser/identifier' +require 'nasl/parser/if' +require 'nasl/parser/import' +require 'nasl/parser/include' +require 'nasl/parser/increment' +require 'nasl/parser/integer' +require 'nasl/parser/ip' +require 'nasl/parser/key_value_pair' +require 'nasl/parser/list' +require 'nasl/parser/local' +require 'nasl/parser/lvalue' +require 'nasl/parser/parameter' +require 'nasl/parser/reference' +require 'nasl/parser/repeat' +require 'nasl/parser/repetition' +require 'nasl/parser/return' +require 'nasl/parser/string' +require 'nasl/parser/undefined' +require 'nasl/parser/while' + +---- inner ---- + +def n(cls, *args) + begin + Nasl.const_get(cls).new(@tree, *args) + rescue + puts "An exception occurred during the creation of a #{cls} instance." + puts + puts "The arguments passed to the constructer were:" + puts args + puts + puts @tok.last.context + puts + raise + end +end + +def c(*args) + n(:Comment, *args) + args[1] +end + +def on_error(type, value, stack) + raise ParseException, "The language's grammar does not permit #{value.name} to appear here", value.context +end + +def next_token + @tok = @tkz.get_token + + if @first && @tok.first == :COMMENT + n(:Comment, @tok.last) + @tok = @tkz.get_token + end + @first = false + + return @tok +end + +def parse(env, code, path) + @first = true + @tree = Tree.new(env) + @tkz = Tokenizer.new(code, path) + @tree.concat(do_parse) +end + +---- footer ---- |