Commit 0ebeef6e authored by dbarbera's avatar dbarbera
Browse files

Added unary expressions nodes

parent 0d5c683e
......@@ -723,8 +723,7 @@ def _primary_variable(prim):
''' Single variable reference '''
sep = u'l_' if find_var(prim.value[0]) else u''
string = u'{sep}{name}'.format(sep=sep, name=prim.value[0])
ada_string = unary(prim, string)
ada_string = u'{sep}{name}'.format(sep=sep, name=prim.value[0])
if prim.exprType.__name__ == 'for_range':
# Ada iterator in FOR loops is an Integer - we must cast to 64 bits
......@@ -896,7 +895,6 @@ def _prim_path(primary_id):
ada_string += ', '.join(list_of_params)
ada_string += ')'
sep = '.'
ada_string = unary(primary_id, ada_string)
return stmts, ada_string, local_decl
......@@ -924,7 +922,6 @@ def _basic_operators(expr):
code.extend(right_stmts)
local_decl.extend(left_local)
local_decl.extend(right_local)
ada_string = unary(expr, ada_string)
return code, ada_string, local_decl
......@@ -964,7 +961,18 @@ def _bitwise_operators(expr):
code.extend(right_stmts)
local_decl.extend(left_local)
local_decl.extend(right_local)
ada_string = unary(expr, ada_string)
return code, ada_string, local_decl
@expression.register(ogAST.ExprNot)
@expression.register(ogAST.ExprNeg)
def _unary_operator(expr):
''' Generate the code for an unary expression '''
code, local_decl = [], []
expr_stmts, expr_str, expr_local = expression(expr.expr)
ada_string = u'({op} {expr})'.format(op=expr.operand, expr=expr_str)
code.extend(expr_stmts)
local_decl.extend(expr_local)
return code, ada_string, local_decl
......@@ -1090,8 +1098,11 @@ def _choice_determinant(primary):
@expression.register(ogAST.PrimReal)
def _integer(primary):
''' Generate code for a raw numerical value '''
ada_string = primary.value[0]
ada_string = unary(primary, ada_string)
if float(primary.value[0]) < 0:
# Parentesize negative integers for maintaining the precedence in the generated code
ada_string = '({})'.format(primary.value[0])
else:
ada_string = primary.value[0]
return [], ada_string, []
......@@ -1099,7 +1110,6 @@ def _integer(primary):
def _integer(primary):
''' Generate code for a raw boolean value '''
ada_string = primary.value[0]
ada_string = unary(primary, ada_string)
return [], ada_string, []
......@@ -1514,25 +1524,6 @@ def _inner_procedure(proc):
return code, local_decl
# A few helper functions needed by the Ada backend
def unary(expr, string):
''' Check for NOT or MINUS unary operators and add them to the string '''
op_minus = getattr(expr, 'op_minus', False)
op_not = getattr(expr, 'op_not', False)
try:
float_val = float(string)
except ValueError:
float_val = 1
if op_minus and float_val > 0:
string = u'(-{})'.format(string)
elif float_val <= 0:
string = u'({})'.format(string)
if op_not:
string = u'not {}'.format(string)
return string
def find_basic_type(a_type):
''' Return the ASN.1 basic type of a_type '''
basic_type = a_type
......
......@@ -127,6 +127,14 @@ class ExprRem(Expression):
operand = 'rem'
class ExprNot(Expression):
operand = 'not'
class ExprNeg(Expression):
operand = '-'
class ExprAssign(Expression):
operand = ':='
......@@ -157,16 +165,12 @@ class Primary(Expression):
self.inputString = primary.inputString
self.line = primary.line
self.charPositionInLine = primary.charPositionInLine
self.op_not = primary.op_not
self.op_minus = primary.op_minus
self.value = primary.value
self.exprType = primary.exprType
else:
self.inputString = inputString
self.line = line
self.charPositionInLine = charPositionInLine
self.op_not = False
self.op_minus = False
self.value = None
self.exprType = None
......
......@@ -61,6 +61,8 @@ OPKIND = {lexer.PLUS: ogAST.ExprPlus,
lexer.APPEND: ogAST.ExprAppend,
lexer.IN: ogAST.ExprIn,
lexer.REM: ogAST.ExprRem,
lexer.NOT: ogAST.ExprNot,
lexer.NEG: ogAST.ExprNeg,
lexer.PRIMARY: ogAST.Primary}
# Insert current path in the search list for importing modules
......@@ -454,7 +456,7 @@ def check_and_fix_op_params(op_name, expr_list, context):
def check_range(typeref, type_to_check):
''' Verify the that the Min/Max bounds of two types are compatible
Called to test that assignments are withing allowed range
both types assumed to be basic types
both types assumed to be basic types
'''
try:
if float(type_to_check.Min) < float(typeref.Min) \
......@@ -861,8 +863,28 @@ def find_type(path, context):
return result
def fix_expression_type(expr, context):
''' Check/ensure type consistency in unary expressions '''
if expr.expr.exprType == UNKNOWN_TYPE \
and isinstance(expr.expr, ogAST.PrimPath) \
and len(expr.expr.value) == 1:
try:
exprType = find_variable(expr.expr.value[0], context)
# Differentiate DCL and FPAR variables
use_type = ogAST.PrimVariable
if isinstance(context, ogAST.Procedure):
for each in context.fpar:
if each['name'].lower() == expr.expr.value[0].lower():
use_type = ogAST.PrimFPAR
break
expr.expr = use_type(primary=expr.expr)
expr.expr.exprType = exprType
except AttributeError:
pass
def fix_expression_types(expr, context):
''' Check/ensure type consistency in expressions having two sides '''
''' Check/ensure type consistency in binary expressions '''
if isinstance(expr, ogAST.Primary):
return
......@@ -1249,14 +1271,9 @@ def primary(root, context):
''' Process a primary (-/NOT value) '''
warnings = []
errors = []
op_not, op_minus = False, False
prim = None
for child in root.getChildren():
if child.type == lexer.NOT:
op_not = True
elif child.type == lexer.MINUS:
op_minus = True
elif child.type == lexer.PRIMARY_ID:
if child.type == lexer.PRIMARY_ID:
# Variable reference, indexed values, or ASN.1 value notation
prim, err, warn = primary_value(child, context=context)
errors.extend(err)
......@@ -1292,10 +1309,6 @@ def primary(root, context):
prim.inputString = get_input_string(root)
prim.line = root.getLine()
prim.charPositionInLine = root.getCharPositionInLine()
if op_not:
prim.op_not = True
if op_minus:
prim.op_minus = True
return prim, errors, warnings
......@@ -1325,7 +1338,7 @@ def expression(root, context):
root.children.pop(idx)
break
# Binary expressions
if root.type in (lexer.PLUS,
lexer.ASTERISK,
lexer.DASH,
......@@ -1374,6 +1387,15 @@ def expression(root, context):
format(expr.inputString, str(report)))
expr = new_expr
# Unary expressions
elif root.type in (lexer.NOT, lexer.NEG):
child = root.getChildren()[0]
expr.expr, err_expr, warn_expr = expression(child, context)
errors.extend(err_expr)
warnings.extend(warn_expr)
fix_expression_type(expr, context)
if root.type in (lexer.EQ,
lexer.NEQ,
lexer.GT,
......@@ -1414,7 +1436,6 @@ def expression(root, context):
errors.append('Check that all your numerical data types have '
'a range constraint')
elif root.type in (lexer.OR, lexer.AND, lexer.XOR):
# in the case of bitwise operators, if both sides are arrays,
# then the result is an array too
......@@ -1425,15 +1446,22 @@ def expression(root, context):
else:
expr.exprType = expr.left.exprType
elif root.type in (lexer.PLUS,
lexer.ASTERISK,
lexer.DASH,
lexer.DIV,
lexer.APPEND,
lexer.REM,
lexer.MOD):
elif root.type == lexer.NOT:
basic = find_basic_type(expr.expr.exprType)
if basic.kind == 'BooleanType':
expr.exprType = BOOLEAN
else:
expr.exprType = expr.expr.exprType
elif root.type == lexer.APPEND:
expr.exprType = expr.left.exprType
elif root.type == lexer.NEG:
basic = find_basic_type(expr.expr.exprType)
attrs = {'Min': str(-float(basic.Max)),
'Max': str(-float(basic.Min))}
expr.exprType = type('Neg', (basic,), attrs)
if root.type == lexer.PRIMARY:
expr, err, warn = primary(root, context)
if not expr:
......@@ -1927,15 +1955,15 @@ def text_area_content(root, ta_ast, context):
elif child.type == lexer.SYNONYM_LIST:
err, warn = synonym(child, ta_ast, context)
errors.extend(err)
warnings.extend(warn)
warnings.extend(warn)
elif child.type == lexer.NEWTYPE:
err, warn = newtype(child, ta_ast, context)
errors.extend(err)
warnings.extend(warn)
warnings.extend(warn)
elif child.type == lexer.SYNTYPE:
err, warn = syntype(child, ta_ast, context)
errors.extend(err)
warnings.extend(warn)
warnings.extend(warn)
elif child.type == lexer.PROCEDURE:
proc, err, warn = procedure(child, context=context)
errors.extend(err)
......
/*
/*
OpenGEODE
ANTLR 3.1.3 grammar for the SDL92 langage
Includes the following features from SDL2000+:
......@@ -89,7 +89,7 @@ tokens {
VARIABLES;
SORT;
DCL;
MINUS;
NEG;
GROUND;
TEXTAREA;
TEXTAREA_CONTENT;
......@@ -183,7 +183,7 @@ route
block_definition
: BLOCK block_id end
entity_in_block*
entity_in_block*
ENDBLOCK end
-> ^(BLOCK block_id entity_in_block*);
......@@ -456,7 +456,7 @@ enabling_condition
continuous_signal
: PROVIDED expression end
: PROVIDED expression end
(PRIORITY integer_literal_name=INT end)?
transition
-> ^(PROVIDED expression $integer_literal_name? transition);
......@@ -491,7 +491,7 @@ signal_item
signal_list_id |
timer_id;*/
/* Not considered for the moment
/* Not considered for the moment
(irrelevant in the scope of the generation of code for a single process)
priority_input
: PRIORITY INPUT priority_input_list end transition;
......@@ -576,7 +576,7 @@ procedure_call
procedure_call_body
: procedure_id actual_parameters?
: procedure_id actual_parameters?
-> ^(OUTPUT_BODY procedure_id actual_parameters?);
......@@ -685,7 +685,7 @@ constant
create_request
: CREATE
: CREATE
createbody
actual_parameters?
end
......@@ -712,7 +712,7 @@ outputbody
outputstmt
: signal_id
: signal_id
actual_parameters?;
to_part
......@@ -795,20 +795,30 @@ variable
field_selection
: (('!'|'.') field_name);
expression : operand0 ( IMPLIES^ operand0)* ;
operand0 : operand1 (( (OR^ ELSE?) | XOR^ ) operand1)*;
operand1 : operand2 ( AND^ THEN? operand2)*;
operand2 : operand3
(( EQ^ | NEQ^ | GT^ | GE^ | LT^ | LE^ | IN^ )
operand3)*;
operand3 : operand4 (( PLUS^ | DASH^ | APPEND^ ) operand4)*;
operand4 : operand5
(( ASTERISK^ | DIV^ | MOD^ | REM^ ) operand5)*;
operand5 : primary_qualifier? primary
-> ^(PRIMARY primary_qualifier? primary);
expression
: operand0 ( IMPLIES^ operand0)* ;
operand0
: operand1 (( (OR^ ELSE?) | XOR^ ) operand1)*;
operand1
: operand2 ( AND^ THEN? operand2)*;
operand2
: operand3 (( EQ^ | NEQ^ | GT^ | GE^ | LT^ | LE^ | IN^ ) operand3)*;
operand3
: operand4 (( PLUS^ | DASH^ | APPEND^ ) operand4)*;
// primary below covers all cases including ASN.1 Value Notation
operand4
: operand5 (( ASTERISK^ | DIV^ | MOD^ | REM^ ) operand5)*;
operand5
: primary -> ^(PRIMARY primary)
| NOT^ operand5
| DASH operand5 -> ^(NEG operand5);
// primary below covers all cases including ASN.1 Value Notation
primary
: a=asn1Value primary_params*
-> ^(PRIMARY_ID asn1Value primary_params*)
......@@ -833,7 +843,7 @@ asn1Value
| L_BRACKET
MANTISSA mant=INT COMMA
BASE bas=INT COMMA
EXPONENT exp=INT
EXPONENT exp=INT
R_BRACKET -> ^(FLOAT2 $mant $bas $exp)
| choiceValue
| L_BRACKET
......@@ -859,7 +869,7 @@ informal_text
// hello:5 (CHOICE field value)
choiceValue
choiceValue
: choice=ID ':' expression
-> ^(CHOICE $choice expression);
......@@ -869,12 +879,6 @@ namedValue
: ID expression;
primary_qualifier
: DASH
-> ^(MINUS)
| NOT;
primary_params
: '(' expression_list ')'
-> ^(PARAMS expression_list)
......@@ -882,7 +886,7 @@ primary_params
-> ^(FIELD_NAME literal_id);
/* All cases are covered by the ground primary
/* All cases are covered by the ground primary
above (Except structure primary, but we favour ASN.1 notation)
extended_primary
: synonym |
......@@ -960,7 +964,7 @@ operator_application
: operator_id '('active_expression_list ')';
active_expression_list
active_expression_list
: active_expression (',' expression_list)?;/* |
ground_expression ',' active_expression_list;*/ // Will not work (recursion)
/*
......@@ -990,7 +994,7 @@ conditional_ground_expression
-> ^(IFTHENELSE $ifexpr $thenexpr $elseexpr);
expression_list
expression_list
: expression (',' expression)*
-> expression+;
......@@ -1048,7 +1052,7 @@ cif
: cif_decl symbolname
L_PAREN x=INT COMMA y=INT R_PAREN
COMMA
L_PAREN width=INT COMMA height=INT R_PAREN
L_PAREN width=INT COMMA height=INT R_PAREN
cif_end
-> ^(CIF $x $y $width $height);
......@@ -1060,7 +1064,7 @@ hyperlink
/* OpenGEODE specific: SDL does not allow specifying the name
of signal parameters, but it is needed to generate function signatures
when generating code (in particular in Ada, where the name in the
when generating code (in particular in Ada, where the name in the
body must comply with the one of the source
Extension is using CIF comment so it is invisible to other SDL parsers
(This is valid SDL code - see ITU-T Z106)
......@@ -1273,13 +1277,13 @@ ENDBLOCK : E N D B L O C K;
SIGNALROUTE : S I G N A L R O U T E;
CONNECT : C O N N E C T;
SYNTYPE : S Y N T Y P E;
ENDSYNTYPE : E N D S Y N T Y P E;
ENDSYNTYPE : E N D S Y N T Y P E;
NEWTYPE : N E W T Y P E;
ENDNEWTYPE : E N D N E W T Y P E;
ARRAY : A R R A Y;
ARRAY : A R R A Y;
CONSTANTS : C O N S T A N T S;
STRUCT : S T R U C T;
SYNONYM : S Y N O N Y M;
SYNONYM : S Y N O N Y M;
IMPORT : I M P O R T;
VIEW : V I E W;
ACTIVE : A C T I V E;
......
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-02 08:11:12
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-07 18:45:53
import sys
from antlr3 import *
......@@ -11,12 +11,12 @@ HIDDEN = BaseRecognizer.HIDDEN
# token types
NUMBER_OF_INSTANCES=24
COMMENT2=211
MANTISSA=169
MANTISSA=170
ROUTE=93
MOD=156
GROUND=76
PARAM=83
NOT=172
NOT=158
SEQOF=13
TEXTAREA_CONTENT=78
EOF=-1
......@@ -68,10 +68,10 @@ Y=184
X=200
FI=65
Z=213
MINUS_INFINITY=165
MINUS_INFINITY=166
WS=210
OUT=129
FloatingPointLiteral=166
FloatingPointLiteral=167
NONE=130
INPUT_NONE=27
CONSTANT=44
......@@ -113,11 +113,10 @@ SIGNALROUTE=116
ENDSYNTYPE=101
SORT=73
SET=36
MINUS=75
TEXT=53
SEMI=124
TEXTAREA=77
StringLiteral=162
StringLiteral=163
BLOCK=94
CIF=66
START=122
......@@ -128,12 +127,12 @@ STRING=19
INPUTLIST=69
EXTERNAL=85
LT=142
EXPONENT=171
EXPONENT=172
TRANSITION=25
ENDBLOCK=115
RESET=37
ENDNEWTYPE=103
BitStringLiteral=158
BitStringLiteral=159
SIGNAL_LIST=30
ENDTEXT=22
CONNECTION=92
......@@ -141,7 +140,7 @@ SYSTEM=88
CONNECT=99
L_PAREN=132
PROCEDURE_CALL=34
BASE=170
BASE=171
COMMENT=9
SYNONYM=109
ENDALTERNATIVE=136
......@@ -153,7 +152,7 @@ OCTSTR=18
VIEW=175
EMPTYSTR=14
ENDCHANNEL=112
NULL=163
NULL=164
ANSWER=41
PRIMARY=61
TASK=79
......@@ -165,16 +164,16 @@ PRIORITY=131
SPECIFIC=177
OR=150
COMPOSITE_STATE=98
OctetStringLiteral=159
OctetStringLiteral=160
FIELD=108
USE=89
FROM=113
ENDPROCEDURE=120
FALSE=161
FALSE=162
OUTPUT=50
SYNONYM_LIST=110
APPEND=154
L_BRACKET=167
L_BRACKET=168
PRIMARY_ID=62
DIGITS=21
HYPERLINK=67
......@@ -207,8 +206,8 @@ STRUCT=106
SAVE=28
FIELDS=107
REM=157
TRUE=160
R_BRACKET=168
TRUE=161
R_BRACKET=169
PROCEDURE=35
JOIN=55
R_PAREN=133
......@@ -217,10 +216,11 @@ NEQ=140
ANY=138
QUESTION=81
LABEL=7
PLUS_INFINITY=164
PLUS_INFINITY=165
PARAMNAMES=95
ASN1=96
KEEP=176
NEG=75
ASSIGN=52
VARIABLES=72
ALTERNATIVE=40
......@@ -450,11 +450,11 @@ class sdl92Lexer(Lexer):
_type = BitStringLiteral
_channel = DEFAULT_CHANNEL
# sdl92.g:848:9: ( '\"' ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )* '\"B' )
# sdl92.g:848:17: '\"' ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )* '\"B'
# sdl92.g:858:9: ( '\"' ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )* '\"B' )
# sdl92.g:858:17: '\"' ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )* '\"B'
pass
self.match(34)
# sdl92.g:848:21: ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )*
# sdl92.g:858:21: ( '0' | '1' | ' ' | '\\t' | '\\r' | '\\n' )*
while True: #loop1
alt1 = 2
LA1_0 = self.input.LA(1)
......@@ -499,11 +499,11 @@ class sdl92Lexer(Lexer):
_type = OctetStringLiteral
_channel = DEFAULT_CHANNEL
# sdl92.g:852:9: ( '\"' ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )* '\"H' )
# sdl92.g:852:17: '\"' ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )* '\"H'
# sdl92.g:862:9: ( '\"' ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )* '\"H' )
# sdl92.g:862:17: '\"' ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )* '\"H'
pass
self.match(34)
# sdl92.g:852:21: ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )*
# sdl92.g:862:21: ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | ' ' | '\\t' | '\\r' | '\\n' )*
while True: #loop2
alt2 = 2
LA2_0 = self.input.LA(1)
......@@ -548,8 +548,8 @@ class sdl92Lexer(Lexer):
_type = ASSIG_OP
_channel = DEFAULT_CHANNEL
# sdl92.g:1158:17: ( ':=' )
# sdl92.g:1158:25: ':='
# sdl92.g:1162:17: ( ':=' )
# sdl92.g:1162:25: ':='
pass
self.match(":=")
......@@ -573,8 +573,8 @@ class sdl92Lexer(Lexer):
_type = L_BRACKET
_channel = DEFAULT_CHANNEL
# sdl92.g:1159:17: ( '{' )
# sdl92.g:1159:25: '{'
# sdl92.g:1163:17: ( '{' )
# sdl92.g:1163:25: '{'
pass
self.match(123)
......@@ -598,8 +598,8 @@ class sdl92Lexer(Lexer):
_type = R_BRACKET
_channel = DEFAULT_CHANNEL
# sdl92.g:1160:17: ( '}' )
# sdl92.g:1160:25: '}'
# sdl92.g:1164:17: ( '}' )
# sdl92.g:1164:25: '}'
pass
self.match(125)
......@@ -623,8 +623,8 @@ class sdl92Lexer(Lexer):
_type = L_PAREN