Hi,

I am currently redesign my old compiler written in python by the use of 
pyl. The current code is attached.

First I want to explain the goal:

This compiler should create an AST which is used to translate a domain 
specific language in to some kind of assembler. Actual there are two 
elements given in the grammar:
1.) a comment
2.) global variable declaration

The global variable declaration can contain a list of variables. It is also 
allowed to write comments. A listing of the text can look like this:
"""
// comment 1

global {
    // comment 2
    integer a;
    integer a[2345];
    // comment 3
}
"""

I have some problems by defining the grammar rules. I give a short pseudo 
listing:

start :
 | startElement
 | start startElement

startElement : comment
startElement : global { varList }

varList :
 | varListElement
 | varList varListElement

varListElement : comment
varListElement : type name ;
varListElement: type name [ number ] ;

As you can see it is very simple. I did not understand the error (4 Shift / 
Reduce Erros). Maybe you can help me.

Thanks and have a nice weekend!
Stefan

-- 
You received this message because you are subscribed to the Google Groups 
"ply-hack" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ply-hack/559b5ca0-7f7c-4bf5-9711-581add0d035d%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
'''
Created on 20.08.2013

@author: StJ
'''
import argparse
import sys
import os
import ply.lex as lex
import ply.yacc as yacc
import ctypes
import struct

import re
import copy
import subprocess
import logging
import exceptions

#import APDB

# some global data

# a dict associate the functionID with the name and the list with parameters
gHALfidD = {
    None : ('unknown function', [])
    }

# a dict associate the variableID with a name 
gHALvidD = {
    None : ('unknown variable type',)
    }

# a dict with all basic i/o types
# data = (name, c type, endianness)
gBasicIOTypesD = {
    None : ('unknown basic i/o type', None, None)
    }

# a dict mapping c types to python types
gCTypeToPythonD = {
    'int' : int,
    'uint32_t' : int,
    'int32_t' : int,
    'raw' : int,
    'char' : int,
    'float' : float,
    }

# the basic AST class object
class ASTobject(object):
    def __init__(self, line ,column):
        self.line = line 
        self.column = column
    
    def __repr__ (self):
        return 'line:{line} column:{column}'.format(line=self.line,column=self.column)
    
# the basic AST comment class
class ASTcomment (ASTobject):
    def __init__(self, line, column, comment):
        super(ASTcomment, self).__init__(line ,column)
        self.comment = comment
    
    def __repr__ (self):
        return 'comment: "{comment}" at {pos}'.format(typeName=self.comment,pos=super(ASTobject,self).__repr__())


# the AST object for type defs
class ASTtypedef (ASTobject):
    def __init__(self, line ,column, typeName, typedefASTInstrL):
        super(ASTtypedef, self).__init__(line ,column)
        self.typeName = typeName
        self.typedefASTInstrL = typedefASTInstrL
    
    def __repr__ (self):
        return 'typedef of "{typeName}" at {pos}'.format(typeName=self.typeName,pos=super(ASTobject,self).__repr__())

# the AST object for subvalue defs at type defs    
class ASTtypedefInstr(ASTobject):
    def __init__(self, line ,column, subName, typeName):
        super(ASTtypedefInstr, self).__init__(line ,column)
        self.subName = subName
        self.typeName = typeName

    def __repr__ (self):
        return 'subvalue typedef of "{name}" from type "{type}" at {pos}'.format(name=self.subName,type=self.typeName, pos=super(ASTobject,self).__repr__())

# the AST type for a variable declaration
class ASTvariableDef(ASTobject):
    def __init__(self, line ,column, varName, varType, amount):
        super(ASTvariableDef, self).__init__(line ,column)
        self.varName = varName
        self.varType = varType
        self.amount = amount
        
    def __repr__ (self):
        return 'variable name:"{name}" with type:"{type}" and an amount of {amount} at {pos}'.format(name=self.subName,type=self.typeName,amount=self.amount, pos=super(ASTobject,self).__repr__())

# the AST type for function parameters
class ASTfuncParameter(ASTobject):
    def __init__(self, line ,column, varName, varType, ioType):
        super(ASTfuncParameter, self).__init__(line ,column)
        self.varName = varName
        self.varType = varType
        self.ioType = ioType
        
    def __repr__ (self):
        return 'function parameter name:"{name}" with type:"{type}" i/o:{io} at {pos}'.format(name=self.varName,type=self.varType,io=self.ioType, pos=super(ASTobject,self).__repr__())

