# NeWS parser. # Don Hopkins # Data types # simple # boolean fontID integer mark name null operator real save # composite # array dictionary file gstate packedarray string # # attributes # executable bit: literal or executable # access bits: unlimited, read-only, execute-only, none # attributes are properties of the object (reference) not its value, except for dictionaries # # arrays # shared sub-structure to support getinterval # packed arrays # # dictionares # can't have null as keys # # strings # shared sub-structure to support getinterval # # two slashes before a name to inline its binding # # NeWS supports characters with high bits binding to system and user objects # # end of line handling rules, line continuation, cr, lf and cr/lf handling # # files # %stdin %stdout %statementedit %lineedit %socket # r w a r+ w+ a+ def getchar(): return None def ungetchar(c): pass def remember(c): pass def iseof(c): return c is None def ishigh(c): return ord(c) > 127 def iseol(c): return c == '\n' def iswhite(c): return c in '\0\t\n\f\r ' # defined in red book def isdelim(c): return c in '()<>[]{}/%' # defined in red book def token(): # Skip spaces and comments. while True: c = getchar() # If comment, then skip until end of line or end of file. if c == '%': while True: c = getchar() if (iseol(c) or iseof(c)) break # If not space or high bit set. if ((not isspace(c)) or ishigh(c)): break if not ishigh(c): if ((c == '[') or (c == ']')): # array # [ and ] are self delimiting name objects that bind to operators, not punctuation elif c == '(': # parse string # literal (string) # parens nest, newlines allowed, \ escapes, \n \r \t \b \f \\ \( \) \ddd (octal character code) # line continuation: \ at end of line ignores \ and newline # base-85 <~WXYZ~> (level 2) elif c == '<': # hex <1234> # if final hex digit is missing, then assume a 0 # dictionary <> (level 2) # << and >> are self delimiting name objects that bind to operators, not punctuation elif c == '{': # begin brace # self delimiting elif c == '}': # end brace # self delimiting elif c == '/': # slash else: if ishigh(c): ungetchar(c) else: # names may begin with digits as long as they are not numbers while True: remember(c) c = getchar() if c <= ' ': break if isdelim(c): ungetchar(c) break if memory() <= '9': # parse number # integer 123 -98 43455 0 +17 # float -.002 34.5 -3.62 123.6e10 1E-5 -1. 0.0 1E6 1.0E6 1.0E-6 # radix 8#1777 16#FFFE 2#1000, base is 2-36, digits are 0-9 a-z A-Z