# EMACS settings: -*- tab-width: 2; indent-tabs-mode: t; python-indent-offset: 2 -*-
# vim: tabstop=2:shiftwidth=2:noexpandtab
# kate: tab-width 2; replace-tabs off; indent-width 2;
#
# ==============================================================================
# Authors: Patrick Lehmann
# Martin Zabel
#
# Python Module: TODO
#
# License:
# ==============================================================================
# Copyright 2007-2016 Technische Universitaet Dresden - Germany
# Chair of VLSI-Design, Diagnostics and Architecture
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
#
# load dependencies
from lib.Parser import MismatchingParserResult, MatchingParserResult, GreedyMatchingParserResult, StartOfDocumentToken
from lib.Parser import SpaceToken, CharacterToken, StringToken, NumberToken
from lib.CodeDOM import AndExpression, OrExpression, XorExpression, NotExpression, InExpression, NotInExpression, Literal, BinaryExpression
from lib.CodeDOM import EmptyLine, CommentLine, BlockedStatement as BlockedStatementBase, ExpressionChoice
from lib.CodeDOM import EqualExpression, UnequalExpression, LessThanExpression, LessThanEqualExpression, GreaterThanExpression, GreaterThanEqualExpression
from lib.CodeDOM import Statement, BlockStatement, ConditionalBlockStatement, Function, Expression, ListElement
from lib.CodeDOM import StringLiteral, IntegerLiteral, Identifier
__api__ = [
'BlockedStatement',
'IfThenElseExpressions', 'ListElementExpressions', 'PathExpressions',
'ListConstructorExpression',
'SubDirectoryExpression',
'ConcatenateExpression',
'ExistsFunction',
'VHDLStatement', 'VerilogStatement', 'CocotbStatement',
'ConstraintStatement',
'LDCStatement', 'SDCStatement', 'UCFStatement', 'XDCStatement',
'InterpolateLiteral',
'PathStatement',
'ReportStatement',
'LibraryStatement',
'IncludeStatement',
'IfStatement', 'ElseIfStatement', 'ElseStatement', 'IfElseIfElseStatement',
'Document'
]
__all__ = __api__
DEBUG = False#True
# ==============================================================================
# Forward declarations
# ==============================================================================
[docs]class BlockedStatement(BlockedStatementBase):
_allowedStatements = []
[docs]class IfThenElseExpressions(ExpressionChoice):
_allowedExpressions = []
[docs]class ListElementExpressions(ExpressionChoice):
_allowedExpressions = []
# class ListConstructorExpression(ExpressionChoice):
# _allowedExpressions = []
[docs]class PathExpressions(ExpressionChoice):
_allowedExpressions = []
# ==============================================================================
# Expressions
# ==============================================================================
NotExpression.__PARSER_EXPRESSIONS__ = IfThenElseExpressions
EqualExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
EqualExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
UnequalExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
UnequalExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
LessThanExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
LessThanExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
LessThanEqualExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
LessThanEqualExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
GreaterThanExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
GreaterThanExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
GreaterThanEqualExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
GreaterThanEqualExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
AndExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
AndExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
OrExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
OrExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
XorExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
XorExpression.__PARSER_RHS_EXPRESSIONS__ = IfThenElseExpressions
ListElement.__PARSER_LIST_ELEMENT_EXPRESSIONS__ = ListElementExpressions
[docs]class ListConstructorExpression(Expression):
def __init__(self):
super().__init__()
self._list = []
@property
def List(self):
return self._list
[docs] def AddElement(self, element):
self._list.append(element)
@classmethod
[docs] def GetParser(cls):
if DEBUG: print("init ListConstructorExpressionParser")
# match for sign "["
token = yield
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult()
if (token.Value != "["): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
result = cls()
parser = ListElementExpressions.GetParser()
parser.send(None)
try:
while True:
parser.send(token)
token = yield
except MatchingParserResult as ex:
result.AddElement(ex.value)
parser = cls.GetRepeatParser(result.AddElement, ListElement.GetParser)
parser.send(None)
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult:
pass
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("ListConstructorExpressionParser: Expected end of line or comment")
if (token.Value != "]"): raise MismatchingParserResult("ListConstructorExpressionParser: Expected end of line or comment")
# construct result
if DEBUG: print("ListConstructorExpressionParser: matched {0}".format(result))
raise MatchingParserResult(result)
def __str__(self):
buffer = "[{0}".format(self._list[0])
for item in self._list[1:]:
buffer += ", {0}".format(item)
buffer += "]"
return buffer
InExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
InExpression.__PARSER_RHS_EXPRESSIONS__ = ListConstructorExpression
NotInExpression.__PARSER_LHS_EXPRESSIONS__ = IfThenElseExpressions
NotInExpression.__PARSER_RHS_EXPRESSIONS__ = ListConstructorExpression
[docs]class SubDirectoryExpression(BinaryExpression):
__PARSER_NAME__ = "SubDirectoryExpressionParser"
__PARSER_LHS_EXPRESSIONS__ = PathExpressions
__PARSER_RHS_EXPRESSIONS__ = PathExpressions
__PARSER_OPERATOR__ = ("/",)
[docs]class ConcatenateExpression(BinaryExpression):
__PARSER_NAME__ = "ConcatenateExpressionParser"
__PARSER_LHS_EXPRESSIONS__ = PathExpressions
__PARSER_RHS_EXPRESSIONS__ = PathExpressions
__PARSER_OPERATOR__ = ("&",)
[docs]class ExistsFunction(Function):
def __init__(self, expression):
super().__init__()
self._expression = expression
@property
def Expression(self):
return self._expression
@classmethod
[docs] def GetParser(cls):
if DEBUG: print("init ExistsFunctionParser")
# match for EXISTS keyword
token = yield
# if (not isinstance(token, StringToken)): raise MismatchingParserResult()
# if (token.Value != "exists"): raise MismatchingParserResult()
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult()
if (token.Value != "?"): raise MismatchingParserResult()
# match for opening (
token = yield
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult()
if (token.Value != "{"): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for path expressions
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
parser.send(token)
token = yield
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for closing sign: }
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("ExistsFunctionParser: Expected end of line or comment")
if (token.Value != "}"): raise MismatchingParserResult("ExistsFunctionParser: Expected end of line or comment")
# construct result
result = cls(pathExpression)
if DEBUG: print("ExistsFunctionParser: matched {0}".format(result))
raise MatchingParserResult(result)
def __str__(self):
return "exists{{{0!s}}}".format(self._expression)
IfThenElseExpressions.AddChoice(Identifier)
IfThenElseExpressions.AddChoice(StringLiteral)
IfThenElseExpressions.AddChoice(IntegerLiteral)
IfThenElseExpressions.AddChoice(NotExpression)
IfThenElseExpressions.AddChoice(ExistsFunction)
IfThenElseExpressions.AddChoice(AndExpression)
IfThenElseExpressions.AddChoice(OrExpression)
IfThenElseExpressions.AddChoice(XorExpression)
IfThenElseExpressions.AddChoice(EqualExpression)
IfThenElseExpressions.AddChoice(UnequalExpression)
IfThenElseExpressions.AddChoice(LessThanExpression)
IfThenElseExpressions.AddChoice(LessThanEqualExpression)
IfThenElseExpressions.AddChoice(GreaterThanExpression)
IfThenElseExpressions.AddChoice(GreaterThanEqualExpression)
IfThenElseExpressions.AddChoice(InExpression)
IfThenElseExpressions.AddChoice(NotInExpression)
ListElementExpressions.AddChoice(Identifier)
ListElementExpressions.AddChoice(StringLiteral)
ListElementExpressions.AddChoice(IntegerLiteral)
# ==============================================================================
# File Reference Statements
# ==============================================================================
[docs]class VHDLStatement(Statement):
def __init__(self, libraryName, pathExpression, commentText):
super().__init__(commentText)
self._libraryName = libraryName
self._pathExpression = pathExpression
@property
def LibraryName(self): return self._libraryName
@property
def PathExpression(self): return self._pathExpression
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for VHDL keyword
if (not isinstance(token, StringToken)): raise MismatchingParserResult("VHDLParser: Expected VHDL keyword.")
if (token.Value.lower() != "vhdl"): raise MismatchingParserResult("VHDLParser: Expected VHDL keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("VHDLParser: Expected whitespace before VHDL library name.")
# match for identifier: library
parser = Identifier.GetParser()
parser.send(None)
library = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
library = ex.value.Name
except MatchingParserResult as ex:
library = ex.value.Name
token = yield
# match for whitespace
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("VHDLParser: Expected whitespace before VHDL fileName.")
# match for a path: pathExpression
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("VHDLParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("VHDLParser: Expected end of line or comment")
# construct result
result = cls(library, pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
if (self._commentText != ""):
return "{0}VHDL {1} {2!s} # {3}".format((" " * indent), self._libraryName, self._pathExpression, self._commentText)
else:
return "{0}VHDL {1} {2!s}".format((" " * indent), self._libraryName, self._pathExpression)
[docs]class VerilogStatement(Statement):
def __init__(self, pathExpression, commentText):
super().__init__()
self._pathExpression = pathExpression
self._commentText = commentText
@property
def PathExpression(self):
return self._pathExpression
@classmethod
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: VERILOG
if (not isinstance(token, StringToken)): raise MismatchingParserResult("VerilogParser: Expected VERILOG keyword.")
if (token.Value.lower() != "verilog"): raise MismatchingParserResult("VerilogParser: Expected VERILOG keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("VerilogParser: Expected whitespace before Verilog fileName.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("VerilogParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("VerilogParser: Expected end of line or comment")
# construct result
result = cls(pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{0}Verilog {1!s}".format(" " * indent, self._pathExpression)
[docs]class CocotbStatement(Statement):
def __init__(self, pathExpression, commentText):
super().__init__()
self._pathExpression = pathExpression
self._commentText = commentText
@property
def PathExpression(self):
return self._pathExpression
@classmethod
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: COCOTB
if (not isinstance(token, StringToken)): raise MismatchingParserResult("CocotbParser: Expected COCOTB keyword.")
if (token.Value.lower() != "cocotb"): raise MismatchingParserResult("CocotbParser: Expected COCOTB keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("CocotbParser: Expected whitespace before Python fileName.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("CocotbParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("CocotbParser: Expected end of line or comment")
# construct result
result = cls(pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{0}Cocotb {1!s}".format(" " * indent, self._pathExpression)
[docs]class ConstraintStatement(Statement):
__PARSER_NAME__ = None
__PARSER_KEYWORD__ = None
def __init__(self, pathExpression, commentText):
super().__init__()
self._pathExpression = pathExpression
self._commentText = commentText
@property
def PathExpression(self):
return self._pathExpression
@classmethod
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: __PARSER_KEYWORD__
if (not isinstance(token, StringToken)): raise MismatchingParserResult(cls.__PARSER_NAME__ + ": Expected UCF keyword.")
if (token.Value.lower() != cls.__PARSER_KEYWORD__): raise MismatchingParserResult(cls.__PARSER_NAME__ + ": Expected UCF keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult(cls.__PARSER_NAME__ + ": Expected whitespace before UCF fileName.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult(cls.__PARSER_NAME__ + ": Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult(cls.__PARSER_NAME__ + ": Expected end of line or comment")
# construct result
result = cls(pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{indent}{kw} {filename!s}".format(indent=" " * indent, kw=self.__PARSER_KEYWORD__, filename=self._pathExpression)
[docs]class LDCStatement(ConstraintStatement):
__PARSER_NAME__ = "LdcParser"
__PARSER_KEYWORD__ = "ldc"
[docs]class SDCStatement(ConstraintStatement):
__PARSER_NAME__ = "SdcParser"
__PARSER_KEYWORD__ = "sdc"
[docs]class UCFStatement(ConstraintStatement):
__PARSER_NAME__ = "UcfParser"
__PARSER_KEYWORD__ = "ucf"
[docs]class XDCStatement(ConstraintStatement):
__PARSER_NAME__ = "XdcParser"
__PARSER_KEYWORD__ = "xdc"
[docs]class InterpolateLiteral(Literal):
def __init__(self, sectionName, optionName):
super().__init__()
self._sectionName = sectionName
self._optionName = optionName
@property
def SectionName(self):
return self._sectionName
@property
def OptionName(self):
return self._optionName
@classmethod
[docs] def GetParser(cls):
if DEBUG: print("init InterpolateLiteralParser")
# match for opening ${
token = yield
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("InterpolateLiteralParser: ")
if (token.Value != "$"): raise MismatchingParserResult("InterpolateLiteralParser: ")
token = yield
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("InterpolateLiteralParser: ")
if (token.Value != "{"): raise MismatchingParserResult("InterpolateLiteralParser: ")
# match for interpolate value
value = {False: "", True: ""}
foundDelimiter = False
while True:
token = yield
if isinstance(token, CharacterToken):
if (token.Value == ":"):
if (foundDelimiter is False):
foundDelimiter = True
else:
raise MismatchingParserResult("InterpolateLiteralParser: ")
elif (token.Value == "}"):
break
elif (token.Value in "._-"):
value[foundDelimiter] += token.Value
else:
raise MismatchingParserResult("InterpolateLiteralParser: ")
elif isinstance(token, (StringToken, NumberToken)):
value[foundDelimiter] += token.Value
else:
raise MismatchingParserResult("InterpolateLiteralParser: ")
if (foundDelimiter is True):
sectionName = value[False]
optionName = value[True]
else:
sectionName = None
optionName = value[False]
# construct result
result = cls(sectionName, optionName)
if DEBUG: print("InterpolateLiteralParser: matched {0}".format(result))
raise MatchingParserResult(result)
def __str__(self):
if (self._sectionName is None):
return "${{{optionName}}}".format(optionName=self._optionName)
else:
return "${{{sectionName}:{optionName}}}".format(sectionName=self._sectionName, optionName=self._optionName)
PathExpressions.AddChoice(Identifier)
PathExpressions.AddChoice(StringLiteral)
PathExpressions.AddChoice(InterpolateLiteral)
PathExpressions.AddChoice(SubDirectoryExpression)
PathExpressions.AddChoice(ConcatenateExpression)
[docs]class PathStatement(Statement):
def __init__(self, variable, pathExpression, commentText):
super().__init__()
self._variable = variable
self._pathExpression = pathExpression
self._commentText = commentText
@property
def Variable(self):
return self._variable
@property
def PathExpression(self):
return self._pathExpression
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: path
if (not isinstance(token, StringToken)): raise MismatchingParserResult("PathParser: Expected UCF keyword.")
if (token.Value.lower() != "path"): raise MismatchingParserResult("PathParser: Expected UCF keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("PathParser: Expected whitespace before variable.")
# match for identifier: variable
parser = Identifier.GetParser()
parser.send(None)
variable = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
variable = ex.value.Name
except MatchingParserResult as ex:
variable = ex.value.Name
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: =
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("PathParser: Expected '=' sign before expression.")
if (token.Value.lower() != "="): raise MismatchingParserResult("PathParser: Expected '=' sign before expression.")
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for expression
# ==========================================================================
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
parser.send(token)
token = yield
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("PathParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("PathParser: Expected end of line or comment")
# construct result
result = cls(variable, pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{indent}Path {var} := {expr!s}".format(indent=" " * indent, var=self._variable, expr=self._pathExpression)
__repr__ = __str__
[docs]class ReportStatement(Statement):
def __init__(self, message, commentText):
super().__init__()
self._message = message
self._commentText = commentText
@property
def Message(self):
return self._message
@classmethod
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: VERILOG
if (not isinstance(token, StringToken)): raise MismatchingParserResult("ReportParser: Expected REPORT keyword.")
if (token.Value.lower() != "report"): raise MismatchingParserResult("ReportParser: Expected REPORT keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("ReportParser: Expected whitespace before report message.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = StringLiteral.GetParser()
parser.send(None)
message = None
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
message = ex.value.Value
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("ReportParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("ReportParser: Expected end of line or comment")
# construct result
result = cls(message, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{0}Report \"{1}\"".format(" " * indent, self._message)
[docs]class LibraryStatement(Statement):
def __init__(self, library, pathExpression, commentText):
super().__init__()
self._library = library
self._pathExpression = pathExpression
self._commentText = commentText
@property
def Library(self):
return self._library
@property
def PathExpression(self):
return self._pathExpression
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: LIBRARY
if (not isinstance(token, StringToken)): raise MismatchingParserResult("LibraryParser: Expected LIBRARY keyword.")
if (token.Value.lower() != "library"): raise MismatchingParserResult("LibraryParser: Expected LIBRARY keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("LibraryParser: Expected whitespace before LIBRARY library name.")
# match for library name
library = ""
while True:
token = yield
if isinstance(token, StringToken):
library += token.Value
elif isinstance(token, NumberToken):
library += token.Value
elif (isinstance(token, CharacterToken)and (token.Value == "_")):
library += token.Value
else:
break
# match for whitespace
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("LibraryParser: Expected whitespace before LIBRARY directoryName.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("LibraryParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("LibraryParser: Expected end of line or comment")
# construct result
result = cls(library, pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{0}Library {1} {2!s}".format(" " * indent, self._library, self._pathExpression)
[docs]class IncludeStatement(Statement):
def __init__(self, pathExpression, commentText):
super().__init__()
self._pathExpression = pathExpression
self._commentText = commentText
@property
def PathExpression(self):
return self._pathExpression
@classmethod
[docs] def GetParser(cls):
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: INCLUDE
if (not isinstance(token, StringToken)): raise MismatchingParserResult("IncludeParser: Expected INCLUDE keyword.")
if (token.Value.lower() != "include"): raise MismatchingParserResult("IncludeParser: Expected INCLUDE keyword.")
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult("IncludeParser: Expected whitespace before INCLUDE fileName.")
# match for string: fileName; use a StringLiteralParser to parse the pattern
parser = PathExpressions.GetParser()
parser.send(None)
pathExpression = None
try:
while True:
token = yield
parser.send(token)
except GreedyMatchingParserResult as ex:
pathExpression = ex.value
except MatchingParserResult as ex:
pathExpression = ex.value
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("IncludeParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("IncludeParser: Expected end of line or comment")
# construct result
result = cls(pathExpression, commentText)
raise MatchingParserResult(result)
def __str__(self, indent=0):
return "{0}Include {1!s}".format(" " * indent, self._pathExpression)
# ==============================================================================
# Conditional Statements
# ==============================================================================
[docs]class IfStatement(ConditionalBlockStatement):
def __init__(self, expression, commentText):
super().__init__(expression)
self._commentText = commentText
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# match for IF clause
# ==========================================================================
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: IF
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "if"): raise MismatchingParserResult()
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult()
# match for expression
# ==========================================================================
parser = IfThenElseExpressions.GetParser()
parser.send(None)
expressionRoot = None
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
expressionRoot = ex.value
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult()
# match for keyword: THEN
token = yield
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "then"): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("IfStatementParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("IfStatementParser: Expected end of line or comment")
# match for inner statements
# ==========================================================================
# construct result
result = cls(expressionRoot, commentText)
parser = cls.GetRepeatParser(result.AddStatement, BlockedStatement.GetParser)
parser.send(None)
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult:
raise MatchingParserResult(result)
def __str__(self, indent=0):
buffer = (" " * indent) + "IfClause " + self._expression.__str__()
for stmt in self._statements:
buffer += "\n{0}".format(stmt.__str__(indent + 1))
return buffer
[docs]class ElseIfStatement(ConditionalBlockStatement):
def __init__(self, expression, commentText):
super().__init__(expression)
self._commentText = commentText
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# match for multiple ELSEIF clauses
# ==========================================================================
token = yield
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for keyword: ELSEIF
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "elseif"): raise MismatchingParserResult()
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult()
# match for expression
# ==========================================================================
parser = IfThenElseExpressions.GetParser()
parser.send(None)
expressionRoot = None
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
expressionRoot = ex.value
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult()
# match for keyword: THEN
token = yield
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "then"): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("ElseIfStatementParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("ElseIfStatementParser: Expected end of line or comment")
# match for inner statements
# ==========================================================================
# construct result
result = cls(expressionRoot, commentText)
parser = cls.GetRepeatParser(result.AddStatement, BlockedStatement.GetParser)
parser.send(None)
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult:
raise MatchingParserResult(result)
def __str__(self, indent=0):
buffer = (" " * indent) + "ElseIfClause" + self._expression.__str__()
for stmt in self._statements:
buffer += "\n{0}".format(stmt.__str__(indent + 1))
return buffer
[docs]class ElseStatement(BlockStatement):
def __init__(self, commentText):
super().__init__()
self._commentText = commentText
@classmethod
[docs] def GetParser(cls):
# match for ELSE clause
# ==========================================================================
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for keyword: ELSE
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "else"): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("ElseStatementParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
commentText += token.Value
else:
raise MismatchingParserResult("ElseStatementParser: Expected end of line or comment")
# match for inner statements
# ==========================================================================
# construct result
result = cls(commentText)
parser = cls.GetRepeatParser(result.AddStatement, BlockedStatement.GetParser)
parser.send(None)
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult:
raise MatchingParserResult(result)
def __str__(self, indent=0):
buffer = (" " * indent) + "ElseClause"
for stmt in self._statements:
buffer += "\n{0}".format(stmt.__str__(indent + 1))
return buffer
[docs]class IfElseIfElseStatement(Statement):
def __init__(self):
super().__init__()
self._ifClause = None
self._elseIfClauses = None
self._elseClause = None
@property
def IfClause(self): return self._ifClause
@IfClause.setter
def IfClause(self, value): self._ifClause = value
@property
def ElseIfClauses(self): return self._elseIfClauses
@ElseIfClauses.setter
def ElseIfClauses(self, value): self._elseIfClauses = value
@property
def ElseClause(self): return self._elseClause
@ElseClause.setter
def ElseClause(self, value): self._elseClause = value
@classmethod # mccabe:disable=MC0001
[docs] def GetParser(cls):
# construct result
result = cls()
# match for IF clause
# ==========================================================================
parser = IfStatement.GetParser()
parser.send(None)
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
result.IfClause = ex.value
# match for multiple ELSEIF clauses
# ==========================================================================
try:
while True:
parser = ElseIfStatement.GetParser()
parser.send(None)
try:
parser.send(token)
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
if (result.ElseIfClauses is None):
result.ElseIfClauses = []
result.ElseIfClauses.append(ex.value)
except MismatchingParserResult as ex:
pass
# match for ELSE clause
# ==========================================================================
# match for inner statements
parser = ElseStatement.GetParser()
parser.send(None)
try:
parser.send(token)
while True:
token = yield
parser.send(token)
except MatchingParserResult as ex:
result.ElseClause = ex.value
except MismatchingParserResult as ex:
pass
# match for END IF clause
# ==========================================================================
# match for optional whitespace
if isinstance(token, SpaceToken): token = yield
# match for keyword: END
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "end"): raise MismatchingParserResult()
# match for whitespace
token = yield
if (not isinstance(token, SpaceToken)): raise MismatchingParserResult()
# match for keyword: IF
token = yield
if (not isinstance(token, StringToken)): raise MismatchingParserResult()
if (token.Value.lower() != "if"): raise MismatchingParserResult()
# match for optional whitespace
token = yield
if isinstance(token, SpaceToken): token = yield
# match for delimiter sign: \n
# commentText = ""
if (not isinstance(token, CharacterToken)): raise MismatchingParserResult("IfElseIfElseStatementParser: Expected end of line or comment")
if (token.Value == "\n"):
pass
elif (token.Value == "#"):
# match for any until line end
while True:
token = yield
if (isinstance(token, CharacterToken) and (token.Value == "\n")): break
# commentText += token.Value
else:
raise MismatchingParserResult("IfElseIfElseStatementParser: Expected end of line or comment")
raise MatchingParserResult(result)
def __str__(self, indent=0):
_indent = " " * indent
buffer = _indent + "IfElseIfElseStatement\n"
buffer += self.IfClause.__str__(indent + 1)
if (self.ElseIfClauses is not None):
for elseIf in self.ElseIfClauses:
buffer += "\n" + elseIf.__str__(indent + 1)
if (self.ElseClause is not None):
buffer += "\n" + self.ElseClause.__str__(indent + 1)
return buffer
[docs]class Document(BlockStatement):
@classmethod
[docs] def GetParser(cls):
result = cls()
parser = cls.GetRepeatParser(result.AddStatement, BlockedStatement.GetParser)
parser.send(None)
token = yield
if (not isinstance(token, StartOfDocumentToken)):
raise MismatchingParserResult("Expected a StartOfDocumentToken, got {0!s}.".format(token))
try:
while True:
token = yield
parser.send(token)
except MatchingParserResult:
raise MatchingParserResult(result)
def __str__(self, indent=0):
buffer = " " * indent + "Document"
for stmt in self._statements:
buffer += "\n{0}".format(stmt.__str__(indent + 1))
return buffer
BlockedStatement.AddChoice(IncludeStatement)
BlockedStatement.AddChoice(LibraryStatement)
BlockedStatement.AddChoice(VHDLStatement)
BlockedStatement.AddChoice(VerilogStatement)
BlockedStatement.AddChoice(CocotbStatement)
BlockedStatement.AddChoice(LDCStatement)
BlockedStatement.AddChoice(SDCStatement)
BlockedStatement.AddChoice(UCFStatement)
BlockedStatement.AddChoice(XDCStatement)
BlockedStatement.AddChoice(PathStatement)
BlockedStatement.AddChoice(ReportStatement)
BlockedStatement.AddChoice(IfElseIfElseStatement)
BlockedStatement.AddChoice(CommentLine)
BlockedStatement.AddChoice(EmptyLine)