stdin - Program does not accept argument Python -


i creating postfix calculator accepts arithmetic expressions , first pushes operators stacl.

./pythonfilename 3 4 1 + - used input. however, since no output displayed, tried debug program see why program not taking in argument. not result in printing output. hit ctrl+c display traceback call , points out x = sys.stdin.readlines.

#!/usr/bin/python  import sys import fileinput  class stack:     def __init__(self):         self.items = []      def isempty(self):         return self.items == []      def push(self,item):         self.items.append(item)      def pop(self):         return self.items(pop)      def peek(self):         return self.items[len(self.items)-1]      def size(self):         return len(self.items)      def is_number(line):         try:             float(line)         except valueerror:             return false          def infixtopostfix():     initstack=stack()     x = sys.stdin.readlines() #read user input      lines in x:#for lines in fileinput.input():         line in lines.strip().split(" "):             if is_number(line):                 initstack.push(line)                 line = float(line)             elif line =='+':                 firstnum = initstack.pop()                 secnum = initstack.pop()                 result = firstnum + secnum                 initstack.push(result)                 print initstack.peek()                            elif line == '-':                 firstnum = initstack.pop()                 secnum = initstack.pop()                 result = firstnum - secnum                 initstack.push(result)                 print initstack.peek()              elif line == '*':                 firstnum = initstack.pop()                 secnum = initstack.pop()                 result = firstnum * secnum                 initstack.push(result)                 print initstack.peek()             elif line == "/":                 firstnum = initstack.pop()                 secnum = initstack.pop()                 result = firstnum / secnum                 initstack.push(result)                 print initstack.peek()             elif line == "%":                 firstnum = initstack.pop()                 secnum = initstack.pop()                 result = firstnum % secnum                 initstack.push(result)                 print initstack.peek()  infixtopostfix() 

the standard way read pipe (cat ... | python myprog.py) is

import sys  line in sys.stdin:     print ">", line 

line here include final '\n'

if instead want take arguments on command line (python myprog.py 3 4 1 + -), use sys.argv[1:] (sys.argv[0] contains myprog.py).

to consistent lexing of input need first check sys.argv , split sys.stdin:

def lex_input():     "returns list of tokens."     tokens = []     if len(sys.argv) > 1:         tokens = sys.argv[1:]     else:         line in sys.stdin:             tokens += line.split()     return tokens 

then need change infixpostfix() function use token-array (instead of doing both parsing , evaluation in same function).

ps: more succinct way of writing individual clauses be:

elif token == '+':     push(pop() + pop()) 

but depends on you're trying accomplish..

update: full'ish solution

update2: debug statements visualize stack (removed stack class in favor of regular list brevity)

import sys  stack = [] push = stack.append pop = stack.pop  operations = {     '+': lambda b, a: + b,     '-': lambda b, a: - b,     '*': lambda b, a: b * a,     '/': lambda b, a: b / a, }  def infixtopostfix(tokens):     print '%-15s %5s %-15s' % ('stack before', 'token', 'stack after')     print '-'*15, '-'*5, '-'*15      token in tokens:         print '%15s %5r' % (stack, token),          if token not in operations:             push(int(token))         else:             push(operations[token](pop(), pop()))          print '%15s' % stack  def lex_input():     "returns list of tokens."     tokens = []     if len(sys.argv) > 1:         tokens = sys.argv[1:]     else:         line in sys.stdin:             tokens += line.split()     return tokens  if __name__ == "__main__":     infixtopostfix(lex_input())     # formed programs should leave single value on stack     print "\nresult is:", stack[0] 

testing:

(dev) go|c:\srv> python rpn.py 3 4 1 + - stack before    token stack after --------------- ----- ---------------              []   '3'             [3]             [3]   '4'          [3, 4]          [3, 4]   '1'       [3, 4, 1]       [3, 4, 1]   '+'          [3, 5]          [3, 5]   '-'            [-2]  result is: -2 

(cat rpn.txt | python rpn.py output same thing if rpn.txt contains 3 4 1 + -).

if try rpn program syntax error, program raise exception, e.g.:

(dev) go|c:\srv> python rpn.py 3 4 + - stack before    token stack after --------------- ----- ---------------              []   '3'             [3]             [3]   '4'          [3, 4]          [3, 4]   '+'             [7]             [7]   '-' traceback (most recent call last):   file "rpn.py", line 60, in <module>     infixtopostfix(lex_input())   file "rpn.py", line 45, in infixtopostfix     push(operations[token](pop(), pop()))   file "rpn.py", line 26, in pop     return stack.pop() indexerror: pop empty list 

in real compiler bad, since don't want end user see details of implementation. instead you'd want give them diagnostic error message, exact place program found it.

in case isn't difficult. i've omitted debug statements print stack:

def infixtopostfix(tokens):     # make copy of input, use in error handling     input_tokens = tokens[:]       try:         i, token in enumerate(tokens):             if token not in operations:                 push(int(token))             else:                 push(operations[token](pop(), pop()))     except indexerror:         print 'detected syntax error @ token no.:', + 1  # people count 1..         print ' '.join(input_tokens)         print '%s%s' % ('-' * (1 + len(' '.join(input_tokens[:i]))), '^')         push('syntax error')  # top of stack contains result of current operation.. 

a small change result printing necessary, printing last element in list (stack[-1]) top of stack instead of relying on list/stack having 1 element @ end:

if __name__ == "__main__":     infixtopostfix(lex_input())     # formed programs should leave single value on stack     print "\nresult is:", stack[-1] 

if feed version our program syntax error:

(dev) go|c:\srv> python rpn.py 34 4 + - detected syntax error @ token no.: 4 34 4 + - -------^  result is: syntax error 

we proper error message, little pointy 'graphic' indicating error detected.

we go further since know of our operations take 2 elements on stack, , give more detailed error message, e.g.:

syntax error @ token "-":  stack underflow    "-" operation requires 2 stack arguments , stack     contained one:          stack      token         ---------- -----         [37]        '-' 

i'll leave implementation of exercise.

as can see, in simple example there more error handling code evaluation code , isn't surprising when writing simple compilers.


Comments

Popular posts from this blog

matlab - error with cyclic autocorrelation function -

django - (fields.E300) Field defines a relation with model 'AbstractEmailUser' which is either not installed, or is abstract -

c# - What is a good .Net RefEdit control to use with ExcelDna? -