1 //  This is Nsymb, which returns the next symbol of the real program (before SEMICOLON_S is inserted.)
  2 //  Last modified on 06/06/74 at 18:25:56 by R F Mabee.
  3 //  Installed on 6180 as Version 3.4, R F Mabee.
  4 //  First installed on 645 as Version 2.7, R F Mabee.
  5 
  6 //  Copyright (c) 1974 by Massachusetts Institute of Technology and Honeywell Information Systems, Inc.
  7 
  8 //  General permission is granted to copy and use this program, but not to sell it, provided that the above
  9 //  copyright statement is given.  Contact Information Processing Services, MIT, for further information.
 10 //  Please contact R F Mabee at MIT for information on this program and versions for other machines.
 11 
 12 get "bcpl_lex_head"
 13 
 14 let Nsymb () = valof
 15      $(   let Sym = nil
 16           Vp := 0
 17   Top:    switchon Chkind into
 18                $(   case Ignorable:
 19                               Rch () repeatwhile Chkind = Ignorable
 20                               goto Top
 21 
 22                     case Small:
 23                               SaveCh () repeatwhile Chkind = Small
 24                               V!0 := Vp
 25                               Sym := EnterIntoDictionary (V, NAME_S)
 26                               if Sym = NAME_S & Vp ge 2 do CaeReport (BadSystemword, DictionaryEntry!1)
 27                               resultis Sym
 28 
 29                     case Capital:
 30                               SaveCh () repeatwhile Chkind ge Digit
 31                               V!0 := Vp
 32                               resultis EnterIntoDictionary (V, NAME_S)
 33 
 34                     case Digit:
 35                               SaveCh () repeatwhile Chkind = Digit
 36                               if Ch = '.' do
 37                                    $(   SaveCh () repeatwhile Chkind = Digit
 38                                         if Ch = 'e' logor Ch = 'E' do
 39                                              $(   SaveCh ()
 40                                                   if Ch = '+' logor Ch = '-' do SaveCh ()
 41                                                   test Chkind = Digit
 42                                                   then SaveCh () repeatwhile Chkind = Digit
 43                                                   or CaeReport (BadNumber)
 44                                              $)
 45                                    $)
 46                               V!0 := Vp
 47                               resultis EnterIntoDictionary (V, NUMBER_S)
 48 
 49                     case Bracket:
 50                               test Ch = '{'
 51                               then Sym := SECTBRA_S
 52                               or Sym, Ch := SECTKET_S, '{'            //  Make string part same as SECTBRA_S.
 53                       Rtag:   SaveCh () repeatwhile Chkind ge Digit
 54                               V!0 := Vp
 55                               EnterIntoDictionary (V, SECTBRA_S)
 56                               resultis Sym
 57 
 58                     case Endline:
 59                               if EndOfAllInputReached resultis ENDPROG_S
 60                               NLPending := true
 61                               Rch () repeatwhile Ch = '*n'
 62                               goto Top
 63 
 64                     case UnderScore:              //  Illegal character, so it falls through.
 65                     case Simple:
 66                $)
 67 
 68           let c = Ch
 69           Rch ()
 70           switchon c into
 71                $(   default:  CaeReport (BadCharacter, c)
 72                               goto Top
 73 
 74                     case '(': resultis RBRA_S
 75                     case ')': resultis RKET_S
 76                     case '[': resultis SBRA_S
 77                     case ']': resultis SKET_S
 78                     case ',': resultis COMMA_S
 79                     case '!': resultis VECAP_S
 80                     case '&': resultis LOGAND_S
 81                     case '|': resultis LOGOR_S
 82                     case ';': resultis SEMICOLON_S
 83                     case '=': resultis VALDEF_S
 84                     case '+': resultis PLUS_S
 85                     case '**':resultis MULT_S
 86 
 87                     case '-': unless Ch = '>' logor Ch = '**' resultis MINUS_S
 88                               Rch ()
 89                               resultis COND_S
 90                     case '/': unless Ch = '/' resultis DIV_S
 91                               Rch () repeatuntil Chkind = Endline
 92                               goto Top
 93                     case ':': unless Ch = '=' resultis COLON_S
 94                               Rch ()
 95                               resultis ASSIGN_S
 96                     case '^': unless Ch = '=' resultis NOT_S
 97                               Rch ()
 98                               resultis NE_S
 99                     case '<': unless Ch = '=' resultis LS_S
100                               Rch ()
101                               resultis LE_S
102                     case '>': unless Ch = '=' resultis GR_S
103                               Rch ()
104                               resultis GE_S
105 
106                     case '$': switchon Ch into
107                                    $(   case '(': Sym := SECTBRA_S
108                                                   goto Rtag
109 
110                                         case ')': Sym, Ch := SECTKET_S, '('
111                                                   goto Rtag
112 
113                                         case '2': case '8': case 'X':
114                                                   V!1, Vp := '$', 1
115                                                   c := Ch             //  Remember base.
116                                                        $(   SaveCh ()
117                                                             switchon Ch into
118                                                                  $(   case '8': case '9': case 'A': case 'B':
119                                                                       case 'C': case 'D': case 'E': case 'F':
120                                                                                 if c = 'X' loop
121                                                                                 break
122                                                                       case '2': case '3': case '4':
123                                                                       case '5': case '6': case '7':
124                                                                                 unless c = '2' loop
125                                                                                 break
126                                                                       case '0': case '1':
127                                                                                 loop
128                                                                       default:  break
129                                                                  $)
130                                                        $)   repeat
131                                                   V!0 := Vp
132                                                   resultis EnterIntoDictionary (V, NUMBER_S)
133 
134                                         default:  CaeReport (BadDollar, Ch)
135                                                   goto Top
136                                    $)
137 
138                     case '.': c := Nsymb ()
139                               switchon c into
140                                    $(   case VALDEF_S:
141                                         case EQ_S:          resultis EQ_F
142                                         case NE_S:          resultis NE_F
143                                         case LS_S:          resultis LS_F
144                                         case LE_S:          resultis LE_F
145                                         case GR_S:          resultis GR_F
146                                         case GE_S:          resultis GE_F
147                                         case PLUS_S:        resultis PLUS_F
148                                         case MINUS_S:       resultis MINUS_F
149                                         case MULT_S:        resultis MULT_F
150                                         case DIV_S:         resultis DIV_F
151                                         default:            CaeReport (BadFloat)
152                                                             resultis c
153                                    $)
154 
155                     case '*'':
156                               Sym := CHARCONST_S
157                               goto Rstring
158                     case '"':
159                               Sym := STRINGCONST_S
160                     Rstring:  V!1, Vp := c, 1
161                               until Ch = c do
162                                    $(   if Ch = '**' do SaveCh ()
163                                         SaveCh ()
164                                         if Vp ge Vmax break
165                                    $)
166                               SaveCh ()
167                               V!0 := Vp
168                               resultis EnterIntoDictionary (V, Sym)
169                $)
170      $)
171 
172 and SaveCh () be              //  Subroutine to stash current character and get next.
173      $(   Vp := Vp + 1
174           if Vp ge Vmax do
175                $(   if Vp = Vmax do CaeReport (TokenTooLong, Vmax)              //  Trick to avoid repeating message.
176                     Vp := Vmax
177                $)
178           V!Vp := Ch
179           Rch ()
180      $)