class ASTinstructionParamConst (ASTobject):
    def __init__(self, line, column, Const, ConstType):
        super(ASTinstructionParamConst, self).__init__(line ,column)
        self.const = Const
        self.constType = ConstType
        
    def __repr__ (self):
        return 'const. instrParam value:"{const}" type:"{type}" at {pos}'.format(const=self.const,type=self.constType, pos=super(ASTobject,self).__repr__())

class ASTinstructionParamRefVar (ASTobject):
    def __init__(self, line, column, varRef, subValueRefList = [], index = 0):
        super(ASTinstructionParamRefVar, self).__init__(line ,column)
        self.varRef = varRef
        self.subValueRefList = subValueRefList
        self.index = index
        
    def __repr__ (self):
        refStr = ''
        for r in self.subValueRefList:
            refStr += '.'+ r
        return 'ref.Var. instrParam to variable:"{varRef}{refStr}[{index}]" at {pos}'.format(const=self.varRef,refStr=refStr, index=self.index, pos=super(ASTobject,self).__repr__())

    def addSubValue(self, sv):
        self.subValueRefList.append(sv)
    
    def setIndex (self, indx):
        self.index = indx
    
# the AST type for an instruction
class ASTinstruction(ASTobject):
    def __init__(self, line ,column, instrID, instrParamsL):
        super(ASTinstruction, self).__init__(line ,column)
        self.instrID = instrID
        self.instrParamsL = instrParamsL
        
    def __repr__ (self):
        paramLstr = ''
        j = 0
        for i in self.instrParamsL:
            if j != 0:
                paramLstr += ', '
            paramLstr += str(i)
            j+=1
        return 'instr.: {name}({params}) at {pos}'.format(name=gHALfidD[self.instrID][0],params=paramLstr, pos=super(ASTobject,self).__repr__())

# the AST type for an instruction
class ASTConditionalBlock(ASTinstruction):
    def __init__(self, line, column, condInstrList, TrueCode, FalseCode, loopFlag, loopExtraCode):
        super(ASTConditionalBlock, self).__init__(line ,column)
        self.condInstrList = condInstrList
        self.TrueCode = TrueCode
        self.FalseCode = FalseCode
        self.loopFlag = loopFlag
        self.loopExtraCode = loopExtraCode
        
    def __repr__ (self):
        return 'condition block at {pos}'.format(pos=super(ASTobject,self).__repr__())


# the AST type for an function call
class ASTinstructionFunctionCall(ASTinstruction):
    def __init__(self, line ,column, functionName, outputL, inputL):
        super(ASTinstructionFunctionCall, self).__init__(line ,column)
        self.functionName = functionName
        self.outputL = outputL
        self.inputL = inputL
        
    def __repr__ (self):
        paramLstr = '['
        j = 0
        for i in self.outputL:
            if j != 0:
                paramLstr += ', '
            paramLstr += str(i)
            j+=1
        paramLstr += '] {callF} ['.format(callF=self.functionName)
        j = 0
        for i in self.inputL:
            if j != 0:
                paramLstr += ', '
            paramLstr += str(i)
            j+=1
        paramLstr += '] at {pos}'.format(pos=super(ASTobject,self).__repr__())
        return paramLstr

# the AST type for an function call
class ASTvariableOperation(ASTinstruction):
    def __init__(self, line ,column, varOpName, ParamDict):
        super(ASTvariableOperation, self).__init__(line ,column)
        self.varOpName = varOpName
        self.ParamDict = ParamDict
        
    def __repr__ (self):
        paramLstr = '{varOpName} ['.format(varOpName=self.varOpName)
        i = 0
        for key, val in self.ParamDict.items():
            if (i != 0):
                paramLstr += ', '
            paramLstr += '{key}={val}'.format(key=key, val=val)
            i += 1 
        paramLstr += '] at {pos}'.format(pos=super(ASTobject,self).__repr__())
        return paramLstr


class ASTexpression(ASTobject):
    def __init__(self, line ,column, expType, expParamL):
        super(ASTexpression, self).__init__(line ,column)
        self.expType = expType
        self.expParamL = expParamL
        
    def __repr__ (self):
        paramLstr = 'expression {expType} on'.format(expType=self.expType)
        j = 0
        for e in self.expParamL:
            if j != 0:
                paramLstr += ' with '
            paramLstr += str(e)
            j+=1
        paramLstr += ' at {pos}'.format(pos=super(ASTobject,self).__repr__())
        return paramLstr
    


