I'd suggest adding a method in the walker which handles AssignmentStatements 
and looks to see if the left-hand side is a NameExpression.  If it is then you 
can add it to a list of excluded variable names which you can remove from 
clnVariableNames after the walk is finished.

From: ironpython-users-bounces+dinov=microsoft....@python.org 
[mailto:ironpython-users-bounces+dinov=microsoft....@python.org] On Behalf Of 
Rutger Koperdraad
Sent: Thursday, December 15, 2011 8:34 AM
To: ironpython-users@python.org
Subject: [Ironpython-users] PythonAst

Hi,

I'm writing an application in Visual Basic .NET that allows the users to write 
scripts in IronPython for some specialized customization needs. Users provide a 
script, a number of variable names and values, and an expression. For example, 
to customize the displaying of dates, they could provide the following script, 
variables and expressions:

Script:
dateformat = 'dddd d MMMM yyyy'
prefix = 'Birth date: '

def format(d):
  import System
  dd = System.DateTime.Parse(d)
  return dd.ToString(dateformat)

Variables:
birthdate = '10/04/1968'

Expression:
prefix + format(birthdate)

In Visual Basic .NET I create a ScriptRuntime, ScriptEngine, ScriptSource and 
ScriptScope. I add the variables to the ScriptScope, execute the script and 
evaluate the expression. That's working like a charm.

I would like to add functionality that automatically detects which variables 
need to be defined. In the above example, I would like the user to specify the 
script and the expression and the software to detect that the variable 
"birthdate" is needed and prompt for a value. I tried to do so with PythonAst, 
but I cannot find sufficient documentation on internet to get it working in 
general. The functions below work to some extent. They get all the names from 
the expression and then remove "format" for being a function name and not a 
variable name. But this function still returns "prefix", which it shouldn't. 
Any help or documentation would be appreciated.

    Public Function GetVariableNames(ByVal strExpression As String) As 
StringCollection
        Try
            If Not String.IsNullOrEmpty(strExpression) Then

                ' Create a script runtime if needed
                If m_objScriptRuntime Is Nothing Then
                    m_objScriptRuntime = ScriptRuntime.CreateFromConfiguration()
                End If

                ' Create the objects needed by the expression walker
                Dim objEngine As ScriptEngine = 
m_objScriptRuntime.GetEngine(ScriptLanguage)
                Dim objSource As ScriptSource = 
objEngine.CreateScriptSourceFromString(strExpression, SourceCodeKind.Expression)
                Dim objSourceUnit As SourceUnit = 
Providers.HostingHelpers.GetSourceUnit(objSource)
                Dim objLanguageContext As LanguageContext = 
HostingHelpers.GetLanguageContext(objEngine)
                Dim objCompilerContext As New CompilerContext(objSourceUnit, 
objLanguageContext.GetCompilerOptions(), ErrorSink.Default)
                Dim objParser As Parser = 
Parser.CreateParser(objCompilerContext, New PythonOptions)
                Dim objPythonAst As PythonAst = objParser.ParseSingleStatement()
                Dim objExpressionWalker As New ExpressionWalker

                ' Determine the variable names
                Call objPythonAst.Walk(objExpressionWalker)

                Return objExpressionWalker.VariableNames
            End If
        Catch ex As Exception
            Call LogException(strExpression, ex)
        End Try

        Return New StringCollection
    End Function

    Private Class ExpressionWalker
        Inherits PythonWalker

        Private clnVariableNames As New StringCollection

        Public ReadOnly Property VariableNames As StringCollection
            Get
                Return clnVariableNames
            End Get
        End Property

        Public Overrides Sub PostWalk(node As NameExpression)
            Call clnVariableNames.Add(node.Name)

            Call MyBase.PostWalk(node)
        End Sub

        Public Overrides Sub PostWalk(node As CallExpression)
            Dim objNameExpression As NameExpression = TryCast(node.Target, 
NameExpression)

            If Not objNameExpression Is Nothing Then
                Call clnVariableNames.Remove(objNameExpression.Name)
            End If

            Call MyBase.PostWalk(node)
        End Sub

    End Class

With best regards,
Rutger Koperdraad.
_______________________________________________
Ironpython-users mailing list
Ironpython-users@python.org
http://mail.python.org/mailman/listinfo/ironpython-users

Reply via email to