[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
The source code that is generated by treecc exports a number of application programmer interfaces (API's) to the programmer. These can be used elsewhere in the compiler implementation to manipulate abstract syntax trees. The following sections describe the API's for each of the output languages.
6.1 C Language APIs | ||
6.2 C++ Language APIs | ||
6.3 Java Language APIs | ||
6.4 C# Language APIs | ||
6.5 Ruby Language APIs | ||
6.6 Python Language APIs |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the C output language, each node type is converted into a ‘typedef’ that contains the node's fields, and the fields of its ancestor node types. The following example demonstrates how treecc node declarations are converted into C source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression *expr1; expression *expr2; } %node plus binary |
becomes:
typedef struct expression__ expression; typedef struct binary__ binary; typedef struct plus__ plus; struct expression__ { const struct expression_vtable__ *vtable__; int kind__; char *filename__; long linenum__; type_code type; }; struct binary__ { const struct binary_vtable__ *vtable__; int kind__; char *filename__; long linenum__; type_code type; expression * expr1; expression * expr2; }; struct plus__ { const struct plus_vtable__ *vtable__; int kind__; char *filename__; long linenum__; type_code type; expression * expr1; expression * expr2; }; |
Programmers should avoid using any identifiers that end in ‘__’. Such identifiers are reserved for internal use by treecc and its support routines.
For each non-abstract node type called ‘NAME’, treecc generates a function called ‘NAME_create’ that creates nodes of that type. The general form of the function's prototype is as follows:
TYPE *NAME_create([YYNODESTATE *state,] PARAMS) |
The return node type, which is the nearest ancestor that has the ‘%typedef’ flag.
The name of the node type that is being created.
The system state, if reentrant code is being generated.
The create parameters, consisting of every field that does not have the ‘%nocreate’ flag. The parameters appear in the same order as the fields in the node types, from the top-most ancestor down to the node type itself. For example:
expression *plus_create(expression * expr1, expression * expr2); |
Enumerated types are converted into a C ‘typedef’ with the same name and values:
%enum JavaType = { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } |
becomes:
typedef enum { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } JavaType; |
Virtual operations are converted into C macros that invoke the correct vtable entry on a node type:
%operation %virtual void infer_type(expression *e) |
becomes:
#define infer_type(this__) \ ((*(((struct expression_vtable__ *) \ ((this__)->vtable__))->infer_type_v__)) \ ((expression *)(this__))) |
Calls to ‘infer_type’ can then be made with ‘infer_type(node)’.
Non-virtual operations are converted into C functions:
%operation void infer_type(expression *e) |
becomes:
extern void infer_type(expression *e); |
Because virtual and non-virtual operations use a similar call syntax, it is very easy to convert a virtual operation into a non-virtual operation when the output language is C. This isn't possible with the other output languages.
Other house-keeping tasks are performed by the following functions and macros. Some of these must be supplied by the programmer. The ‘state’ parameter is required only if a reentrant compiler is being built.
int yykind(ANY *node)
Gets the numeric kind value associated with a particular node. The kind value for node type ‘NAME’ is called ‘NAME_kind’.
const char *yykindname(ANY *node)
Gets the name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
int yyisa(ANY *node, type)
Determines if ‘node’ is an instance of the node type ‘type’.
char *yygetfilename(ANY *node)
Gets the filename corresponding to where ‘node’ was created during parsing. This macro is only generated if ‘%option track_lines’ was specified.
long yygetlinenum(ANY *node)
Gets the line number corresponding to where ‘node’ was created during parsing. This macro is only generated if ‘%option track_lines’ was specified.
void yysetfilename(ANY *node, char *value)
Sets the filename associated with ‘node’ to ‘value’. The string is not copied, so ‘value’ must persist for the lifetime of the node. This macro will rarely be required, unless a node corresponds to a different line than the current parse line. This macro is only generated if ‘%option track_lines’ was specified.
void yysetlinenum(ANY *node, long value)
Sets the line number associated with ‘node’ to ‘value’. This macro will rarely be required, unless a node corresponds to a different line than the current parse line. This macro is only generated if ‘%option track_lines’ was specified.
char *yycurrfilename([YYNODESTATE *state])
Get the name of the current input file from the parser. The pointer that is returned from this function is stored as-is: the string is not copied. Therefore, the value must persist for at least as long as the node will persist. This function must be supplied by the programmer if ‘%option track_lines’ was specified.
long yycurrlinenum([YYNODESTATE *state])
Get the number of the current input line from the parser. This function must be supplied by the programmer if ‘%option track_lines’ was specified.
void yynodeinit([YYNODESTATE *state])
Initializes the node memory manager. If the system is reentrant, then the node memory manager is ‘state’. Otherwise a global node memory manager is used.
void *yynodealloc([YYNODESTATE *state,] unsigned int size)
Allocates a block of memory of ‘size’ bytes in size from the node memory manager. This function is called automatically from the node-specific ‘*_create’ functions. The programmer will not normally need to call this function.
This function will return NULL
if the system is out of
memory, or if ‘size’ is too large to be allocated within
the node memory manager. If the system is out of memory, then
‘yynodealloc’ will call ‘yynodefailed’ prior to
returning NULL
.
int yynodepush([YYNODESTATE *state])
Pushes the current node memory manager position. The next time
yynodepop
is called, the node memory manager will reset to
the pushed position. This function returns zero if the system
is out of memory.
void yynodepop([YYNODESTATE *state])
Pops the current node memory manager position. This function has
no effect if yynodepush
was not called previously.
The yynodepush
and yynodepop
functions can be used
to perform a simple kind of garbage collection on nodes. When
the parser enters a scope, it pushes the node memory manager
position. After all definitions in the scope have been dealt
with, the parser pops the node memory manager to reclaim all
of the memory used.
void yynodeclear([YYNODESTATE *state])
Clears the entire node memory manager and returns it to the
state it had after calling yynodeinit
. This is typically
used upon program shutdown to free all remaining node memory.
void yynodefailed([YYNODESTATE *state])
Called when yynodealloc
or yynodepush
detects that
the system is out of memory. This function must be supplied by
the programmer. The programmer may choose to exit to program
when the system is out of memory; in which case yynodealloc
will never return NULL
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the C++ output language, each node type is converted into a ‘class’ that contains the node's fields, virtual operations, and other house-keeping definitions. The following example demonstrates how treecc node declarations are converted into C++ source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression *expr1; expression *expr2; } %node plus binary |
becomes:
class expression { protected: int kind__; char *filename__; long linenum__; public: int getKind() const { return kind__; } const char *getFilename() const { return filename__; } int getLinenum() const { return linenum__; } void setFilename(char *filename) { filename__ = filename; } void setLinenum(long linenum) { linenum__ = linenum; } void *operator new(size_t); void operator delete(void *, size_t); protected: expression(); public: type_code type; virtual int isA(int kind) const; virtual const char *getKindName() const; protected: virtual ~expression(); }; class binary : public expression { protected: binary(expression * expr1, expression * expr2); public: expression * expr1; expression * expr2; virtual int isA(int kind) const; virtual const char *getKindName() const; protected: virtual ~binary(); }; class plus : public binary { public: plus(expression * expr1, expression * expr2); public: virtual int isA(int kind) const; virtual const char *getKindName() const; protected: virtual ~plus(); }; |
The following standard methods are available on every node type:
int getKind()
Gets the numeric kind value associated with a particular node. The kind value for node type ‘NAME’ is called ‘NAME_kind’.
virtual const char *getKindName()
Gets the name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
virtual int isA(int kind)
Determines if the node is a member of the node type that corresponds to the numeric kind value ‘kind’.
const char *getFilename()
Gets the filename corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
long getLinenum()
Gets the line number corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
void setFilename(char *value)
Sets the filename associated with the node to ‘value’. The string is not copied, so ‘value’ must persist for the lifetime of the node. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
void setLinenum(long value)
Sets the line number associated with the node to ‘value’. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
If the generated code is non-reentrant, then the constructor for the class can be used to construct nodes of the specified node type. The constructor parameters are the same as the fields within the node type's definition, except for ‘%nocreate’ fields.
If the generated code is reentrant, then nodes cannot be constructed using the C++ ‘new’ operator. The ‘*Create’ methods on the ‘YYNODESTATE’ factory class must be used instead.
The ‘YYNODESTATE’ class contains a number of house-keeping methods that are used to manage nodes:
static YYNODESTATE *getState()
Gets the global ‘YYNODESTATE’ instance that is being used by non-reentrant code. If an instance has not yet been created, this method will create one.
When using non-reentrant code, the programmer will normally subclass ‘YYNODESTATE’, override some of the methods below, and then construct an instance of the subclass. This constructed instance will then be returned by future calls to ‘getState’.
void *alloc(size_t size)
Allocates a block of memory of ‘size’ bytes in size from the node memory manager. This function is called automatically from the node-specific constructors and ‘*Create’ methods. The programmer will not normally need to call this function.
This function will return NULL
if the system is out of
memory, or if ‘size’ is too large to be allocated within
the node memory manager. If the system is out of memory, then
‘alloc’ will call ‘failed’ prior to returning NULL
.
int push()
Pushes the current node memory manager position. The next time
pop
is called, the node memory manager will reset to
the pushed position. This function returns zero if the system
is out of memory.
void pop()
Pops the current node memory manager position. This function has
no effect if push
was not called previously.
The push
and pop
methods can be used
to perform a simple kind of garbage collection on nodes. When
the parser enters a scope, it pushes the node memory manager
position. After all definitions in the scope have been dealt
with, the parser pops the node memory manager to reclaim all
of the memory used.
void clear()
Clears the entire node memory manager and returns it to the state it had after construction.
virtual void failed()
Called when alloc
or push
detects that
the system is out of memory. This method is typically
overridden by the programmer in subclasses. The programmer may
choose to exit to program when the system is out of memory; in
which case alloc
will never return NULL
.
virtual char *currFilename()
Get the name of the current input file from the parser. The pointer that is returned from this function is stored as-is: the string is not copied. Therefore, the value must persist for at least as long as the node will persist. This method is usually overrriden by the programmer in subclasses if ‘%option track_lines’ was specified.
virtual long currLinenum()
Get the number of the current input line from the parser. This method is usually overridden by the programmer in subclasses if ‘%option track_lines’ was specified.
The programmer will typically subclass ‘YYNODESTATE’ to provide additional functionality, and then create an instance of this class to act as the node memory manager and node creation factory.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the Java output language, each node type is converted into a ‘class’ that contains the node's fields, virtual operations, and other house-keeping definitions. The following example demonstrates how treecc node declarations are converted into Java source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression expr1; expression expr2; } %node plus binary |
becomes:
public class expression { protected int kind__; protected String filename__; protected long linenum__; public int getKind() { return kind__; } public String getFilename() { return filename__; } public long getLinenum() const { return linenum__; } public void setFilename(String filename) { filename__ = filename; } public void setLinenum(long linenum) { linenum__ = linenum; } public static final int KIND = 1; public type_code type; protected expression() { this.kind__ = KIND; this.filename__ = YYNODESTATE.getState().currFilename(); this.linenum__ = YYNODESTATE.getState().currLinenum(); } public int isA(int kind) { if(kind == KIND) return 1; else return 0; } public String getKindName() { return "expression"; } } public class binary extends expression { public static final int KIND = 2; public expression expr1; public expression expr2; protected binary(expression expr1, expression expr2) { super(); this.kind__ = KIND; this.expr1 = expr1; this.expr2 = expr2; } public int isA(int kind) { if(kind == KIND) return 1; else return super.isA(kind); } public String getKindName() { return "binary"; } } public class plus extends binary { public static final int KIND = 3; public plus(expression expr1, expression expr2) { super(expr1, expr2); this.kind__ = KIND; } public int isA(int kind) { if(kind == KIND) return 1; else return super.isA(kind); } public String getKindName() { return "plus"; } } |
The following standard members are available on every node type:
int KIND
The kind value for the node type corresponding to this class.
int getKind()
Gets the numeric kind value associated with a particular node. The kind value for node type ‘NAME’ is called ‘NAME.KIND’.
String getKindName()
Gets the name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
int isA(int kind)
Determines if the node is a member of the node type that corresponds to the numeric kind value ‘kind’.
String getFilename()
Gets the filename corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
long getLinenum()
Gets the line number corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
void setFilename(String value)
Sets the filename associated with the node to ‘value’. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
void setLinenum(long value)
Sets the line number associated with the node to ‘value’. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
If the generated code is non-reentrant, then the constructor for the class can be used to construct nodes of the specified node type. The constructor parameters are the same as the fields within the node type's definition, except for ‘%nocreate’ fields.
If the generated code is reentrant, then nodes cannot be constructed using the Java ‘new’ operator. The ‘*Create’ methods on the ‘YYNODESTATE’ factory class must be used instead.
Enumerated types are converted into a Java ‘class’:
%enum JavaType = { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } |
becomes:
public class JavaType { public static final int JT_BYTE = 0; public static final int JT_SHORT = 1; public static final int JT_CHAR = 2; public static final int JT_INT = 3; public static final int JT_LONG = 4; public static final int JT_FLOAT = 5; public static final int JT_DOUBLE = 6; public static final int JT_OBJECT_REF = 7; } |
References to enumerated types in fields and operation parameters are replaced with the type ‘int’.
Virtual operations are converted into public methods on the Java node classes.
Non-virtual operations are converted into a static method within a class named for the operation. For example,
%operation void InferType::infer_type(expression e) |
becomes:
public class InferType { public static void infer_type(expression e) { ... } } |
If the class name (‘InferType’ in the above example) is omitted, then the name of the operation is used as both the class name and the the method name.
The ‘YYNODESTATE’ class contains a number of house-keeping methods that are used to manage nodes:
static YYNODESTATE getState()
Gets the global ‘YYNODESTATE’ instance that is being used by non-reentrant code. If an instance has not yet been created, this method will create one.
When using non-reentrant code, the programmer will normally subclass ‘YYNODESTATE’, override some of the methods below, and then construct an instance of the subclass. This constructed instance will then be returned by future calls to ‘getState’.
This method will not be present if a reentrant system is being generated.
String currFilename()
Get the name of the current input file from the parser. This method is usually overrriden by the programmer in subclasses if ‘%option track_lines’ was specified.
long currLinenum()
Get the number of the current input line from the parser. This method is usually overridden by the programmer in subclasses if ‘%option track_lines’ was specified.
The programmer will typically subclass ‘YYNODESTATE’ to provide additional functionality, and then create an instance of this class to act as the global state and node creation factory.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the C# output language, each node type is converted into a ‘class’ that contains the node's fields, virtual operations, and other house-keeping definitions. The following example demonstrates how treecc node declarations are converted into C# source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression expr1; expression expr2; } %node plus binary |
becomes:
public class expression { protected int kind__; protected String filename__; protected long linenum__; public int getKind() { return kind__; } public String getFilename() { return filename__; } public long getLinenum() const { return linenum__; } public void setFilename(String filename) { filename__ = filename; } public void setLinenum(long linenum) { linenum__ = linenum; } public const int KIND = 1; public type_code type; protected expression() { this.kind__ = KIND; this.filename__ = YYNODESTATE.getState().currFilename(); this.linenum__ = YYNODESTATE.getState().currLinenum(); } public virtual int isA(int kind) { if(kind == KIND) return 1; else return 0; } public virtual String getKindName() { return "expression"; } } public class binary : expression { public const int KIND = 2; public expression expr1; public expression expr2; protected binary(expression expr1, expression expr2) : expression() { this.kind__ = KIND; this.expr1 = expr1; this.expr2 = expr2; } public override int isA(int kind) { if(kind == KIND) return 1; else return base.isA(kind); } public override String getKindName() { return "binary"; } } public class plus : binary { public const int KIND = 5; public plus(expression expr1, expression expr2) : binary(expr1, expr2) { this.kind__ = KIND; } public override int isA(int kind) { if(kind == KIND) return 1; else return base.isA(kind); } public override String getKindName() { return "plus"; } } |
The following standard members are available on every node type:
const int KIND
The kind value for the node type corresponding to this class.
int getKind()
Gets the numeric kind value associated with a particular node. The kind value for node type ‘NAME’ is called ‘NAME.KIND’.
virtual String getKindName()
Gets the name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
virtual int isA(int kind)
Determines if the node is a member of the node type that corresponds to the numeric kind value ‘kind’.
String getFilename()
Gets the filename corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
long getLinenum()
Gets the line number corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
void setFilename(String value)
Sets the filename associated with the node to ‘value’. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
void setLinenum(long value)
Sets the line number associated with the node to ‘value’. This method will rarely be required, unless a node corresponds to a different line than the current parse line. This method is only generated if ‘%option track_lines’ was specified.
If the generated code is non-reentrant, then the constructor for the class can be used to construct nodes of the specified node type. The constructor parameters are the same as the fields within the node type's definition, except for ‘%nocreate’ fields.
If the generated code is reentrant, then nodes cannot be constructed using the C# ‘new’ operator. The ‘*Create’ methods on the ‘YYNODESTATE’ factory class must be used instead.
Enumerated types are converted into a C# ‘enum’ definition:
%enum JavaType = { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } |
becomes:
public enum JavaType { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF, } |
Virtual operations are converted into public virtual methods on the C# node classes.
Non-virtual operations are converted into a static method within a class named for the operation. For example,
%operation void InferType::infer_type(expression e) |
becomes:
public class InferType { public static void infer_type(expression e) { ... } } |
If the class name (‘InferType’ in the above example) is omitted, then the name of the operation is used as both the class name and the the method name.
The ‘YYNODESTATE’ class contains a number of house-keeping methods that are used to manage nodes:
static YYNODESTATE getState()
Gets the global ‘YYNODESTATE’ instance that is being used by non-reentrant code. If an instance has not yet been created, this method will create one.
When using non-reentrant code, the programmer will normally subclass ‘YYNODESTATE’, override some of the methods below, and then construct an instance of the subclass. This constructed instance will then be returned by future calls to ‘getState’.
This method will not be present if a reentrant system is being generated.
virtual String currFilename()
Get the name of the current input file from the parser. This method is usually overrriden by the programmer in subclasses if ‘%option track_lines’ was specified.
virtual long currLinenum()
Get the number of the current input line from the parser. This method is usually overridden by the programmer in subclasses if ‘%option track_lines’ was specified.
The programmer will typically subclass ‘YYNODESTATE’ to provide additional functionality, and then create an instance of this class to act as the global state and node creation factory.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the Ruby output language, each node type is converted into a ‘class’ that contains the node's fields, operations, and other house-keeping definitions. The following example demonstrates how treecc node declarations are converted into Ruby source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression expr1; expression expr2; } %node plus binary |
becomes:
class YYNODESTATE @@state = nil def YYNODESTATE.state return @@state unless @@state.nil? @@state = YYNODESTATE.new() return @@state end def intialize @@state = self end def currFilename return nil end def currLinenum return 0 end end class Expression protected attr_reader :kind public attr_accessor :Linenum, :Filename attr_accessor :type KIND = 1 def initialize() @kind = KIND @Filename = YYNODESTATE.state.currFilename() @Linenum = YYNODESTATE.state.currLinenum() end def isA(kind) if(@kind == KIND) then return true else return 0 end end def KindName return "Expression" end end class Binary < Expression attr_accessor :expr1 attr_accessor :expr2 KIND = 2 def initialize(expr1, expr2) super(expr1, expr2) @kind = KIND self.expr1 = expr1 self.expr2 = expr2 end def isA(kind) if(@kind == Kind) then return true else return super(kind) end end def KindName return "Binary" end end class Plus < Binary KIND = 3 def initialize(expr1, expr2) super(expr1, expr2expr1, expr2) @kind = KIND end def isA(kind) if(@kind == KIND) then return true else return super(kind) end end def KindName return "Plus" end end |
The following standard members are available on every node type:
KIND
The kind value for the node type corresponding to this class. The kind value for node type ‘NAME’ is called ‘NAME::KIND’.
KindName
The name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
isA(int kind)
Determines if the node is a member of the node type that corresponds to the numeric kind value ‘kind’.
Filename
The filename corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
Linenum()
The line number corresponding to where the node was created during parsing. This method is only generated if ‘%option track_lines’ was specified.
Enumerated types are converted into a Ruby ‘class’ definition:
%enum JavaType = { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } |
becomes:
class JavaType JT_BYTE = 0 JT_SHORT = 1 JT_CHAR = 2 JT_INT = 3 JT_LONG = 4 JT_FLOAT = 5 JT_DOUBLE = 6 JT_OBJECT_REF = 7 end |
Virtual operations are converted into public methods on the Ruby node classes.
Non-virtual operations are converted into a class method within a class named for the operation. For example,
%operation void InferType::infer_type(expression e) |
becomes:
class InferType def InferType.infer_type(expression e) ... end end |
If the class name (‘InferType’ in the above example) is omitted, then the name of the operation is used as both the class name and the the method name. You then get a method with a name starting with an uppercase letter. However, Ruby methods start with lowercase methods. So never forget the class name.
The ‘YYNODESTATE’ class contains a number of house-keeping methods that are used to manage nodes:
YYNODESTATE::state()
Gets the global ‘YYNODESTATE’ instance that is being used by non-reentrant code. If an instance has not yet been created, this method will create one.
currFilename
The name of the current input file from the parser. This fields accessor method is usually overrriden by the programmer in subclasses if ‘%option track_lines’ was specified.
currLinenum
The number of the current input line from the parser. This fields accessor method is usually overridden by the programmer in subclasses if ‘%option track_lines’ was specified.
The programmer will typically subclass ‘YYNODESTATE’ to provide additional functionality, and then create an instance of this class to act as the global state and node creation factory.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
In the Python output language, each node type is converted into a ‘class’ that contains the node's fields, operations, and other house-keeping definitions. The following example demonstrates how treecc node declarations are converted into Python source code:
%node expression %abstract %typedef = { %nocreate type_code type; } %node binary expression %abstract = { expression expr1; expression expr2; } %node plus binary |
becomes:
class expression: KIND = 1 def __init__(self): self.kind = 1 self.filename = yycurrfilename() self.linenum = yycurrlinenum() def getKindName(self): return self.__class__.__name__ class binary (expression): KIND = 2 def __init__(self, expr1, expr2): expression.__init__(self) self.kind = 2 self.expr1 = expr1 self.expr2 = expr2 class plus (binary): KIND = 3 def __init__(self, expr1, expr2): binary.__init__(self, expr1, expr2) self.kind = 3 |
The following standard members are available on every node type:
KIND
The kind value for the node type corresponding to this class. The kind value for node type ‘NAME’ is called ‘NAME.KIND’.
kind
Gets the numeric kind value associated with a particular node. The kind value for node type ‘NAME’ is called ‘NAME.KIND’.
getKindName()
The name of the node kind associated with a particular node. This may be helpful for debugging and logging code.
filename
The filename corresponding to where the node was created during parsing. This field is only initialized if ‘%option track_lines’ was specified.
linenum
The line number corresponding to where the node was created during parsing. This field is only initialized if ‘%option track_lines’ was specified.
The isA()
method from the other output languages is not present
in the Python binding. Use the standard Python isinstance
function instead.
Enumerated types are converted into a Python ‘class’ definition:
%enum JavaType = { JT_BYTE, JT_SHORT, JT_CHAR, JT_INT, JT_LONG, JT_FLOAT, JT_DOUBLE, JT_OBJECT_REF } |
becomes:
class JavaType: JT_BYTE = 0 JT_SHORT = 1 JT_CHAR = 2 JT_INT = 3 JT_LONG = 4 JT_FLOAT = 5 JT_DOUBLE = 6 JT_OBJECT_REF = 7 |
Virtual operations are converted into public methods on the Python node classes. Non-virtual operations are converted into a global method within the generated Python module.
If ‘%option track_lines’ is specified, then the generated Python module is assumed to contain the following global methods to provide line tracking information:
yycurrfilename()
The name of the current input file from the parser.
yycurrlinenum()
The number of the current input line from the parser.
The programmer will typically provide a literal %end
block to
define these methods.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated by Klaus Treichel on January, 18 2009 using texi2html 1.78.