0

I'm trying to parse a user input that each word/name/number gets seperated by whitespace (except for strings which are defined by double quotes) and gets pushed into a list. The list gets printed along the way. I previously made a version of this code but this time I want to used Tokens to make things cleaner. Here's what I have so far but it's not printing anything.

    #!/util/bin/python
import re


def main ():


    for i in tokenizer('abcd xvc  23432 "exampe" 366'):
        print (i);



    tokens = (
  ('STRING', re.compile('"[^"]+"')),  # longest match
  ('NAME', re.compile('[a-zA-Z_]+')),
  ('SPACE', re.compile('\s+')),
  ('NUMBER', re.compile('\d+')),
)


def tokenizer(s):
  i = 0
  lexeme = []
  while i < len(s):
    match = False
    for token, regex in tokens:
      result = regex.match(s, i)
      if result:
        lexeme.append((token, result.group(0)))
        i = result.end()
        match = True
        break
    if not match:
      raise Exception('lexical error at {0}'.format(i))
  return lexeme




  main()

2 Answers 2

2

I suggest to use the shlex module for breaking up quoted string:

>>> import shlex
>>> s = 'hello "quoted string" 123   \'More quoted string\' end'
>>> s
'hello "quoted string" 123   \'More quoted string\' end'
>>> shlex.split(s)
['hello', 'quoted string', '123', 'More quoted string', 'end']

After that, you can classify all your tokens (string, number, ...) as you want. The only thing you are missing is space: shlex does not care about space.

Here is a simple demo:

import shlex

if __name__ == '__main__':
    line = 'abcd xvc  23432 "exampe" 366'
    tokens = shlex.split(line)
    for token in tokens:
        print '>{}<'.format(token)

Output:

>abcd<
>xvc<
>23432<
>exampe<
>366<

Update

If you insist on not stripping the quote marks, then call split() with posix=False:

    tokens = shlex.split(line, posix=False)

Output:

>abcd<
>xvc<
>23432<
>"exampe"<
>366<
Sign up to request clarification or add additional context in comments.

3 Comments

So for that demo it will print the line without the space characters? @Hai Vu
I updated my solution and you can see there is no space before or after each token.
Ok got that but I think that it also strips away the double quotes (") if there is a string. How do I concatenate the quote back on? @Hai Vu
1

I think your indentation is broken, this:

#!/util/bin/python
import re

tokens = (
  ('STRING', re.compile('"[^"]+"')),  # longest match
  ('NAME', re.compile('[a-zA-Z_]+')),
  ('SPACE', re.compile('\s+')),
  ('NUMBER', re.compile('\d+')),
)


def main ():

  for i in tokenizer('abcd xvc  23432 "exampe" 366'):
    print (i);


def tokenizer(s):
  i = 0
  lexeme = []
  while i < len(s):
    match = False
    for token, regex in tokens:
      result = regex.match(s, i)
      if result:
        lexeme.append((token, result.group(0)))
        i = result.end()
        match = True
        break
    if not match:
      raise Exception('lexical error at {0}'.format(i))
  return lexeme


main()

prints:

('NAME', 'abcd')
('SPACE', ' ')
('NAME', 'xvc')
('SPACE', '  ')
('NUMBER', '23432')
('SPACE', ' ')
('STRING', '"exampe"')
('SPACE', ' ')
('NUMBER', '366')

2 Comments

Yes that was it thanks. But also I want it to push it to a list without pushing the space
Use shlex and you don't have to worry about space. See my solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.