//mparse.bcpl external [ // OS Resets; Wss; Wns; Puts; MoveBlock // Defined here ParseAddress; ParseTextList ] manifest[ BadToken = 1 SymbToken = 2 NumbToken = 3 LimitToken = 4 BlankToken = 5 CommaToken = 6 DotToken = 7 OtherToken = 8 ] let ParseAddress(TV, lvX, PV, lvY) = valof [ unless ParseSymbol(TV, lvX, PV, lvY) then resultis false unless ParseSign(TV, lvX, PV, lvY) then resultis false unless ParseNumb(TV, lvX, PV, lvY) then resultis false resultis true ] and ParseSymbol(TV, lvX, PV, lvY) = valof [ let TSize = nil SkipBlankToken(TV, lvX) switchon ChkToken(TV, rv lvX, lv TSize) into [ case SymbToken: case DotToken: resultis CopyToken(TV, lvX, PV, lvY, TSize) case BadToken: resultis false default: resultis CopyToken(TV, lvX, PV, lvY, 0) ] ] and ParseSign(TV, lvX, PV, lvY) = valof [ let TSize = nil SkipBlankToken(TV, lvX) switchon ChkToken(TV, rv lvX, lv TSize) into [ case OtherToken: resultis CopyToken(TV,lvX,PV,lvY, ((TV!(rv lvX) eq $+) logor (TV!(rv lvX) eq $-)) ? 1,0) case BadToken: resultis false default: resultis CopyToken(TV, lvX, PV, lvY, 0) ] ] and ParseNumb(TV, lvX, PV, lvY) = valof [ let TSize = nil SkipBlankToken(TV, lvX) switchon ChkToken(TV, rv lvX, lv TSize) into [ case NumbToken: resultis CopyToken(TV, lvX, PV, lvY, TSize) case BadToken: resultis false default: resultis CopyToken(TV, lvX, PV, lvY, 0) ] ] and ParseText(TV, lvX, PV, lvY) = valof [ SkipBlankToken(TV, lvX) for I = rv lvX to TV!0 do if TV!I eq $, then [ let Size = I - rv lvX resultis CopyToken(TV, lvX, PV, lvY, Size) ] let Size = (TV!0) - rv lvX + 1 resultis CopyToken(TV, lvX, PV, lvY, Size) ] and ParseTextList(TV, lvX, Pv, lvY) = valof [ while rv lvX le TV!0 do [ if not ParseText(TV, lvX, Pv, lvY) then resultis false if rv lvX le TV!0 then rv lvX = rv lvX + 1 // skip comma ] resultis true ] and SkipBlankToken(TV, lvX) be [ let TSize = nil unless ChkToken(TV, rv lvX, lv TSize) eq BlankToken then return rv lvX = rv lvX + TSize ] and CopyToken(TV, lvX, PV, lvY, Size) = valof [ let Y = rv lvY let X = rv lvX if Y + Size > PV!0 then resultis false PV!Y = Size MoveBlock(PV+Y+1,TV+X,Size) rv lvX = X + Size rv lvY = Y + Size + 1 resultis true ] and ChkToken(TV, X, lvSize) = valof [ let C = TV!X let L = TV!0 let Kind = BadToken let Size = 0 let J = nil test X>TV!0 ifso Kind = LimitToken ifnot test ($a le C & C le $z) % ($A le C & C le $Z) % (C eq $8) % (C eq $9) ifso Kind = SymbToken ifnot test ($0 le C logand C le $7) ifso Kind = NumbToken ifnot test C eq $, ifso Kind = CommaToken ifnot test C eq $ ifso Kind = BlankToken ifnot Kind = OtherToken switchon Kind into [ case SymbToken: case NumbToken: J = X + 1 while J le L do [ let Ch = TV!J if Ch eq $ % Ch eq $, then break if (Ch eq $+ % Ch eq $-) & ((J+1) le L) then if TV!(J+1) < $8 then break if Kind eq NumbToken then unless ($0 le Ch logand Ch le $7) do Kind = SymbToken if Ch eq $. then Kind = DotToken J = J + 1 ] Size = J - X; endcase case LimitToken: Size = 0; endcase case CommaToken: case OtherToken: Size = 1; endcase case BlankToken: J = X + 1 while J le L do [ if TV!J ne $ then break; J = J + 1] Size = J - X; endcase ] rv lvSize = Size resultis Kind ]