Commit 0daf32df authored by Alexander Shiryaev's avatar Alexander Shiryaev
Browse files

Oberon-0 added

parent 01964801
# Alexander Shiryaev, 2011
import Scanner
import Parser
def Process (s):
scanner = Scanner.Scanner(s)
parser = Parser.Parser()
Parser.Errors.Init('', '', True, parser.getParsingPos, parser.errorMessages)
Parser.Errors.errors = []
Parser.Errors.count = 0
parser.Parse(scanner)
Parser.Errors.Summarize(scanner.buffer)
return tuple( [ (e.line, e.col, e.str) for e in Parser.Errors.errors ] )
#-------------------------------------------------------------------------
#Parser.py -- ATG file parser
#Compiler Generator Coco/R,
#Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
#extended by M. Loeberbauer & A. Woess, Univ. of Linz
#ported from Java to Python by Ronald Longo
#
#This program is free software; you can redistribute it and/or modify it
#under the terms of the GNU General Public License as published by the
#Free Software Foundation; either version 2, or (at your option) any
#later version.
#
#This program is distributed in the hope that it will be useful, but
#WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
#for more details.
#
#You should have received a copy of the GNU General Public License along
#with this program; if not, write to the Free Software Foundation, Inc.,
#59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#As an exception, it is allowed to write an extension of Coco/R that is
#used as a plugin in non-free software.
#
#If not otherwise stated, any source code generated by Coco/R (other than
#Coco/R itself) does not fall under the GNU General Public License.
#-------------------------------------------------------------------------*/
import sys
from Scanner import Token
from Scanner import Scanner
from Scanner import Position
Trace = False
class ErrorRec( object ):
def __init__( self, l, c, s ):
self.line = l
self.col = c
self.num = 0
self.str = s
class Errors( object ):
errMsgFormat = "file %(file)s : (%(line)d, %(col)d) %(text)s\n"
eof = False
count = 0 # number of errors detected
fileName = ''
listName = ''
mergeErrors = False
mergedList = None # PrintWriter
errors = [ ]
minErrDist = 2
errDist = minErrDist
# A function with prototype: f( errorNum=None ) where errorNum is a
# predefined error number. f returns a tuple, ( line, column, message )
# such that line and column refer to the location in the
# source file most recently parsed. message is the error
# message corresponging to errorNum.
@staticmethod
def Init( fn, dir, merge, getParsingPos, errorMessages ):
Errors.theErrors = [ ]
Errors.getParsingPos = getParsingPos
Errors.errorMessages = errorMessages
Errors.fileName = fn
listName = dir + 'listing.txt'
Errors.mergeErrors = merge
if Errors.mergeErrors and Trace:
try:
Errors.mergedList = open( listName, 'w' )
except IOError:
raise RuntimeError( '-- Compiler Error: could not open ' + listName )
@staticmethod
def storeError( line, col, s ):
if Errors.mergeErrors:
Errors.errors.append( ErrorRec( line, col, s ) )
else:
Errors.printMsg( Errors.fileName, line, col, s )
@staticmethod
def SynErr( errNum, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
msg = Errors.errorMessages[ errNum ]
Errors.storeError( line, col, msg )
Errors.count += 1
@staticmethod
def SemErr( errMsg, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
Errors.storeError( line, col, errMsg )
Errors.count += 1
@staticmethod
def Warn( errMsg, errPos=None ):
line,col = errPos if errPos else Errors.getParsingPos( )
Errors.storeError( line, col, errMsg )
@staticmethod
def Exception( errMsg ):
print errMsg
assert False
@staticmethod
def printMsg( fileName, line, column, msg ):
vals = { 'file':fileName, 'line':line, 'col':column, 'text':msg }
sys.stdio.write( Errors.errMsgFormat % vals )
@staticmethod
def display( s, e ):
assert Trace
Errors.mergedList.write('**** ')
for c in xrange( 1, e.col ):
if s[c-1] == '\t':
Errors.mergedList.write( '\t' )
else:
Errors.mergedList.write( ' ' )
Errors.mergedList.write( '^ ' + e.str + '\n')
@staticmethod
def Summarize( sourceBuffer ):
if Errors.mergeErrors:
# Initialize the line iterator
srcLineIter = iter(sourceBuffer)
srcLineStr = srcLineIter.next( )
srcLineNum = 1
try:
# Initialize the error iterator
errIter = iter(Errors.errors)
errRec = errIter.next( )
# Advance to the source line of the next error
while srcLineNum < errRec.line:
if Trace:
Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) )
srcLineStr = srcLineIter.next( )
srcLineNum += 1
# Write out all errors for the current source line
while errRec.line == srcLineNum:
if Trace:
Errors.display( srcLineStr, errRec )
errRec = errIter.next( )
except:
pass
# No more errors to report
try:
# Advance to end of source file
while True:
Errors.mergedList.write( '%4d %s\n' % (srcLineNum, srcLineStr) )
srcLineStr = srcLineIter.next( )
srcLineNum += 1
except:
pass
if Trace:
Errors.mergedList.write( '\n' )
Errors.mergedList.write( '%d errors detected\n' % Errors.count )
Errors.mergedList.close( )
if Trace:
sys.stdout.write( '%d errors detected\n' % Errors.count )
if (Errors.count > 0) and Errors.mergeErrors:
sys.stdout.write( 'see ' + Errors.listName + '\n' )
class Parser( object ):
_EOF = 0
_ident = 1
_integer = 2
maxT = 44
T = True
x = False
minErrDist = 2
def __init__( self ):
self.scanner = None
self.token = None # last recognized token
self.la = None # lookahead token
self.genScanner = False
self.tokenString = '' # used in declarations of literal tokens
self.noString = '-none-' # used in declarations of literal tokens
self.errDist = Parser.minErrDist
def getParsingPos( self ):
return self.la.line, self.la.col
def SynErr( self, errNum ):
if self.errDist >= Parser.minErrDist:
Errors.SynErr( errNum )
self.errDist = 0
def SemErr( self, msg ):
if self.errDist >= Parser.minErrDist:
Errors.SemErr( msg )
self.errDist = 0
def Warning( self, msg ):
if self.errDist >= Parser.minErrDist:
Errors.Warn( msg )
self.errDist = 0
def Successful( self ):
return Errors.count == 0;
def LexString( self ):
return self.token.val
def LookAheadString( self ):
return self.la.val
def Get( self ):
while True:
self.token = self.la
self.la = self.scanner.Scan( )
if self.la.kind <= Parser.maxT:
self.errDist += 1
break
self.la = self.token
def Expect( self, n ):
if self.la.kind == n:
self.Get( )
else:
self.SynErr( n )
def StartOf( self, s ):
return self.set[s][self.la.kind]
def ExpectWeak( self, n, follow ):
if self.la.kind == n:
self.Get( )
else:
self.SynErr( n )
while not self.StartOf(follow):
self.Get( )
def WeakSeparator( self, n, syFol, repFol ):
s = [ False for i in xrange( Parser.maxT+1 ) ]
if self.la.kind == n:
self.Get( )
return True
elif self.StartOf(repFol):
return False
else:
for i in xrange( Parser.maxT ):
s[i] = self.set[syFol][i] or self.set[repFol][i] or self.set[0][i]
self.SynErr( n )
while not s[self.la.kind]:
self.Get( )
return self.StartOf( syFol )
def Oberon0( self ):
self.module()
def module( self ):
self.Expect(3)
self.Expect(1)
self.Expect(4)
self.declarations()
if (self.la.kind == 5):
self.Get( )
self.StatementSequence()
self.Expect(6)
self.Expect(1)
self.Expect(7)
def declarations( self ):
if (self.la.kind == 8):
self.Get( )
while self.la.kind == 1:
self.Get( )
self.Expect(9)
self.expression()
self.Expect(4)
if (self.la.kind == 10):
self.Get( )
while self.la.kind == 1:
self.Get( )
self.Expect(9)
self.type()
self.Expect(4)
if (self.la.kind == 11):
self.Get( )
while self.la.kind == 1:
self.IdentList()
self.Expect(12)
self.type()
self.Expect(4)
while self.la.kind == 17:
self.ProcedureDeclaration()
self.Expect(4)
def StatementSequence( self ):
self.statement()
while self.la.kind == 4:
self.Get( )
self.statement()
def expression( self ):
self.SimpleExpression()
if (self.StartOf(1)):
if self.la.kind == 9:
self.Get( )
elif self.la.kind == 20:
self.Get( )
elif self.la.kind == 21:
self.Get( )
elif self.la.kind == 22:
self.Get( )
elif self.la.kind == 23:
self.Get( )
else:
self.Get( )
self.SimpleExpression()
def type( self ):
if self.la.kind == 1:
self.Get( )
elif self.la.kind == 14:
self.ArrayType()
elif self.la.kind == 16:
self.RecordType()
else:
self.SynErr(45)
def IdentList( self ):
self.Expect(1)
while self.la.kind == 13:
self.Get( )
self.Expect(1)
def ProcedureDeclaration( self ):
self.ProcedureHeading()
self.Expect(4)
self.ProcedureBody()
self.Expect(1)
def ArrayType( self ):
self.Expect(14)
self.expression()
self.Expect(15)
self.type()
def RecordType( self ):
self.Expect(16)
self.FieldList()
while self.la.kind == 4:
self.Get( )
self.FieldList()
self.Expect(6)
def FieldList( self ):
if (self.la.kind == 1):
self.IdentList()
self.Expect(12)
self.type()
def ProcedureHeading( self ):
self.Expect(17)
self.Expect(1)
if (self.la.kind == 18):
self.FormalParameters()
def ProcedureBody( self ):
self.declarations()
if (self.la.kind == 5):
self.Get( )
self.StatementSequence()
self.Expect(6)
def FormalParameters( self ):
self.Expect(18)
if (self.la.kind == 1 or self.la.kind == 11):
self.FPSection()
while self.la.kind == 4:
self.Get( )
self.FPSection()
self.Expect(19)
def FPSection( self ):
if (self.la.kind == 11):
self.Get( )
self.IdentList()
self.Expect(12)
self.type()
def SimpleExpression( self ):
if (self.la.kind == 25 or self.la.kind == 26):
if self.la.kind == 25:
self.Get( )
else:
self.Get( )
self.term()
while self.la.kind == 25 or self.la.kind == 26 or self.la.kind == 27:
if self.la.kind == 25:
self.Get( )
elif self.la.kind == 26:
self.Get( )
else:
self.Get( )
self.term()
def term( self ):
self.factor()
while self.StartOf(2):
if self.la.kind == 28:
self.Get( )
elif self.la.kind == 29:
self.Get( )
elif self.la.kind == 30:
self.Get( )
else:
self.Get( )
self.factor()
def factor( self ):
if self.la.kind == 1:
self.Get( )
if self.la.kind == 18:
self.Get( )
self.expression()
if (self.la.kind == 13):
self.Get( )
self.expression()
self.Expect(19)
elif self.StartOf(3):
self.selector()
else:
self.SynErr(46)
elif self.la.kind == 2:
self.Get( )
elif self.la.kind == 18:
self.Get( )
self.expression()
self.Expect(19)
elif self.la.kind == 32:
self.Get( )
self.factor()
else:
self.SynErr(47)
def selector( self ):
while self.la.kind == 7 or self.la.kind == 33:
if self.la.kind == 7:
self.Get( )
self.Expect(1)
else:
self.Get( )
self.expression()
self.Expect(34)
def statement( self ):
if (self.StartOf(4)):
if self.la.kind == 1:
self.AssignmentOrProcedureCall()
elif self.la.kind == 35:
self.IfStatement()
elif self.la.kind == 39:
self.WhileStatement()
else:
self.RepeatStatement()
def AssignmentOrProcedureCall( self ):
self.Expect(1)
if self.la.kind == 7 or self.la.kind == 33 or self.la.kind == 43:
self.selector()
self.Get( )
self.expression()
elif self.StartOf(5):
if (self.la.kind == 18):
self.ActualParameters()
else:
self.SynErr(48)
def IfStatement( self ):
self.Expect(35)
self.expression()
self.Expect(36)
self.StatementSequence()
while self.la.kind == 37:
self.Get( )
self.expression()
self.Expect(36)
self.StatementSequence()
if (self.la.kind == 38):
self.Get( )
self.StatementSequence()
self.Expect(6)
def WhileStatement( self ):
self.Expect(39)
self.expression()
self.Expect(40)
self.StatementSequence()
self.Expect(6)
def RepeatStatement( self ):
self.Expect(41)
self.StatementSequence()
self.Expect(42)
self.expression()
def ActualParameters( self ):
self.Expect(18)
if (self.StartOf(6)):
self.expression()
while self.la.kind == 13:
self.Get( )
self.expression()
self.Expect(19)
def Parse( self, scanner ):
self.scanner = scanner
self.la = Token( )
self.la.val = u''
self.Get( )
self.Oberon0()
self.Expect(0)
set = [
[T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x],
[x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x],
[x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x],
[x,x,x,x, T,x,T,T, x,T,x,x, x,T,x,T, x,x,x,T, T,T,T,T, T,T,T,T, T,T,T,T, x,T,T,x, T,T,T,x, T,x,T,x, x,x],
[x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, x,T,x,x, x,x],
[x,x,x,x, T,x,T,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,T,x, x,x],
[x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,T,T,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x]
]
errorMessages = {
0 : "EOF expected",
1 : "ident expected",
2 : "integer expected",
3 : "\"MODULE\" expected",
4 : "\";\" expected",