Skip to content

Commit

Permalink
Allow modifiers such as (),[] and . on any variable access
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson committed Jan 18, 2016
1 parent cc3e2da commit f923900
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,140 @@ static Obj GAPInfo;

static UInt WarnOnUnboundGlobalsRNam;


void ReadReferenceModifiers( TypSymbolSet follow )
{
char type = ' ';
UInt level = 0;
UInt narg = 0;
UInt rnam = 0;
/* followed by one or more selectors */
while ( IS_IN( TLS(Symbol), S_LPAREN|S_LBRACK|S_LBRACE|S_DOT ) ) {
/* <Var> '[' <Expr> ']' list selector */
if ( TLS(Symbol) == S_LBRACK ) {
Match( S_LBRACK, "[", follow );
ReadExpr( S_COMMA|S_RBRACK|follow, 'r' );
narg = 1;
while ( TLS(Symbol) == S_COMMA) {
Match(S_COMMA,",", follow|S_RBRACK);
ReadExpr(S_COMMA|S_RBRACK|follow, 'r' );
narg++;
}
Match( S_RBRACK, "]", follow );
type = (level == 0 ? '[' : ']');
}

/* <Var> '{' <Expr> '}' sublist selector */
else if ( TLS(Symbol) == S_LBRACE ) {
Match( S_LBRACE, "{", follow );
ReadExpr( S_RBRACE|follow, 'r' );
Match( S_RBRACE, "}", follow );
type = (level == 0 ? '{' : '}');
}

/* <Var> '![' <Expr> ']' list selector */
else if ( TLS(Symbol) == S_BLBRACK ) {
Match( S_BLBRACK, "![", follow );
ReadExpr( S_RBRACK|follow, 'r' );
Match( S_RBRACK, "]", follow );
type = (level == 0 ? '<' : '>');
}

/* <Var> '!{' <Expr> '}' sublist selector */
else if ( TLS(Symbol) == S_BLBRACE ) {
Match( S_BLBRACE, "!{", follow );
ReadExpr( S_RBRACE|follow, 'r' );
Match( S_RBRACE, "}", follow );
type = (level == 0 ? '(' : ')');
}

/* <Var> '.' <Ident> record selector */
else if ( TLS(Symbol) == S_DOT ) {
Match( S_DOT, ".", follow );
if ( TLS(Symbol) == S_IDENT || TLS(Symbol) == S_INT ) {
rnam = RNamName( TLS(Value) );
Match( TLS(Symbol), "identifier", follow );
type = '.';
}
else if ( TLS(Symbol) == S_LPAREN ) {
Match( S_LPAREN, "(", follow );
ReadExpr( S_RPAREN|follow, 'r' );
Match( S_RPAREN, ")", follow );
type = ':';
}
else {
SyntaxError("Record component name expected");
}
level = 0;
}

/* <Var> '!.' <Ident> record selector */
else if ( TLS(Symbol) == S_BDOT ) {
Match( S_BDOT, "!.", follow );
if ( TLS(Symbol) == S_IDENT || TLS(Symbol) == S_INT ) {
rnam = RNamName( TLS(Value) );
Match( TLS(Symbol), "identifier", follow );
type = '!';
}
else if ( TLS(Symbol) == S_LPAREN ) {
Match( S_LPAREN, "(", follow );
ReadExpr( S_RPAREN|follow, 'r' );
Match( S_RPAREN, ")", follow );
type = '|';
}
else {
SyntaxError("Record component name expected");
}
level = 0;
}

/* <Var> '(' [ <Expr> { ',' <Expr> } ] ')' function call */
else if ( TLS(Symbol) == S_LPAREN ) {
Match( S_LPAREN, "(", follow );
if ( ! READ_ERROR() ) { IntrFuncCallBegin(); }
narg = 0;
if ( TLS(Symbol) != S_RPAREN && TLS(Symbol) != S_COLON) {
ReadExpr( S_RPAREN|follow, 'r' );
narg++;
}
while ( TLS(Symbol) == S_COMMA ) {
Match( S_COMMA, ",", follow );
ReadExpr( S_RPAREN|follow, 'r' );
narg++;
}
type = 'c';
if (TLS(Symbol) == S_COLON ) {
Match( S_COLON, ":", follow );
if ( TLS(Symbol) != S_RPAREN ) /* save work for empty options */
{
ReadFuncCallOptions(S_RPAREN | follow);
type = 'C';
}
}
Match( S_RPAREN, ")", follow );
}

/* so the prefix was a reference */
if ( READ_ERROR() ) {}
else if ( type == '[' ) { IntrElmList(narg); }
else if ( type == ']' ) { IntrElmListLevel( narg, level ); }
else if ( type == '{' ) { IntrElmsList(); level++; }
else if ( type == '}' ) { IntrElmsListLevel( level ); level++; }
else if ( type == '<' ) { IntrElmPosObj(); }
else if ( type == '>' ) { IntrElmPosObjLevel( level ); }
else if ( type == '(' ) { IntrElmsPosObj(); level++; }
else if ( type == ')' ) { IntrElmsPosObjLevel( level ); level++; }
else if ( type == '.' ) { IntrElmRecName( rnam ); level=0; }
else if ( type == ':' ) { IntrElmRecExpr(); level=0; }
else if ( type == '!' ) { IntrElmComObjName( rnam ); level=0; }
else if ( type == '|' ) { IntrElmComObjExpr(); level=0; }
else if ( type == 'c' || type == 'C' )
{ IntrFuncCallEnd( 1UL, type == 'C', narg ); level=0; }
else
SyntaxError("Parse error in modifiers"); // This should never be reached
}
}

void ReadCallVarAss (
TypSymbolSet follow,
Char mode )
Expand Down Expand Up @@ -1609,6 +1743,8 @@ void ReadAtom (
else {
Match( S_INT, "expression", follow );
}

ReadReferenceModifiers(follow);
}


Expand Down
40 changes: 40 additions & 0 deletions tst/testinstall/modifiers.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#############################################################################
##
#W modifiers.tst GAP Library
##
##
gap> START_TEST("modifiers.tst");
gap> x := rec();
rec( )
gap> x.2 := 3;
3
gap> x;
rec( 2 := 3 )
gap> x.2 := rec();
rec( )
gap> x.2.3 := 5;
5
gap> x;
rec( 2 := rec( 3 := 5 ) )
gap> x.f := -> rec();
function( ) ... end
gap> x;
rec( 2 := rec( 3 := 5 ), f := function( ) ... end )
gap> x.f().q := 6;
6
gap> y := [];
[ ]
gap> x := rec( a := 3 );
rec( a := 3 )
gap> 1 + x.a;
4
gap> x.f := -> [4];
function( ) ... end
gap> 4 + x.f()[1];
8
gap> x.f()[1];
4
gap> l := [[1,2,3],[4,5,6],[7,8,9]];;
gap> Print(l{[2..3]}{[2..3]},"\n");
[ [ 5, 6 ], [ 8, 9 ] ]
gap> STOP_TEST( "modifiers.tst", 1);
2 changes: 2 additions & 0 deletions tst/teststandard/bugfix.tst
Original file line number Diff line number Diff line change
Expand Up @@ -2611,6 +2611,8 @@ Syntax error: Badly formed number: need a digit before or after the decimal po\
int in stream line 1
. . . .
^
Syntax error: Record component name expected in stream line 2
^

# 2013/08/29 (MH)
gap> record := rec( foo := "bar" );
Expand Down

0 comments on commit f923900

Please sign in to comment.