FreeBASIC  0.91.0
parser-compound-do.bas
Go to the documentation of this file.
1 '' DO..LOOP compound statement parsing
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 #include once "fb.bi"
6 #include once "fbint.bi"
7 #include once "parser.bi"
8 #include once "ast.bi"
9 
10 '' DoStmtBegin = DO ((WHILE | UNTIL) Expression)? .
12  dim as ASTNODE ptr expr = any
13  dim as integer iswhile = any, isuntil = any
14  dim as FBSYMBOL ptr il = any, el = any, cl = any
15  dim as FB_CMPSTMTSTK ptr stk = any
16 
17  '' DO
18  lexSkipToken( )
19 
20  '' add ini and end labels (will be used by any EXIT DO)
21  il = symbAddLabel( NULL )
22  el = symbAddLabel( NULL, FB_SYMBOPT_NONE )
23 
24  '' emit ini label
25  astAdd( astNewLABEL( il ) )
26 
27  '' ((WHILE | UNTIL) Expression)?
28  iswhile = FALSE
29  isuntil = fALSE
30 
31  select case lexGetToken( )
32  case FB_TK_WHILE
33  iswhile = TRUE
34  case FB_TK_UNTIL
35  isuntil = TRUE
36  end select
37 
38  if( iswhile or isuntil ) then
39  lexSkipToken( )
40 
41  '' Expression
42  expr = cExpression( )
43  if( expr = NULL ) then
44  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
45  '' error recovery: fake a node
46  expr = astNewCONSTi( 0 )
47  end if
48 
49  '' branch
50  expr = astBuildBranch( expr, el, (not iswhile) )
51  if( expr = NULL ) then
52  errReport( FB_ERRMSG_INVALIDDATATYPES )
53  '' error recovery: fake a node
54  expr = astNewNOP( )
55  end if
56 
57  astAdd( expr )
58  cl = il
59 
60  else
61  expr = NULL
62  cl = symbAddLabel( NULL, FB_SYMBOPT_NONE )
63  end if
64 
65  '' push to stmt stack
66  stk = cCompStmtPush( FB_TK_DO )
67  stk->scopenode = astScopeBegin( )
68  stk->do.attop = (expr <> NULL)
69  stk->do.inilabel = il
70  stk->do.cmplabel = cl
71  stk->do.endlabel = el
72 end sub
73 
74 '' DoStmtEnd = LOOP ((WHILE | UNTIL) Expression)? .
75 sub cDoStmtEnd( )
76  dim as ASTNODE ptr expr = any
77  dim as integer iswhile = any, isuntil = any
78  dim as FB_CMPSTMTSTK ptr stk = any
79 
80  stk = cCompStmtGetTOS( FB_TK_DO )
81  if( stk = NULL ) then
82  hSkipStmt( )
83  exit sub
84  end if
85 
86  '' LOOP
87  lexSkipToken( )
88 
89  '' ((WHILE | UNTIL | SttSeparator) Expression)?
90  iswhile = FALSE
91  isuntil = fALSE
92 
93  select case lexGetToken( )
94  case FB_TK_WHILE
95  iswhile = TRUE
96  case FB_TK_UNTIL
97  isuntil = TRUE
98  end select
99 
100  if( (iswhile or isuntil) and (stk->do.attop) ) then
101  errReport( FB_ERRMSG_SYNTAXERROR )
102  end if
103 
104  '' end scope
105  if( stk->scopenode <> NULL ) then
106  astScopeEnd( stk->scopenode )
107  end if
108 
109  '' emit comp label, if needed
110  if( stk->do.cmplabel <> stk->do.inilabel ) then
111  astAdd( astNewLABEL( stk->do.cmplabel ) )
112  end if
113 
114  '' bottom check?
115  if( iswhile or isuntil ) then
116  lexSkipToken( )
117 
118  '' Expression
119  expr = cExpression( )
120  if( expr = NULL ) then
121  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
122  '' error recovery: fake a node
123  expr = astNewCONSTi( 0 )
124  end if
125 
126  '' branch
127  expr = astBuildBranch( expr, stk->do.inilabel, iswhile )
128  if( expr = NULL ) then
129  errReport( FB_ERRMSG_INVALIDDATATYPES )
130  '' error recovery: fake a node
131  expr = astNewNOP( )
132  end if
133 
134  astAdd( expr )
135  else
136  '' top check
137  astAdd( astNewBRANCH( AST_OP_JMP, stk->do.inilabel ) )
138  end if
139 
140  '' end label (loop exit)
141  astAdd( astNewLABEL( stk->do.endlabel ) )
142 
143  '' pop from stmt stack
144  cCompStmtPop( stk )
145 end sub
146