Commit eac5a1fa authored by dbarbera's avatar dbarbera
Browse files

Refactor prim_value into literal and prim_path

parent c78539cc
...@@ -1065,116 +1065,19 @@ def expression_list(root, context): ...@@ -1065,116 +1065,19 @@ def expression_list(root, context):
return result, errors, warnings return result, errors, warnings
def primary_value(root, context=None): def primary_path(root, context=None):
''' '''Process a primary path'''
Process a primary expression such as a!b(4)!c(hello)
or { x 1, y a:2 } (ASN.1 Value Notation)
Try to determine the type of the primary when possible
There are three cases where the type cannot be determined at all:
(1) if the primary is a single literal (can be a var, enum or choice)
(2) if the primary is a sequence literal
(3) if the type is a choice literal
In case of a SEQUENCE OF, the Min/Max values are set
'''
warnings = []
errors = []
prim = None
global TMPVAR global TMPVAR
def primary_elem(child): errors, warnings = [], []
''' Process a single token '''
prim = None
if child.type == lexer.ID:
prim = ogAST.PrimPath()
prim.value = [child.text]
prim.exprType = UNKNOWN_TYPE
elif child.type == lexer.INT:
prim = ogAST.PrimInteger()
prim.value = [child.text.lower()]
prim.exprType = type('PrInt', (object,),
{'kind': 'IntegerType', 'Min': child.text, 'Max': child.text})
elif child.type in (lexer.TRUE, lexer.FALSE):
prim = ogAST.PrimBoolean()
prim.value = [child.text.lower()]
prim.exprType = type('PrBool', (object,), {'kind': 'BooleanType'})
elif child.type == lexer.FLOAT:
prim = ogAST.PrimReal()
prim.value = [child.getChild(0).text]
prim.exprType = type('PrReal', (object,),
{'kind': 'RealType',
'Min': prim.value[0], 'Max': prim.value[0]})
elif child.type == lexer.STRING:
prim = ogAST.PrimStringLiteral()
prim.value = child.getChild(0).text
prim.exprType = type('PrStr', (object,),
{'kind': 'StringType',
'Min': str(len(prim.value) - 2),
'Max': str(len(prim.value) - 2)})
elif child.type == lexer.FLOAT2:
prim = ogAST.PrimMantissaBaseExp()
mant = float(child.getChild(0).toString())
base = int(child.getChild(1).toString())
exp = int(child.getChild(2).toString())
# Compute mantissa * base**exponent to get the value type range
value = float(mant * pow(base, exp))
prim.value = {'mantissa': mant, 'base': base, 'exponent': exp}
prim.exprType = type('PrMantissa', (object,),
{'kind': 'RealType',
'Min': str(value), 'Max': str(value)})
elif child.type == lexer.EMPTYSTR:
# Empty SEQUENCE OF (i.e. "{}")
prim = ogAST.PrimEmptyString()
prim.exprType = type('PrES', (object,), {'kind': 'SequenceOfType',
'Min': '0', 'Max': '0'})
elif child.type == lexer.CHOICE:
prim = ogAST.PrimChoiceItem()
choice = child.getChild(0).toString()
expr, err, warn = expression(child.getChild(1), context)
errors.extend(err)
warnings.extend(warn)
prim.value = {'choice': choice, 'value': expr}
prim.exprType = UNKNOWN_TYPE
elif child.type == lexer.SEQUENCE:
prim = ogAST.PrimSequence()
prim.value = {}
for elem in child.getChildren():
if elem.type == lexer.ID:
field_name = elem.text
else:
prim.value[field_name], err, warn = (
expression(elem, context))
errors.extend(err)
warnings.extend(warn)
prim.exprType = UNKNOWN_TYPE
elif child.type == lexer.SEQOF:
prim = ogAST.PrimSequenceOf()
prim.value = []
for elem in child.getChildren():
# SEQUENCE OF elements cannot have fieldnames/indexes
prim_elem = primary_elem(elem)
prim_elem.inputString = get_input_string(elem)
prim_elem.line = elem.getLine()
prim_elem.charPositionInLine = elem.getCharPositionInLine()
prim.value.append(prim_elem)
prim.exprType = type('PrSO', (object,), {
'kind': 'SequenceOfType',
'Min': str(len(child.children)),
'Max': str(len(child.children)),
'type': UNKNOWN_TYPE
})
elif child.type == lexer.BITSTR:
prim = ogAST.PrimBitStringLiteral()
warnings.append('Bit string literal not supported yet')
elif child.type == lexer.OCTSTR:
prim = ogAST.PrimOctetStringLiteral()
warnings.append('Octet string literal not supported yet')
else:
warnings.append('Unsupported primary construct, type:' +
str(child.type) +
' (line ' + str(child.getLine()) + ')')
return prim
prim = primary_elem(root.getChild(0)) prim = ogAST.PrimPath()
prim.value = [root.children[0].text]
prim.exprType = UNKNOWN_TYPE
global TMPVAR
prim.tmpVar = TMPVAR
TMPVAR += 1
# Process fields or params, if any # Process fields or params, if any
for child in root.children[slice(1, len(root.children))]: for child in root.children[slice(1, len(root.children))]:
...@@ -1230,10 +1133,6 @@ def primary_value(root, context=None): ...@@ -1230,10 +1133,6 @@ def primary_value(root, context=None):
else: else:
prim = ogAST.PrimPath() prim = ogAST.PrimPath()
global TMPVAR
prim.tmpVar = TMPVAR
TMPVAR += 1
return prim, errors, warnings return prim, errors, warnings
...@@ -1322,12 +1221,13 @@ def expression(root, context): ...@@ -1322,12 +1221,13 @@ def expression(root, context):
return neg_expression(root, context) return neg_expression(root, context)
elif root.type == lexer.PAREN: elif root.type == lexer.PAREN:
return expression(root.children[0], context) return expression(root.children[0], context)
elif root.type == lexer.PRIMARY_ID: elif root.type == lexer.PRIMPATH:
return primary_value(root, context) return primary_path(root, context)
elif root.type == lexer.IFTHENELSE: elif root.type == lexer.IFTHENELSE:
return if_then_else_expression(root, context) return if_then_else_expression(root, context)
elif root.type == lexer.LITERAL:
return literal(root.children[0], context)
else: else:
# TODO: return error/warning message
raise NotImplementedError raise NotImplementedError
...@@ -1566,6 +1466,119 @@ def if_then_else_expression(root, context): ...@@ -1566,6 +1466,119 @@ def if_then_else_expression(root, context):
return expr, errors, warnings return expr, errors, warnings
def literal(root, context):
''' Literal expression analysis '''
prim, errors, warnings = None, [], []
if root.type == lexer.ID:
prim = ogAST.PrimPath()
prim.value = [root.text]
prim.exprType = UNKNOWN_TYPE
elif root.type == lexer.INT:
prim = ogAST.PrimInteger()
prim.value = [root.text.lower()]
prim.exprType = type('PrInt', (object,), {
'kind': 'IntegerType',
'Min': root.text,
'Max': root.text
})
elif root.type in (lexer.TRUE, lexer.FALSE):
prim = ogAST.PrimBoolean()
prim.value = [root.text.lower()]
prim.exprType = type('PrBool', (object,), {'kind': 'BooleanType'})
elif root.type == lexer.FLOAT:
prim = ogAST.PrimReal()
prim.value = [root.text]
prim.exprType = type('PrReal', (object,), {
'kind': 'RealType',
'Min': prim.value[0],
'Max': prim.value[0]
})
elif root.type == lexer.STRING:
prim = ogAST.PrimStringLiteral()
prim.value = root.text
prim.exprType = type('PrStr', (object,), {
'kind': 'StringType',
'Min': str(len(prim.value) - 2),
'Max': str(len(prim.value) - 2)
})
elif root.type == lexer.FLOAT2:
prim = ogAST.PrimMantissaBaseExp()
mant = float(root.getChild(0).toString())
base = int(root.getChild(1).toString())
exp = int(root.getChild(2).toString())
# Compute mantissa * base**exponent to get the value type range
value = float(mant * pow(base, exp))
prim.value = {'mantissa': mant, 'base': base, 'exponent': exp}
prim.exprType = type('PrMantissa', (object,), {
'kind': 'RealType',
'Min': str(value),
'Max': str(value)
})
elif root.type == lexer.EMPTYSTR:
# Empty SEQUENCE OF (i.e. "{}")
prim = ogAST.PrimEmptyString()
prim.exprType = type('PrES', (object,), {
'kind': 'SequenceOfType',
'Min': '0',
'Max': '0'
})
elif root.type == lexer.CHOICE:
prim = ogAST.PrimChoiceItem()
choice = root.getChild(0).toString()
expr, err, warn = expression(root.getChild(1), context)
errors.extend(err)
warnings.extend(warn)
prim.value = {'choice': choice, 'value': expr}
prim.exprType = UNKNOWN_TYPE
elif root.type == lexer.SEQUENCE:
prim = ogAST.PrimSequence()
prim.value = {}
for elem in root.getChildren():
if elem.type == lexer.ID:
field_name = elem.text
else:
prim.value[field_name], err, warn = (expression(elem, context))
errors.extend(err)
warnings.extend(warn)
prim.exprType = UNKNOWN_TYPE
elif root.type == lexer.SEQOF:
prim = ogAST.PrimSequenceOf()
prim.value = []
for elem in root.getChildren():
# SEQUENCE OF elements cannot have fieldnames/indexes
prim_elem, prim_elem_errors, prim_elem_warnings = literal(elem, context)
errors += prim_elem_errors
warnings += prim_elem_warnings
prim_elem.inputString = get_input_string(elem)
prim_elem.line = elem.getLine()
prim_elem.charPositionInLine = elem.getCharPositionInLine()
prim.value.append(prim_elem)
prim.exprType = type('PrSO', (object,), {
'kind': 'SequenceOfType',
'Min': str(len(root.children)),
'Max': str(len(root.children)),
'type': UNKNOWN_TYPE
})
elif root.type == lexer.BITSTR:
prim = ogAST.PrimBitStringLiteral()
warnings.append('Bit string literal not supported yet')
elif root.type == lexer.OCTSTR:
prim = ogAST.PrimOctetStringLiteral()
warnings.append('Octet string literal not supported yet')
else:
# TODO: return error message
raise NotImplementedError
prim.inputString = get_input_string(root)
global TMPVAR
prim.tmpVar = TMPVAR
TMPVAR += 1
return prim, errors, warnings
def variables(root, ta_ast, context): def variables(root, ta_ast, context):
''' Process declarations of variables (dcl a,b Type := 5) ''' ''' Process declarations of variables (dcl a,b Type := 5) '''
var = [] var = []
...@@ -2662,7 +2675,7 @@ def end(root, parent=None, context=None): ...@@ -2662,7 +2675,7 @@ def end(root, parent=None, context=None):
if child.type == lexer.CIF: if child.type == lexer.CIF:
# Get symbol coordinates # Get symbol coordinates
c.pos_x, c.pos_y, c.width, c.height = cif(child) c.pos_x, c.pos_y, c.width, c.height = cif(child)
elif child.type == lexer.StringLiteral: elif child.type == lexer.STRING:
c.inputString = child.toString()[1:-1] c.inputString = child.toString()[1:-1]
elif child.type == lexer.HYPERLINK: elif child.type == lexer.HYPERLINK:
c.hyperlink = child.getChild(0).toString()[1:-1] c.hyperlink = child.getChild(0).toString()[1:-1]
...@@ -3076,7 +3089,7 @@ def assign(root, context): ...@@ -3076,7 +3089,7 @@ def assign(root, context):
for child in root.getChildren(): for child in root.getChildren():
if child.type == lexer.VARIABLE: if child.type == lexer.VARIABLE:
# Left part of the assignation # Left part of the assignation
prim, err, warn = primary_value(child, context) prim, err, warn = primary_path(child, context)
prim.inputString = get_input_string(child) prim.inputString = get_input_string(child)
prim.line = child.getLine() prim.line = child.getLine()
prim.charPositionInLine = child.getCharPositionInLine() prim.charPositionInLine = child.getCharPositionInLine()
...@@ -3146,7 +3159,7 @@ def for_loop(root, context): ...@@ -3146,7 +3159,7 @@ def for_loop(root, context):
# Implicit variable declaration for the iterator # Implicit variable declaration for the iterator
context_scope = dict(context.variables) context_scope = dict(context.variables)
elif child.type == lexer.VARIABLE: elif child.type == lexer.VARIABLE:
list_var, err, warn = primary_value(child, context) list_var, err, warn = primary_path(child, context)
forloop['list'] = ogAST.PrimVariable(primary=list_var) forloop['list'] = ogAST.PrimVariable(primary=list_var)
warnings.extend(warn) warnings.extend(warn)
errors.extend(err) errors.extend(err)
......
...@@ -69,6 +69,7 @@ tokens { ...@@ -69,6 +69,7 @@ tokens {
INPUTLIST; INPUTLIST;
JOIN; JOIN;
LABEL; LABEL;
LITERAL;
NEG; NEG;
NEWTYPE; NEWTYPE;
NEXTSTATE; NEXTSTATE;
...@@ -82,7 +83,7 @@ tokens { ...@@ -82,7 +83,7 @@ tokens {
PARAMS; PARAMS;
PAREN; PAREN;
PRIMARY; PRIMARY;
PRIMARY_ID; PRIMPATH;
PROCEDURE; PROCEDURE;
PROCEDURE_CALL; PROCEDURE_CALL;
PROCEDURE_NAME; PROCEDURE_NAME;
...@@ -820,51 +821,42 @@ operand5 ...@@ -820,51 +821,42 @@ operand5
| DASH operand5 -> ^(NEG operand5); | DASH operand5 -> ^(NEG operand5);
primary primary
: asn1Value primary_params* -> ^(PRIMARY_ID asn1Value primary_params*) : ID primary_params+ -> ^(PRIMPATH ID primary_params*)
| L_PAREN expression R_PAREN -> ^(PAREN expression) | literal -> ^(LITERAL literal)
| '(' expression ')' -> ^(PAREN expression)
| conditional_ground_expression | conditional_ground_expression
; ;
// ASN.1 Value Notation used for assignations and comparisons literal
asn1Value : BITSTR^
: BitStringLiteral -> ^(BITSTR BitStringLiteral) | OCTSTR^
| OctetStringLiteral -> ^(OCTSTR OctetStringLiteral)
| TRUE^ | TRUE^
| FALSE^ | FALSE^
| StringLiteral -> ^(STRING StringLiteral) | STRING
| NULL^ | NULL^
| PLUS_INFINITY^ | PLUS_INFINITY^
| MINUS_INFINITY^ | MINUS_INFINITY^
| ID | INT^
| INT | FLOAT^
| FloatingPointLiteral -> ^(FLOAT FloatingPointLiteral) | ID^
| L_BRACKET R_BRACKET -> ^(EMPTYSTR) | choiceValue
| L_BRACKET | '{' '}' -> ^(EMPTYSTR)
| '{'
MANTISSA mant=INT COMMA MANTISSA mant=INT COMMA
BASE bas=INT COMMA BASE bas=INT COMMA
EXPONENT exp=INT EXPONENT exp=INT
R_BRACKET -> ^(FLOAT2 $mant $bas $exp) '}' -> ^(FLOAT2 $mant $bas $exp)
| choiceValue | '{'
| L_BRACKET
namedValue (COMMA namedValue)* namedValue (COMMA namedValue)*
R_BRACKET -> ^(SEQUENCE namedValue+) '}' -> ^(SEQUENCE namedValue+)
| L_BRACKET | '{'
asn1Value (COMMA asn1Value)* literal (COMMA literal)*
R_BRACKET -> ^(SEQOF asn1Value+) '}' -> ^(SEQOF literal+)
; ;
BitStringLiteral
: '"' ('0'|'1'|' ' | '\t' | '\r' | '\n')* '"B';
OctetStringLiteral
: '"' ('0'..'9'|'a'..'f'|'A'..'F'|' ' | '\t' | '\r' | '\n')*
'"H';
informal_text informal_text
: StringLiteral : STRING
-> ^(INFORMAL_TEXT StringLiteral); -> ^(INFORMAL_TEXT STRING);
// hello:5 (CHOICE field value) // hello:5 (CHOICE field value)
...@@ -1043,8 +1035,8 @@ via : VIA state_entry_point_name ...@@ -1043,8 +1035,8 @@ via : VIA state_entry_point_name
end end
: (cif? hyperlink? COMMENT StringLiteral)? SEMI : (cif? hyperlink? COMMENT STRING)? SEMI
-> ^(COMMENT cif? hyperlink? StringLiteral)?; -> ^(COMMENT cif? hyperlink? STRING)?;
cif cif
...@@ -1057,9 +1049,9 @@ cif ...@@ -1057,9 +1049,9 @@ cif
hyperlink hyperlink
: cif_decl KEEP SPECIFIC GEODE HYPERLINK StringLiteral : cif_decl KEEP SPECIFIC GEODE HYPERLINK STRING
cif_end cif_end
-> ^(HYPERLINK StringLiteral); -> ^(HYPERLINK STRING);
/* OpenGEODE specific: SDL does not allow specifying the name /* OpenGEODE specific: SDL does not allow specifying the name
of signal parameters, but it is needed to generate function signatures of signal parameters, but it is needed to generate function signatures
...@@ -1078,8 +1070,8 @@ paramnames ...@@ -1078,8 +1070,8 @@ paramnames
CIF Extensions are valid SDL constructs (ITU-T Z106) CIF Extensions are valid SDL constructs (ITU-T Z106)
*/ */
use_asn1 use_asn1
: cif_decl KEEP SPECIFIC GEODE ASNFILENAME StringLiteral cif_end : cif_decl KEEP SPECIFIC GEODE ASNFILENAME STRING cif_end
-> ^(ASN1 StringLiteral); -> ^(ASN1 STRING);
symbolname symbolname
...@@ -1286,12 +1278,21 @@ SYNONYM : S Y N O N Y M; ...@@ -1286,12 +1278,21 @@ SYNONYM : S Y N O N Y M;
IMPORT : I M P O R T; IMPORT : I M P O R T;
VIEW : V I E W; VIEW : V I E W;
ACTIVE : A C T I V E; ACTIVE : A C T I V E;
StringLiteral : STR+ ;
fragment fragment
STR STR
: '\'' ( options {greedy=false;} : .)* '\'' : '\'' ( options {greedy=false;} : .)* '\'';
;
STRING
: STR+ ;
BITSTR
: '"' ('0'|'1'|' ' | '\t' | '\r' | '\n')* '"B';
OCTSTR
: '"' ('0'..'9'|'a'..'f'|'A'..'F'|' ' | '\t' | '\r' | '\n')*
'"H';
ID ID
: ALPHA (ALPHA | DIGITS | '_')*; : ALPHA (ALPHA | DIGITS | '_')*;
...@@ -1306,13 +1307,12 @@ fragment ...@@ -1306,13 +1307,12 @@ fragment
DIGITS DIGITS
: ('0'..'9')+; : ('0'..'9')+;
FloatingPointLiteral FLOAT
: INT DOT (DIGITS)? (Exponent)? : INT DOT (DIGITS)? (Exponent)?
| INT | INT
; ;
WS : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;} WS : (' ' | '\t' | '\r' | '\n')+ {$channel=HIDDEN;};
;
/* /*
COMMENT COMMENT
: '//' ( options {greedy=false;} : . )* '//' {$channel=HIDDEN;} : '//' ( options {greedy=false;} : . )* '//' {$channel=HIDDEN;}
......
This diff is collapsed.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment