Skip to content

Instantly share code, notes, and snippets.

@haskellcamargo
Created June 6, 2015 00:57
Show Gist options
  • Save haskellcamargo/896b82a4f30e5aef239c to your computer and use it in GitHub Desktop.
Save haskellcamargo/896b82a4f30e5aef239c to your computer and use it in GitHub Desktop.
Expressions analyzer - AdvPL
#include "protheus.ch"
/**
* Gramatica formal da analise de expressoes, dentro do parser, levando em conta
* a geracao de tokens.
* @author Marcelo Camargo
* @since 17/04/2015
*
* expr := string | number | array | nil | codeblock | date | object
* string := <? T_STRING ?>
* number := <? T_NUMBER ?>
* array := expr | <? NT_EMPTY_ARRAY ?>
* nil := <? T_NIL ?>
* codeblock := <? T_CODEBLOCK ?>
* date := <? T_DATE ?>
* object := { property }
* property := <? T_PROPERTY ?>
* logic = <? T_TRUE ?> | <? T_FALSE ?>
*/
#xtranslate BREAKLINE => CHR( 13 ) + CHR( 10 )
//------------------------------------------------------------------------------
/*{Protheus.doc} VarDump
Analisa recursivamente uma expressao, em sua equivalencia a var_dump (PHP),
dir (Python), console.log (Javascript) ou obj.inspect (Ruby). Monta uma arvore
visual com definicoes de escopo e informacoes precisas sobre a expressao
recebida.
@author Marcelo Camargo
@since 17/04/2015
@param xVar - Expressao a ser analisada.
@return
/*/
//------------------------------------------------------------------------------
Function VarDump( xVar )
Scope := 0 // Scope initial value
ConOut( ParseExpr( xVar ) )
Return
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseExpr
Analisa uma expressao usando um micro top-down recursive descent parser,
utilizando informacoes sobre o tipo como tokens.
@author Marcelo Camargo
@since 17/04/2015
@param xVar - Expressao a ser analisada.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseExpr( xVar )
Local cType := ValType( xVar )
Do Case
Case cType == "C" // String
Return ParseString( xVar )
Case cType == "N" // Number
Return ParseNumber( xVar )
Case cType == "A" // Array
Return ParseArray( xVar )
Case cType == "U" // Nil
Return ParseNil()
Case cType == "B" // Codeblock
Return ParseBlock( xVar )
Case cType == "D" // Date
Return ParseDate( xVar )
Case cType == "O" // Object
Return ParseObject( xVar )
Case cType == "L" // Logic
Return ParseBool( xVar )
Otherwise
Return ParseUnknown( xVar )
EndCase
Return
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseString
Analisa uma string e retorna seu tamanho e conteudo interno corretamente
formatados.
@author Marcelo Camargo
@since 17/04/2015
@param cData - String a ser analisada.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseString( cData )
Return "string<" + AllTrim( Str( Len( cData ) ) ) + ">('" + cData + "')" ;
+ BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseNumber
Analisa uma numero e retorna seu conteudo visualmente formatado.
@author Marcelo Camargo
@since 17/04/2015
@param nData - Numero (inteiro ou real) a ser analisado.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseNumber( nData )
Return "number(" + AllTrim( Str( nData ) ) + ")" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseBool
Analisa um valor logico e retorna seu conteudo visualmente formatado,
neste caso, seu source.
@author Marcelo Camargo
@since 17/04/2015
@param lData - Vaor logico a ser analisado.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseBool( lData )
Return "logic(" + IIf( lData, "True", "False" ) + ")" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseUnknown
Analisa um valor com tipo desconhecido e retorna este de forma formatada,
quando possivel.
@author Marcelo Camargo
@since 17/04/2015
@param xData - Valor desconhecido (talvez novos tipos) a serem analisados.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseUnknown( xData )
Return "unknown(" + ValType( xData ) + ")" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseNil
Simbolo nao-terminal que representa um terminal literal nulo.
@author Marcelo Camargo
@since 17/04/2015
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseNil()
Return "NIL" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseArray
Analisa recursivamente um array e seus sub-elementos, seguindo a gramatica
definida no começo do arquivo e montando um template com os dados analisados,
seguindo uma ordem logica de escopo.
@author Marcelo Camargo
@since 17/04/2015
@param aData - Array a ser analisado.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseArray( aData )
Local nI
Local cTemplate := ""
// Array e um nao terminal que pode conter itens em seu escopo.
Scope++
cTemplate += "array<" + AllTrim( Str( Len( aData ) ) ) + ">("
If Len( aData ) > 0 // Vamos quebrar linha apenas quando o array tiver itens.
cTemplate += BREAKLINE
EndIf
// Percorrendo todos os elementos do array, vamos, recursivamente, analisar
// os valores contidos em cada um deles, ate alcancarmos algum simbolo
// literal.
For nI := 1 To Len( aData )
cTemplate += Replicate( " ", Scope * 2 ) + "[" + Alltrim( Str( nI ) ) ;
+ "] => " + ParseExpr( aData[ nI ] )
Next nI
// Retornamos ao nosso escopo anterior caso tenhamos itens no array, por
// questoes esteticas de formatacao.
cTemplate += IIf( Len( aData ) > 0, Replicate( " ", ( Scope * 2 ) - 2 ), ;
"" ) + ")" + BREAKLINE
Scope--
Return cTemplate
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseBlock
Analisa um bloco e retorna seu conteudo visualmente formatado, neste caso,
seu source.
@author Marcelo Camargo
@since 17/04/2015
@param bData - Bloco a ser analisado.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseBlock( bData )
Return "block(" + GetCBSource( bData ) + ")" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseDate
Analisa uma data e retorna seu conteudo visualmente formatado.
@author Marcelo Camargo
@since 17/04/2015
@param dData - Data a ser analisada.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseDate( dData )
Return "date(" + DtoC( dData) + ")" + BREAKLINE
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseObject
Aplica reflexao e, dentro de um objeto, busca por suas propriedades e exibe
seus pares de chave e valor de forma formatada.
@author Marcelo Camargo
@since 17/04/2015
@param oData - Objeto a ser analisado.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseObject( oData )
Local cTemplate := ""
// Array contendo os dados do objeto.
Local aChildren := ClassDataArr( oData )
// Objeto e um nao terminal que pode conter itens em seu escopo.
Scope++
cTemplate += "object<" + GetClassName( oData ) + "> {" + BREAKLINE
cTemplate += ParseProperty( aChildren )
cTemplate += Replicate( " ", ( Scope * 2 ) - 2 ) + "}" + BREAKLINE
Scope--
Return cTemplate
//------------------------------------------------------------------------------
/*{Protheus.doc} ParseProperty
Analise de propriedades de objetos.
@author Marcelo Camargo
@since 17/04/2015
@param aProp - Array reflectivo de propriedades a serem analisadas.
@return string
/*/
//------------------------------------------------------------------------------
Static Function ParseProperty( aProp )
Local nI
Local cTemplate := ""
// Cada propriedade corresponde a um elemento.
// [ nI ][ 1 ] => Chave
// [ nI ][ 2 ] => Valor
// [ nI ][ 3 ] => Campo com valor number(0)
For nI := 1 To Len( aProp )
cTemplate += Replicate( " ", Scope * 2 ) + "Property<" + aProp[ nI ][ 1 ] + ;
">: " + ParseExpr( aProp[ nI ][ 2 ] )
Next nI
Return cTemplate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment