XTRAN Example — Translate PL/M $IF/$ELSEIF/$ELSE Statements to C
The following example uses the standard set of XTRAN rules for parsing PL/M and translating it to C. The input and output are untouched, except for parenthetical remarks added to the input.
NOTE that the translation shown below was done with default conditions. XTRAN provides many options for controlling the way it translates.
Process Flowchart
Here is a flowchart for this process, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
code
Input to XTRAN: demcif.plm
(Since we're not in an include file, all
$IF
/$ELSEIF
/$ELSE
consequences should
be parsed, except those that enclose parts of statements.)
DECLARE foo BYTE; $SET (SETV1,SETV2=3) DECLARE yes_1 WORD; /*should parse*/ $IF SETV1 /*true*/ DECLARE yes_2 WORD; /*should parse*/ $ELSEIF SETV2=3 /*false*/ DECLARE yes_3 WORD; /*should parse*/ DECLARE yes_4 WORD; /*should parse*/ $ELSE DECLARE yes_5 WORD; /*should parse*/ DECLARE yes_6 WORD; /*should parse*/ $ENDIF DECLARE yes_7_end WORD; /*should parse*/ $INCLUDE(FOO:DEMCIF1.PLM) $SET (SETV3) /*will survive*/ foo = $IF (SETV3) /*won't survive*/ 2 $ELSE /*won't survive*/ 3 $ENDIF /*won't survive*/ ; $RESET (SETV3) /*will survive*/ foo = $IF (SETV3) /*won't survive*/ 2 $ELSE /*won't survive*/ 3 $ENDIF /*won't survive*/ ; $IF setv3 IF foo = 1 THEN DO; foo = 10; END; $ELSE IF foo = 2 THEN DO; foo = 20; END; $ENDIF $IF NOT setv3 foo = 30; $ENDIF $SET (setv1, setv2) $IF (setv1) $IF (setv2) foo = 1; $ENDIF foo = 2; $ELSE foo = 3; $ENDIF $IF (setv3) /* foo = 4; */ $ELSE /* foo = 5; */ $ENDIF
Input to XTRAN: demcif1.plm
(This file is included by demcif.plm
. Since we're in an
$INCLUDE
file, none of the control statements should survive, but
should be honored.)
$SET (SETV3,SETV4=3) declare inc_yes_1 word; /*should parse*/ $RESET (SETV3) declare inc_yes_2 word; /*should parse*/ $SET (SETV4=2) $IF (UNSETV1) /*false*/ declare inc_no_1 word; /*shouldn't parse*/ $ELSEIF (SETV4=2) declare inc_yes_3 word; /*should parse*/ declare inc_yes_4_end word; /*should parse*/ $ELSE declare inc_no_2_end word; /*shouldn't parse*/ $ENDIF
Output from XTRAN:
static unsigned char foo; #undef PP_SETV1 #define PP_SETV1 0xFF #undef PP_SETV2 #define PP_SETV2 3 static unsigned short yes_1; /*should parse*/ #if defined PP_SETV1 ? PP_SETV1 & 1 : 0 /*true*/ static unsigned short yes_2; /*should parse*/ #else #if (defined PP_SETV2 ? PP_SETV2 : 0) == 3 /*false*/ static unsigned short yes_3; /*should parse*/ static unsigned short yes_4; /*should parse*/ #else static unsigned short yes_5; /*should parse*/ static unsigned short yes_6; /*should parse*/ #endif #endif static unsigned short yes_7_end; /*should parse*/ #include "demcif1.h" #undef PP_SETV3 /*will survive*/ #define PP_SETV3 0xFF foo = 2; #undef PP_SETV3 /*will survive*/ foo = 3; #if defined PP_SETV3 ? PP_SETV3 & 1 : 0 if (foo == 1) { foo = 10; } #else if (foo == 2) { foo = 20; } #endif #if !(defined PP_SETV3 ? PP_SETV3 & 1 : 0) foo = 30; #endif #undef PP_SETV1 #define PP_SETV1 0xFF #undef PP_SETV2 #define PP_SETV2 0xFF #if defined PP_SETV1 ? PP_SETV1 & 1 : 0 #if defined PP_SETV2 ? PP_SETV2 & 1 : 0 foo = 1; #endif foo = 2; #else foo = 3; #endif #if defined PP_SETV3 ? PP_SETV3 & 1 : 0 /* foo = 4; */ #else /* foo = 5; */ #endif
Messages from the run:
demcif.plm(34) -- %XTRAN: Warning! Control line honored and deleted! demcif.plm(36) -- %XTRAN: Warning! Control line honored and deleted! demcif.plm(36) -- %XTRAN: Warning! Skipping code due to failed $IF/$ELSE! demcif.plm(38) -- %XTRAN: Warning! Control line honored and deleted! demcif.plm(42) -- %XTRAN: Warning! Control line honored and deleted! demcif.plm(42) -- %XTRAN: Warning! Skipping code due to failed $IF/$ELSE! demcif.plm(44) -- %XTRAN: Warning! Control line honored and deleted! demcif.plm(46) -- %XTRAN: Warning! Control line honored and deleted!