ruby--ruby/test/racc/assets/nasl.y

627 lines
17 KiB
Plaintext

################################################################################
# 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 constructor 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 ----