# the AST type for functions
class ASTfunction(ASTobject):
    def __init__(self, line ,column, fname, inpOutpL, localVarL, instructionL):
        super(ASTfunction, self).__init__(line ,column)
        self.fname = fname
        self.inpOutpL = inpOutpL
        self.localVarL = localVarL
        self.instructionL = instructionL

    def __repr__ (self):
        rStr = 'function definition of "{fname}" at {pos}'.format(fname=self.fname, pos=super(ASTobject,self).__repr__())
        rStr += '\n=========================================='
        rStr += '\nInputs / Outputs:'
        for e in self.inpOutpL:
            rStr += '\n\t{io}'.format(io=e)
        rStr = '\nLocal variables:'
        for e in self.localVarL:
            rStr += '\n\t{v}'.format(v=e)
        rStr = '\ninstructions:'
        for e in self.instructionL:
            rStr += '\n\t{instr}'.format(instr=e)
        rStr += '\n=========================================='

# the AST type for functions
class ASTmain(ASTobject):
    def __init__(self, line ,column, mainName, localVarL, instructionL):
        super(ASTmain, self).__init__(line ,column)
        self.mainName = mainName
        self.localVarL = localVarL
        self.instructionL = instructionL

    def __repr__ (self):
        rStr = 'main function definition of "{mainName}" at {pos}'.format(mainName=self.mainName, pos=super(ASTobject,self).__repr__())
        rStr += '\n=========================================='
        rStr = '\nLocal variables:'
        for e in self.localVarL:
            rStr += '\n\t{v}'.format(v=e)
        rStr = '\ninstructions:'
        for e in self.instructionL:
            rStr += '\n\t{instr}'.format(instr=e)
        rStr += '\n=========================================='


# setup
# def setup():
#     logging.info ('setup')
#     logging.info ('open database')
#     db = APDB.APDB('APdbCreate.sql','dbInit.xml')
#     
#     logging.info ('populate basic i/o type list')
#     dbBIOL = db.HAL_basicIOTypes_getList()
#     for (idHAL_IOTypesDefinition, TypeID, TypeName, description, cType, endianType, sizeInBytes) in dbBIOL:
#         gBasicIOTypesD[TypeID] = (TypeName, cType, endianType) 
#     
#     logging.info ('populate function HAL list')
#     dbfL = db.HAL_DefFunctions_getList()
#     for (fuuid, fid, fname, fdescr) in dbfL:
#         dbfpL = db.HAL_DefFunctions_getParamList(fid)
#         fpL = []
#         for (idHAL_FunctionsParameter, pfid, name, descr, idParameterClass, idParameterType) in dbfpL:
#             fpL.append((name, idParameterClass, idParameterType))
#         gHALfidD[fid] = (fname, fpL)
# 
#     logging.info ('populate variable HAL list')
#     dbvL = db.HAL_VariableDefinition_getList()
#     for (idHAL_VariableDefinition, VariableID, varName, description) in dbvL:
#         gHALvidD[VariableID] = (varName,)
#     logging.info ('setup finished')

# ==========================================================
# lets create the tokenizer
# ==========================================================

reserved = {
    'typedef'       :   'typedef',
    'global'        :   'global',
    'local'         :   'local',
    'code'          :   'code',
    'function'      :   'function',
    'interface'     :   'interface',
    'main'          :   'main',
    'if'            :   'if',
    'else'          :   'else',
    'for'           :   'for',
    'while'         :   'while',
    'checkButtonPressed': 'checkButtonPressed',
    'update'        :   'update',
    }
    
tokens = [
    'lBrace',
    'rBrace',
    'lSoftBrace',
    'rSoftBrace',
    'lBracket',
    'rBracket',
    'comma',
    'semicolon',
    'name',
    'iNumber',
    'fNumber',
    'arrowLeft',
    'arrowRight',
    'not',
    'add',
    'sub',
    'mul',
    'div',
    'nEqual',
    'equal',
    'assign',
    'comment',
    'less',
    'lessEqual',
    'more',
    'moreEqual',
    'inc',
    'dec',
    'string',
    'addAssign',
    'point'        
    ] + list(reserved.values())

