1    	package acl2s.lib.parse.obj;
2    	
3    	import java.math.BigInteger;
4    	
5    	import acl2s.lib.parse.ObjectNotSupported;
6    	import acl2s.lib.parse.IParseContext;
7    	import acl2s.lib.parse.ParseException;
8    	import acl2s.lib.parse.Parser;
9    	import acl2s.lib.parse.RealFns;
10   	import acl2s.lib.parse.StringParser;
11   	import acl2s.lib.parse.SymOrNumFns;
12   	
13   	public abstract class IntOrRat extends Num {
14   		/**
15   		 * 
16   		 */
17   		private static final long serialVersionUID = -8985321361858651937L;
18   	
19   		public abstract double doubleApprox();
20   		
21   		public abstract IntOrRat invert();
22   	
23   		public abstract IntOrRat negate();
24   		
25   		public abstract boolean lessThan(IntOrRat r);
26   		
27   		public static IntOrRat parse(Parser p) throws ParseException {
28   			IParseContext pc = p.getContext();
29   			int radix = pc == null ? 10 : pc.getReadBase();
30   			boolean inMacro = false;
31   			
32   			char c = p.peek();
33   			if (c == '#') {
34   				p.skip();
35   				c = p.pop();
36   				switch (c) {
37   				case '0':
38   				case '1':
39   				case '2':
40   				case '3':
41   				case '4':
42   				case '5':
43   				case '6':
44   				case '7':
45   				case '8':
46   				case '9':
Event example: Example of checking the function's return value.
Also see events: [check_return][example][example][example][example]
47   					char d = p.pop();
48   					if (Character.isDigit(d)) {
49   						char e = p.pop();
50   						if (e != 'r' && e != 'R') {
51   							throw new ParseException("Expected 1-2 digit radix followed by R, e.g. #16R42.");
52   						}
53   						radix = 10 * (c - '0') + (d - '0');
54   					} else {
55   						if (d != 'r' && d != 'R') {
56   							throw new ParseException("Expected 1-2 digit radix followed by R, e.g. #16R42.");
57   						}
58   						radix = (c - '0');
59   					}
60   					if (radix > 36 || radix < 2) {
61   						throw new ParseException("Radix must be from 2 to 36, e.g. #16R42.");
62   					}
63   					inMacro = true;
64   					break;
65   				case 'b':
66   				case 'B':
67   					radix = 2;
68   					inMacro = true;
69   					break;
70   				case 'o':
71   				case 'O':
72   					radix = 8;
73   					inMacro = true;
74   					break;
75   				case 'x':
76   				case 'X':
77   					radix = 16;
78   					inMacro = true;
79   					break;
80   				case 'r':
81   				case 'R':
82   					throw new ParseException("Expected 1-2 digit radix before the R, e.g. #16R42.");
83   				default:
84   					throw new ParseException("Unrecognized #-sequence for number.");
85   				}
86   			}
87   			return parseNonMacroPart(p, radix, inMacro);
88   		}
89   		
90   		public static IntOrRat parseNonMacroPart(Parser p, int radix, boolean inMacro) throws ParseException {
91   			boolean negative = false;
92   			boolean isFloat = false;
93   			Object saved = p.save();
94   			char c = p.pop();
95   			try {
96   				if (c == '-') {
97   					negative = true;
98   					c = p.pop();
99   				} else if (c == '+') {
Event example: Example of checking the function's return value.
Also see events: [check_return][example][example][example][example]
100  					c = p.pop();
101  				}
102  				BigInteger v1 = BigInteger.ZERO;
103  				BigInteger v2 = BigInteger.ZERO;
104  				int digit;
105  				if (c != '.') {
106  					digit = RealFns.getDigit(c);
107  					if (digit < 0) {
108  						throw new ParseException("At least one digit needed in number.");
109  					}
110  					if (digit >= radix) {
111  						throw new ParseException("Invalid digit for radix " + radix + " number.");
112  					}
113  					v1 = BigInteger.valueOf(digit);
114  					c = p.peek();
115  					digit = RealFns.getDigit(c);
116  					while (digit >= 0) {
117  						if (digit >= radix) {
118  							throw new ParseException("Invalid digit for radix " + radix + " number.");
119  						}
120  						v1 = v1.multiply(BigInteger.valueOf(radix)).add(BigInteger.valueOf(digit));
121  						c = p.next();
122  						digit = RealFns.getDigit(c);
123  					}
124  					if (negative) {
125  						v1 = v1.negate();
126  					}
127  					if (SymOrNumFns.isTerminator(c)) {
128  						return Int.create(v1);
129  					}
130  					if (c == '.' && SymOrNumFns.isTerminator(p.peek(1))) {
131  						if (radix != 10) {
132  							p.restore(saved);
133  							return parseNonMacroPart(p, 10, inMacro);
134  						}
135  						p.skip();
136  						return Int.create(v1);
137  					}
138  					if (RealFns.tryFloatExpt(p)) {
139  						RealFns.floatThrow();
140  					}
141  					if (c == '.') {
142  						isFloat = true;
143  					} else if (c != '/') {
144  						throw new ParseException("Invalid character in number.");
145  					}
146  					c = p.next();
147  				} else { // c == '.' and no preceding digits
148  					isFloat = true;
149  					c = p.peek();
150  					digit = RealFns.getDigit(c);
151  					if (digit < 0) {
152  						throw new ParseException("Invalid floating-point number.");
153  					}
154  				}
155  				digit = RealFns.getDigit(c);
156  				while (digit >= 0) {
157  					if (digit >= radix) {
158  						if (isFloat) {
159  							break;
160  						} else {
161  							throw new ParseException("Invalid digit for radix " + radix + " number.");
162  						}
163  					}
164  					v2 = v2.multiply(BigInteger.valueOf(radix)).add(BigInteger.valueOf(digit));
165  					c = p.next();
166  					digit = RealFns.getDigit(c);
167  				}
168  				if (isFloat) {
169  					/*(void)*/RealFns.tryFloatExpt(p);
170  					c = p.peek();
171  					if (SymOrNumFns.isTerminator(c)) {
172  						if (inMacro) {
173  							throw new ParseException("Non-rational in radix macro.");				
174  						} else {
175  							RealFns.floatThrow(); // terminal
176  						}
177  					}
178  				} else if (SymOrNumFns.isTerminator(c)) {
179  					return Rat.create(v1,v2);
180  				}
181  				throw new ParseException("Invalid character in number.");
182  			} catch (ObjectNotSupported ons) {
183  				throw ons;
184  			} catch (ParseException pe) {
185  				p.restore(saved);
186  				// also, as side effect below, skips to terminator
187  				if (RealFns.isPotentialNumber(p,radix) && !inMacro) {
188  					throw new ObjectNotSupported("Potential numbers (CLTL 22.1.2) are reserved.  Use || to make a symbol.");
189  				} else {
190  					throw pe;
191  				}
192  			}
193  		}
194  		
195  		public static void main(String[] args) throws ParseException {
196  			for (String s : args) {
197  				System.out.println(parse(new StringParser(null, s)));
198  			}
199  		}
200  	}