rev 572 - in trunk: pr/test src
SVN User <[email protected]> Fri, 04 Jun 2004 15:08:42 -0400
| Newsgroups | gmane.comp.lang.prothon.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: mark
Date: 2004-06-04 15:08:39 -0400 (Fri, 04 Jun 2004)
New Revision: 572
Modified:
trunk/pr/test/test.pr
trunk/src/builtins-string.c
trunk/src/interp.c
Log:
fixed binding permission bug 25
Modified: trunk/pr/test/test.pr
===================================================================
--- trunk/pr/test/test.pr 2004-06-04 18:56:19 UTC (rev 571)
+++ trunk/pr/test/test.pr 2004-06-04 19:08:39 UTC (rev 572)
@@ -1,725 +1,8 @@
#!/usr/bin/env prothon
-"""String format parser"""
+# chiter.pr
+BreakChars = 'abc'
-import Re as _re
-/*
-import gettext as _gettext
-import os.path as _path
-try:
- _MyDir, MyName = _path.split(__file__)
-except:
- _MyDir = '.'
-_LocalsDir = _path.join(_MyDir, 'locals')
-_TextDomain = 'formatparser'
-_gettext.bindtextdomain(_TextDomain, _LocalsDir)
-_gettext.textdomain(_TextDomain)
-_ = _gettext.gettext
-*/
+ich = BreakChars.iter_().next{}
-# Exception types.
-object FPParseError(ParseError):
- pass
-
-object FPIndexError(IndexError):
- pass
-
-object FPTypeError(TypeError):
- pass
-
-object Tokenizer:
- """Break a string into tokens"""
-
- def makeFactory(re):
- pat = _re.compile(re)
- def Factory(s='', psn=0, next=''):
- return self(pat, s, psn, next)
- Factory.regex = re
- return Factory{}
-
- def init_(pat, s='', psn=0, next='', end=None):
- self.pat = pat
- self.s = s
- if end is None:
- self.end = s.len()
- else:
- self.end = end
- self.psn = psn
- self.next = next
- self.rejected = False
-
- def synchronize(other):
- if not self is other:
- self.s = other.s
- self.psn = other.psn
- self.end = other.end
- self.next = other.next
-
- def nextToken():
- if self.rejected:
- self.rejected = False
- elif self.psn < self.end:
- m = self.pat.search(self.s, self.psn)
- if m is None:
- self.next = ''
- self.psn = self.end
- else:
- self.psn = m.end()
- self.next = self.s[m.start():self.psn]
-
- def reject():
- self.rejected = True
-
- def peekNextCh():
- if self.psn is not None:
- try:
- return self.s[self.psn]
- except IndexError:
- self.psn = None
- return ''
-
- def skipCh():
- self.psn += 1
-
- def isEnd():
- return self.psn >= self.end
-
- def clear():
- self.next = self.s = ''
- self.psn = self.end = 0
-
-# Regular expression stuff
-# Please udate the break table if any changes made here.
-#
-# Find specifiers within a format string.
-RegEx = r"[^%]+"
-RootTokenizer = Tokenizer.makeFactory(RegEx)
-
-# Break a specifier into tokens.
-# A tokens is one of:
-# - "'" delimited string
-# - positive integer preceded by '@'
-# - character sequence starting with '%',
-# not containing break characters or white space,
-# and optionally ending with '%'
-# - character sequence not containing white space
-# or break characters
-# - break character
-# Tokens can be any break character,
-# a "'" delimited string, a positive integer
-# preceded by a "@", an name starting with,
-# and optionally ending with, a '%',
-# or any character sequence not containing
-# a break character or whitespace.
-RegEx = (r"'(''|[^'])*'|" +
- r"@[0-9]+|" +
- r"%[^-\s%(),.@:'!=><+*/]*%?|" +
- r"[^-\s%(),.@:'!=><+*/]+|" +
- r"==|!=|>=|<=|" +
- r"[^\s]"
- )
-FormatTokenizer = Tokenizer.makeFactory(RegEx)
-del RegEx
-
-# Reserved characters in a specifier.
-# These form a break table.
-# Please modify the regular expressions if any
-# changes made here.
-BreakChars = r"%(),.@:'!=><+-*/"
-
-ich = BreakChars.iter_()
-Escape = ich.next() # Marks special names at format level
-ArgListStart = ich.next() # Encloses function arguments
-ArgListEnd = ich.next()
-ArgSep = ich.next() # Separates function arguments
-AttribRefOp = ich.next() # References an anttribute
-PositionOp = ich.next() # Starts a position indentifier
-ExprLitOp = ich.next() # Leaves an expression unevaluated
-Quote = ich.next() # Delimits a character string
-# Arithmetic / comparison operator primitives
-NotSign = ich.next()
-EqualSign = ich.next()
-GreaterThanSign = ich.next()
-LessThanSign = ich.next()
-PlusSign = ich.next()
-MinusSign = ich.next()
-TimesSign = ich.next()
-DivideSign = ich.next()
-del ich
-
-# Arithmetic / comparison operators
-EqualOp = EqualSign + EqualSign
-NotEqualOp = NotSign + EqualSign
-GreaterThanOp = GreaterThanSign
-GreaterThanOrEqualOp = GreaterThanSign + EqualSign
-LessThanOp = LessThanSign
-LessThanOrEqualOp = LessThanSign + EqualSign
-AdditionOp = PlusSign
-SubtractionOp = MinusSign
-MultiplicationOp = TimesSign
-DivisionOp = DivideSign
-
-object Node:
- """Abstract base type for parse tree node"""
-
- # Abstract methods.
- def parse(tokens):
- """Abstract parse method"""
- raise NameError #, \
- #"parse required for " + String(type(self))
-
- def eval(context=None):
- """Abstract eval method"""
- # Though most node subclasses implement eval, it is not required.
- # Catch unintensional calls.
- raise NameError #, \
- #"eval not implemented for " + String(type(self))
-
-object Tree(Node):
- """Abstract base type for none-leaf nodes"""
-
- # Default methods.
- def init_(tokens=None, parts=None):
- if parts is None:
- self.parts = []
- else:
- self.parts = list(parts)
- self.parse(tokens)
-
- def str_():
- return ''.join([String(p) for p in self.iterParts()])
-
- def addPart(part):
- self.parts.append(part)
-
- def iterParts(psn=0):
- return iter(self.parts[psn:])
-
- def getPart(idx):
- return self.parts[idx]
-
- def getParts(start):
- return self.parts[start:]
-
-object String(Node):
- """Wrap a string in a node-like object."""
- def init_(s):
- self.s = s
-
- def eval(*args):
- return self.s
-
- def str_():
- return self.s
-
-object QuotedString(String):
- """A quoted string"""
- def init_(tokens):
- super.init_(tokens.next[1:-1].replace(Quote*2, Quote))
- def str_():
- return (Quote +
- super.str_().replace(Quote, Quote*2) +
- Quote)
-
-object Keyword(String):
- """Keyword identifier node-like object"""
- def init_(s):
- super.init_(s)
-
- def eval(context):
- try:
- obj = context.getObject(self.s)
- except IndexError:
- raise FPIndexError #, \
- #fmt(_("Identifier %(s) not found"), s=self.s)
- return obj
-
- def getValue():
- return self.s
-
- def evalAttribute(obj, context):
- return context.getAttribute(obj, self.s)
-
-EmptyKeywordInstance = Keyword('')
-
-object IntegerLiteral(Node):
- """Wrap an integer in a node-like object"""
- def init_(i):
- self.i = i
-
- def eval(*args):
- return self.i
-
- def str_():
- return String(self.i)
-
-object ArgumentPosition(Node):
- """Argument position node-like object"""
- def init_(tokens):
- self.p = int(tokens.next[1:])
-
- def eval(context):
- return context.getObjectIdx(self.p)
-
- def str_():
- return PositionOp + String(self.p)
-
-def Identifier(tokens):
- """Return token as a node"""
- ch = tokens.next[0]
- if ch == PositionOp:
- node = ArgumentPosition(tokens)
- elif ch == Quote:
- node = QuotedString(tokens)
- elif ch == Escape:
- node = Keyword(tokens.next)
- elif ch in BreakChars:
- node = EmptyKeywordInstance
- tokens.reject()
- else:
- s = tokens.next
- try:
- node = IntegerLiteral(int(s))
- except ValueError:
- node = Keyword(s)
- return node
-
-# Accepts node in parts. Leaves token in next if any.
-object References(Tree):
- """Reference an identifier"""
-
- def parse(tokens):
- while tokens.next == AttribRefOp:
- tokens.nextToken()
- if tokens.isEnd():
- raise FPParseError #, \
- #_("Reference missing attribute keyword.")
- node = Identifier(tokens)
- if not isinstance(node, Keyword):
- raise FPParseError #, \
- #fmt(_("Require a keyword for attribute name: got '%(n)'"),
- # n=node)
- if node is EmptyKeywordInstance:
- raise FPParseError #, \
- #_("Require an attribute name: got nothing")
- tokens.nextToken()
- if tokens.next == ArgListStart:
- self.addPart(FunctionCall(tokens, [node]))
- tokens.nextToken()
- else:
- self.addPart(node)
-
- def eval(context):
- value = self.getPart(0).eval(context)
- for attr in self.iterParts(1):
- value = attr.evalAttribute(value, context)
- return value
-
- def str_():
- return AttribRefOp.join([String(p) for p in self.iterParts()])
-
-object ExpressionClosure:
- def init_(expr, context):
- self.expr = expr
- self.context = context
-
- def getValue():
- return self.expr.eval(self.context)
-
- def str_():
- return String(self.expr)
-
-# Accepts nothing. Leaves token in next, if any.
-object ExpressionLiteral(Tree):
- def parse(tokens):
- tokens.nextToken()
- if tokens.next == '':
- raise FPParseError #, \
- #_("Expecting an expression after a literal op.: got nothing")
- self.addPart(QuotedExpression(tokens))
-
- def eval(context):
- return ExpressionClosure(self.getPart(0), context)
-
- def str_():
- return ExprLitOp + String(self.getPart(0))
-
-object Negate(Node):
- def init_(node):
- self._node = node
- def eval(context):
- return context.doMethod(self._node.eval(context), '_minus_')
- def str_():
- return '-' + String(self._node)
-
-# Accepts token in tokens. Leaves token in next, if any.
-def FullIdentifier(tokens):
- if tokens.next == SubtractionOp:
- tokens.nextToken()
- if tokens.next is '':
- raise FPParseError #, \
- #_("Unexpected end-of-negation op.")
- node = FullIdentifier(tokens)
- if node is EmptyKeywordInstance:
- raise FPParseError #, \
- #_("Expected identifier after negation op.")
- node = Negate(node)
- else:
- node = Identifier(tokens)
- tokens.nextToken()
- if tokens.next == ArgListStart:
- node = FunctionCall(tokens, [node])
- tokens.nextToken()
- if tokens.next == AttribRefOp:
- node = References(tokens, [node])
- return node
-
-object BinaryOperator(Node):
- # To be defined by subclasses
- Op = ''
- Method = ''
- def getNode():
- raise NameError #, \
- #("BinaryOperator attribute getNode missing for %s" %
- # type(self))
-
- def init_(tokens, left, getNode):
- if left is EmptyKeywordInstance:
- raise FPParseError #, \
- #fmt(_("Expecting an expression before '%(s)' op."),
- # s=self.Op)
- self._left = left
- tokens.nextToken()
- if tokens.next == '':
- raise FPParseError #, \
- #fmt(_("Unexpected end of '%(s)' expression"),
- # s=self.Op)
- right = getNode(tokens)
- if right is EmptyKeywordInstance:
- raise FPParseError#, \
- #fmt(_("Expecting an expression after '%(s)' op."),
- # s=self.Op)
- self._right = right
-
- def eval(context):
- return context.doMethod(self._left.eval(context),
- self.Method,
- self._right.eval(context))
-
- def str_():
- return "%s %s %s" % (self._left, self.Op, self._right)
-
-object Divide(BinaryOperator):
- Op = DivisionOp
- Method = '_div_'
-
-object Multiply(BinaryOperator):
- Op = MultiplicationOp
- Method = '_mult_'
-
-# Accepts token in tokens. Leaves token in next, if any.
-def Multiplication(tokens):
- node = FullIdentifier(tokens)
- cont = True
- while cont:
- if tokens.next == MultiplicationOp:
- node = Multiply(tokens, node, FullIdentifier)
- elif tokens.next == DivisionOp:
- node = Divide(tokens, node, FullIdentifier)
- else:
- cont = False
- return node
-
-object Subtract(BinaryOperator):
- Op = SubtractionOp
- Method = '_sub_'
-
-object Add(BinaryOperator):
- Op = AdditionOp
- Method = '_add_'
-
-# Accepts token in tokens. Leaves token in next, if any.
-def Addition(tokens):
- node = Multiplication(tokens)
- cont = True
- while cont:
- if tokens.next == AdditionOp:
- node = Add(tokens, node, Multiplication)
- elif tokens.next == SubtractionOp:
- node = Subtract(tokens, node, Multiplication)
- else:
- cont = False
- return node
-
-object IsLessThanOrEqual(BinaryOperator):
- Op = LessThanOrEqualOp
- Method = '_le_'
-
-object IsLessThan(BinaryOperator):
- Op = LessThanOp
- Method = '_lt_'
-
-object IsGreaterThanOrEqual(BinaryOperator):
- Op = GreaterThanOrEqualOp
- Method = '_ge_'
-
-object IsGreaterThan(BinaryOperator):
- Op = GreaterThanOp
- Method = '_gt_'
-
-object IsNotEqual(BinaryOperator):
- Op = NotEqualOp
- Method = '_ne_'
-
-# Accepts node; returns token in next.
-object IsEqual(BinaryOperator):
- Op = EqualOp
- Method = '_eq_'
-
-# Accepts token in tokens. Leaves token in next, if any.
-def Comparison(tokens):
- node = Addition(tokens)
- if tokens.next == EqualOp:
- node = IsEqual(tokens, node, Addition)
- elif tokens.next == NotEqualOp:
- node = IsNotEqual(tokens, node, Addition)
- elif tokens.next == GreaterThanOp:
- node = IsGreaterThan(tokens, node, Addition)
- elif tokens.next == GreaterThanOrEqualOp:
- node = IsGreaterThanOrEqual(tokens, node, Addition)
- elif tokens.next == LessThanOp:
- node = IsLessThan(tokens, node, Addition)
- elif tokens.next == LessThanOrEqualOp:
- node = IsLessThanOrEqual(tokens, node, Addition)
- return node
-
-# Accepts token in tokens. Leaves token in next, if any.
-def QuotedExpression(tokens):
- """Reference an identifier"""
- if tokens.next == ExprLitOp:
- node = ExpressionLiteral(tokens)
- else:
- node = Comparison(tokens)
- return node
-
-# Accepts node in parts; ignores token in tokens;
-# leaves ArgListEnd in tokens.
-object FunctionCall(Tree):
- """Call a function"""
- def parse(tokens):
- if not isinstance(self.getPart(0), Keyword):
- raise FPParseError #, \
- #fmt(_("Function call requires keyword: got %(s)"),
- # s=self.getPart(0))
- while True:
- tokens.nextToken()
- if tokens.next == '':
- raise FPParseError #, _("Unexpected end of arg. list")
- node = QuotedExpression(tokens)
- if not tokens.next:
- raise FPParseError #, _("Unexpected end of arg. list")
- if tokens.next == ArgListEnd: # Loop test
- break
- if tokens.next == ArgSep:
- self.addPart(node)
- else:
- raise FPParseError #, \
- #fmt(_("Unexpected character %(c) in argument list"),
- # c=tokens.next[0])
- if node is not EmptyKeywordInstance:
- self.addPart(node)
-
- def eval(context):
- return context.doFunction(self.getPart(0).getValue(),
- *[arg.eval(context) for arg in self.iterParts(1)])
-
- def evalAttribute(obj, context):
- return context.doMethod(obj, self.getPart(0).getValue(),
- *[arg.eval(context) for arg in self.iterParts(1)])
-
- def str_():
- if self.getPart(-1) is EmptyKeywordInstance:
- term=ArgSep
- else:
- term=''
- return ("%s(%s%s)" %
- (String(self.getPart(0)),
- ArgSep.join([String(p) for p in self.iterParts(1)]),
- term))
-
-SpecifierTokens = FormatTokenizer() # Share with subtree node
-
-def Specifier(tokens):
- """Parse a single format specifier"""
- SpecifierTokens.synchronize(tokens)
- SpecifierTokens.nextToken()
- node = Identifier(SpecifierTokens)
- if SpecifierTokens.next == Escape or SpecifierTokens.next[-1] != Escape:
- SpecifierTokens.nextToken()
- if SpecifierTokens.next == ArgListStart:
- node = FunctionCall(SpecifierTokens, [node])
- else:
- raise FPParseError #, "Format specification missing arg. list."
- tokens.synchronize(SpecifierTokens)
- return node
-
-gen iterFormat(s):
- """Iterate over the specifier and non-specifier parts
- of a format."""
- tokens = RootTokenizer(s)
- while not tokens.isEnd():
- if tokens.peekNextCh() == Escape:
- yield Specifier(tokens)
- else:
- tokens.nextToken()
- yield String(tokens.next)
-
-object Context:
- """Execution environment of a specifier"""
-
- def init_(next, namedobjs=None, funcs=None, idxobjs=None):
- self._nxtgetObject = next.getObject
- if namedobjs is None or namedobjs.len() == 0: # None or empty map
- self._namedobjects = None
- self.getObject = next.getObject
- else:
- self._namedobjects = Dict(namedobjs)
- self._nxtdoFunction = next.doFunction
- if not funcs: # None or empty map
- self._functions = None
- self.doFunction = next.doFunction
- else:
- self._functions = Dict(funcs)
- self._nxtgetObjectIdx = next.getObjectIdx
- if not idxobjs:
- self._indexedobjects = None
- self.getObjectIdx = next.getObjectIdx
- else:
- self._indexedobjects = Tuple(idxobjs)
- self.getAttribute = next.getAttribute
- self.doMethod = next.doMethod
-
- # Default context interface methods;
- # may be overridden by instance versions.
- def getObject(name):
- try:
- obj = self._namedobjects[name]
- except IndexError:
- obj = self._nxtgetObject(name)
- return obj
-
- def getObjectIdx(idx):
- try:
- obj = self._indexedobjects[idx]
- except IndexError:
- obj = self._nxtgetObjectIdx(idx)
- return obj
-
- def doFunction(name, *args):
- try:
- fn = self._functions[name]
- except IndexError:
- return self._nxtdoFunction(name, *args)
- return fn(*args)
-
-# Foratter for internal user.
-object SimpleFormatter:
-
- def init_(map=None):
- self._recurselevel = 0
- if map is None:
- self._map = {}
- else:
- self._map = dict(map)
- self._map.update!({Escape: self._doFormat,
- '':None,
- Escape*2:Escape,
- '%sn%s' % (Escape, Escape): '\n'})
-
- def call_(*args, **kwds):
- """(fmt, id1=arg1, id2=arg2, ...) ==> string."""
- if self._recurselevel > 1:
- # We have a problem.
- return "fmt: %s\n" +
- "args: %s\n" +
- "kwds: %s\n" % (repr(args[0]), String(args[1:]), String(kwds))
- try:
- fmt = args[0]
- except IndexError:
- raise FMTTypeError #, \
- #fmt(_("Formatter() takes at least 1 argument (%(n) given)"),
- # n=args.len()
- try:
- for idx, arg in enumerate(args[1:]):
- kwds[idx] = arg
- except NameError:
- for idx in args.len()-1:
- kwds[idx] = args[idx+1]
-# for idx, arg in zip(range(args.len()-1), args[1:]):
-# kwds[idx] = arg
- # Join upgrades to unicode if one of the
- # sequence items is unicode.
- context = self.newContext(kwds)
- self._recurselevel += 1
- try:
- return ''.join([f.eval(context) for f in iterFormat(fmt)])
- finally:
- self._recurselevel -= 1
-
- # Context interface.
- def newContext(namedobjs=None, funcs=None, idxobjs=None):
- return Context(self, namedobjs, funcs, idxobjs)
-
- def getObject(obj):
- return self._map[obj]
-
- def getObjectIdx(idx):
- raise IndexError #, \
- #fmt(_("Argument index @%(i) out-of-range"), i=idx)
-
- def getAttribute(obj, attr):
- if attr == 'type':
- return type(obj)
- if attr == 'str':
- return String(obj)
- if attr == 'unicode':
- return unicode(obj)
- if attr == 'repr':
- return repr(obj)
- raise NameError #, \
- #fmt(_("Unsupported attribute %(attr)"), attr=attr)
- return '' # Never gets here
-
- def doFunction(name, *args):
- return self._map[name](*args)
-
- def doMethod(obj, attr, *args):
- if attr == 'center':
- if isinstance(obj, unicode):
- return obj.center(args[0])
- return String(obj).center(args[0])
- raise NameError #, \
- #fmt(_("Unsupported method %(attr)"), attr=attr)
- return '' # Never gets here
-
- def close():
- pass
-
- # Formatting function.
- def _doFormat(obj, width=None, precision=None):
- s = String(obj)
- if not precision:
- if not width:
- return s
- return "%*s" % (width, s)
- if not width:
- return "%.*s" % (precision, s)
- return "%*.*s" % (width, precision, s)
-
-object fmt(SimpleFormatter): pass
-fmt.init_()
-
-print "Starting test now"
-print fmt("Version 0.4.3")
-print fmt("The value of pi to %(p) decimal places is %(pi,,p) .",
- pi=3.141592658, p=4)
\ No newline at end of file
+print ich(), ich(), ich()
Modified: trunk/src/builtins-string.c
===================================================================
--- trunk/src/builtins-string.c 2004-06-04 18:56:19 UTC (rev 571)
+++ trunk/src/builtins-string.c 2004-06-04 19:08:39 UTC (rev 572)
@@ -367,15 +367,6 @@
return res;
}
-DEF(String, iter_, NULL) {
- obj_p gen_obj = NEW_OBJ(StringGen_OBJ);
- BIN_CONTENT_CHK(String);
- gen_obj->data_type = DATA_TYPE_DATAPTR;
- gen_obj->data.ptr = pr_strptr(self);
- set_attr(ist, gen_obj, sym(ist, "saved_string"), self);
- return gen_obj;
-}
-
DEF(String, ord, NULL) {
BIN_CONTENT_CHK(String);
return NEW_INT((int)(*pr_strptr(self)));
@@ -732,6 +723,17 @@
return list_obj;
}
+DEF(String, iter_, NULL) {
+ obj_p gen_obj;
+ BIN_CONTENT_CHK(String);
+ gen_obj = NEW_OBJ(StringGen_OBJ);
+ gen_obj->data_type = DATA_TYPE_DATAPTR;
+ gen_obj->data.ptr = pr_strptr(self);
+ set_attr(ist, gen_obj, sym(ist, "savedString"), self);
+ return gen_obj;
+}
+
+
DEF(String, cDataLen_, NULL) {
BIN_CONTENT_CHK(String);
return NEW_INT(sizeof(pr_str_t) + pr_strlen(self) + 1);
Modified: trunk/src/interp.c
===================================================================
--- trunk/src/interp.c 2004-06-04 18:56:19 UTC (rev 571)
+++ trunk/src/interp.c 2004-06-04 19:08:39 UTC (rev 572)
@@ -1172,7 +1172,10 @@
if (!(bindee = fr_stack[fr_sp+2])) bindee = fr_stack[fr_sp];
obj = get_item(ist, fr_stack[fr_sp], fr_stack[fr_sp+1]); IF_EXC_BREAK;
bound_meth = copy_object(ist, obj);
- set_attr(ist, bound_meth, SYM(BINDOBJ_), bindee); IF_EXC_BREAK;
+ su(i);
+ set_attr(ist, bound_meth, SYM(BINDOBJ_), bindee);
+ un_su(i);
+ IF_EXC_BREAK;
fr_push(bound_meth);
} break;
case OP_OBJCALL: {