t_lBrace = '{' 
t_rBrace = '}'
t_lSoftBrace = '\(' 
t_rSoftBrace = '\)'
t_lBracket = '\['
t_rBracket = '\]'
t_nEqual = '!='
t_equal = '=='
t_assign = '='
t_comma = ','
t_semicolon = ';' 
t_ignore = ' \t'
t_arrowLeft = '>>'
t_arrowRight = '<<'
t_not = '!'
t_div = '/'
t_mul = '\*'
t_lessEqual = '<='
t_less = '<'
t_moreEqual = '>='
t_more = '>'
t_inc = '\+\+'
t_add = '\+'
t_dec = '--'
t_sub = '-'
t_addAssign = '\+='
t_point = '\.'

def t_comment (t):
    r'(/\*(.|\n)*?\*/)|(//.*)'
    t.type = 'comment'
    l = len(t.value)
    if (t.value[0:2] == '//') :
        t.value = t.value[2:l]
    else :
        t.value = t.value[2:l-2]
    return t
    
def t_string (t):
    r'\"([^\\\n]|(\\.))*?\"'
    return t

def t_name(t):
    r'[a-zA-Z_][a-zA-Z0-9_]*'
    t.type = reserved.get(t.value,'name')    # Check for reserved words
    return t

def t_fNumber(t):
    r'[-+]?\d+\.\d+([eE][-+]?\d+)?'
    try:
        t.value = float(t.value)
    except ValueError:
        print("Integer value too large %d", t.value)
        t.value = 0
    return t

def t_iNumber(t):
    r'[-+]?\d+'
    try:
        t.value = int(t.value)
    except ValueError:
        print("Integer value too large %d", t.value)
        t.value = 0
    return t
    
# Define a rule so we can track line numbers
def t_newline(t):
    r'\n+'
    t.lexer.lineno += len(t.value)

def t_error(t):
    print("Illegal character '%s'" % t.value[0])
    t.lexer.skip(1)

# =====================================================
# the parser
# =====================================================

# Parsing rules
def p_startElements(p):
    """start :
        | startEle
        | start startEle"""

def p_startComment (p):
    'startEle : comment'
    p[0] = ASTcomment (p.lineno(1) ,p.lexpos(1), p[1])


def p_startGlobVar(p):
    'startEle : global lBrace varDeclList rBrace'
    p[0] = p[3]



def p_varDecl_Easy(p):
    'varDecl : name name semicolon'
    pass

def p_varDecl_Amount(p):
    'varDecl : name name lBracket iNumber rBracket semicolon'
    pass

def p_varDecl_Comment(p):
    'varDecl : comment'
    pass
    
def p_varDecl_list(p):
    """varDeclList :
        | varDecl
        | varDeclList varDecl"""
    pass

# error rule
def p_error(p):
    text = 'Syntax error at Line: {line} pos: {pos}'.format(line= p.lineno, pos=p.lexpos)
    raise exceptions.SyntaxError(text)

# reads a textfile into a buffer and return it
def readFile (filename):
    logging.info ('try to open file "{fn}"'.format(fn=filename))
    file = open(filename, 'r')
    logging.info ('read data')
    text = file.read()
    logging.info ('close file')
    file.close()
    return text


def main(argv):
    parser = argparse.ArgumentParser(description='the audio language compiler v. 0.2')
    parser.add_argument('-i', help='the audio language code input file')
    parser.add_argument('-o', help='the audio language assembler output dir', default=os.curdir)
    args = parser.parse_args()
    return (args.i, args.o)

if __name__ == '__main__':
    
    # setup logger
    logging.basicConfig(filename='ALClog.txt',filemode='w',format='%(name)s [%(levelname)s] : %(message)s',level=logging.DEBUG)
    logging.info ('start logger')

    # get cmdline arguments
    (iFile, oDir) = main(sys.argv[1:])
    
    # setup compiler
    #setup()
    
    # read AL file
#    try:
#    ALtxt = readFile(iFile)

ALtxt = """
// comment 1

global {
    // comment 2
    integer a;
    integer a[2345];
    // comment 3
}
"""
    # create lexer
    lexer = lex.lex()
    lexer.input(ALtxt)

    p = yacc.yacc(
        start='start',
        debugfile='ALC2dbg.txt',
        tabmodule='ALC2tab.txt'
    )
    
    res = p.parse(ALtxt,lexer=lexer)
    print res
    
#     except IOError as e:
#         print "I/O error({0}): {1}".format(e.errno, e.strerror)
#     except ValueError:
#         print "Could not convert data to an integer."
#     except TypeError as te:
#         print "type error "+str(te)
#     except:
#         print "Unexpected error:", sys.exc_info()[0]
#         raise
    
    
        
    pass

Reply via email to