Source code for parseidf

"""
parseidf.py

parses an idf file into a dictionary of lists in the following manner:

    each idf object is represented by a list of its fields, with the first field
    being the objects type.

    each such list is appended to a list of objects with the same type in the
    dictionary, indexed by type:

    { [A] => [ [A, x, y, z], [A, a, b, c],
      [B] => [ [B, 1, 2], [B, 1, 2, 3] }

    also, all field values are strings, i.e. no interpretation of the values is made.

.. note:: Use eppy instead!
"""
import ply.lex as lex
import ply.yacc as yacc

# list of token names
tokens = (
        'VALUE',
        'COMMA',
        'SEMICOLON',
)

# regular expression rules for simple tokens
t_COMMA = r'[ \t]*,[ \t]*'
t_SEMICOLON = r'[ \t]*;[ \t]*'

# ignore comments, tracking line numbers at the same time
[docs]def t_COMMENT(t): r'[ \t\r\n]*!.*' newlines = [n for n in t.value if n == '\n'] t.lineno += len(newlines) pass
# No return value. Token discarded # Define a rule so we can track line numbers
[docs]def t_newline(t): r'[ \t]*(\r?\n)+' t.lexer.lineno += len(t.value)
[docs]def t_VALUE(t): r'[ \t]*([^!,;\n]|[*])+[ \t]*' return t
# Error handling rule
[docs]def t_error(t): raise SyntaxError("Illegal character '%s' at line %d of input" % (t.value[0], t.lexer.lineno)) t.lexer.skip(1)
# define grammar of idf objects
[docs]def p_idffile(p): 'idffile : idfobjectlist' result = {} for idfobject in p[1]: name = idfobject[0] result.setdefault(name.upper(), []).append(idfobject) p[0] = result
[docs]def p_idfobjectlist(p): 'idfobjectlist : idfobject' p[0] = [p[1]]
[docs]def p_idfobjectlist_multiple(p): 'idfobjectlist : idfobject idfobjectlist' p[0] = [p[1]] + p[2]
[docs]def p_idfobject(p): 'idfobject : objectname SEMICOLON' p[0] = [p[1]]
[docs]def p_idfobject_with_values(p): 'idfobject : objectname COMMA valuelist SEMICOLON' p[0] = [p[1]] + p[3]
[docs]def p_objectname(p): 'objectname : VALUE' p[0] = p[1].strip()
[docs]def p_valuelist(p): 'valuelist : VALUE' p[0] = [p[1].strip()]
[docs]def p_valuelist_multiple(p): 'valuelist : VALUE COMMA valuelist' p[0] = [p[1].strip()] + p[3]
# oh, and handle errors
[docs]def p_error(p): raise SyntaxError("Syntax error in input on line %d" % lex.lexer.lineno)
[docs]def parse(input): ''' parses a string with the contents of the idf file and returns the dictionary representation. ''' lexer = lex.lex(debug=False) lexer.input(input) parser = yacc.yacc() result = parser.parse(debug=False) return result