Skip to content

AST Specification

M2SF Project Administrator edited this page May 23, 2017 · 100 revisions

Abstract Syntax Tree

The M2C/M2J/M2Sharp compilers encode valid Modula-2 input in memory as an abstract syntax tree (AST).

The AST uses three kinds of nodes.

  • an EMPTY sentinel node
  • non-terminal nodes
  • terminal nodes

The Sentinel Node

The sentinel node EMPTY is used to encode the absence of an optional sub-node in non-terminal nodes.

Non-Terminal Nodes

Non-terminal nodes are used to encode non-terminal symbols such as modules, imports, definitions, declarations, statements and expressions.

AST, DEFMOD, IMPLIST, IMPORT, UNQIMP, DEFLIST, CONSTDEF, TYPEDEF, PROCDEF, SUBR, ENUM, SET, ARRAY, RECORD, POINTER, PROCTYPE, EXTREC, VRNTREC, INDEXLIST, FIELDLISTSEQ, FIELDLIST, VFLISTSEQ, VFLIST, VARIANTLIST, VARIANT, CLABELLIST, CLABELS, FTYPELIST, OPENARRAY, CONSTP, VARP, FPARAMLIST, FPARAMS, IMPMOD, BLOCK, DECLLIST, TYPEDECL, VARDECL, PROC, MODDECL, VSREC, VSFIELD, EXPORT, QUALEXP, STMTSEQ, ASSIGN, PCALL, RETURN, WITH, IF, SWITCH, LOOP, WHILE, REPEAT, FORTO, EXIT, ARGS, ELSIFSEQ, ELSIF, CASELIST, CASE, FIELD, INDEX, DESIG, DEREF, NEG, NOT, EQ, NEQ, LT, LTEQ, GT, GTEQ, IN, PLUS, MINUS, OR, ASTERISK, SOLIDUS, DIV, MOD, AND, FCALL, SETVAL.

Terminal Nodes

Terminal nodes are used to encode terminal symbols such as filenames, options, identifiers, integer literals, real number literals, character code and quoted literals.

IDENT, QUALIDENT, IDENTLIST, INTVAL, REALVAL, CHRVAL, QUOTEDVAL, FILENAME, OPTIONS.

Serialised Representation

Any AST node may be represented in a serialised format of the form

( nodetype subnode-0 subnode-1 subnode-2 ... subnode-N )

where the actual number of sub-nodes is dependent on the node type.

This form of tree representation is called an S-expression.

AST Node Reference

The structure of the AST used by M2Sharp is described below in S-expression format.

Empty Node

The EMPTY node encodes the absence of an optional sub-node.

Graph

empty

S-Expression

emptyNode :=
  '(' EMPTY ')'
  ;

Root Node

The AST node encodes the root of the syntax tree.

Graph

root

S-Expression

astRootNode :=
  '(' AST filename options compilationUnit ')'
  ;

filename := filenameNode ; /* terminal node */

options := optionsNode ; /* terminal node */

compilationUnit :=
  defModuleNode | impModuleNode
  ;

Definition Module Node

The DEFMOD node encodes a definition module.

Graph

defmod

S-Expression

defModuleNode :=
  '(' DEFMOD moduleIdent importList definitionList ')'
  ;

moduleIdent := identNode ; /* terminal node */

importList :=
  importListNode | emptyNode
  ;

definitionList :=
  definitionListNode | emptyNode
  ;

Import List Node

The IMPLIST node encodes the entirety of import directives in a module.

Graph

implist

S-Expression

importListNode :=
  '(' IMPLIST import+ ')'
  ;

import :=
  importNode | unqImportNode
  ;

Qualified Import Node

The IMPORT node encodes a qualified import directive.

Graph

import

S-Expression

importNode :=
  '(' IMPORT identList ')'
  ;
  
identList := identListNode ; /* terminal node */

Unqualified Import Node

The UNQIMP node encodes an unqualified import directive.

Graph

unqimp

S-Expression

unqImportNode :=
  '(' UNQIMP moduleIdent identList ')'
  ;

Definition List Node

The DEFLIST node encodes one or more definitions.

Graph

definition

S-Expression

definitionListNode :=
  '(' DEFLIST definition+ ')'
  ;
  
definition :=
  constDefNode | typeDefNode | varDeclNode | ProcDefNode
  ;

Constant Definition Node

The CONSTDEF node encodes a constant definition.

constDefNode :=
  '(' CONSTDEF identNode exprNode ')'
  ;

Type Definition Node

The TYPEDEF node encodes a type definition.

typeDefNode :=
  '(' TYPEDEF identNode ( typeNode | emptyNode ) ')'
  ;

typeNode :=
  identNode | qualidentNode |
  subrTypeNode | enumTypeNode | setTypeNode | arrayTypeNode | recTypeNode |
  extRecTypeNode | vrntRecTypeNode | pointerTypeNode | procTypeNode
  ;

Procedure Definition Node

The PROCDEF node encodes a procedure definition.

procDefNode :=
  '(' PROCDEF identNode formalParamList returnType ')'
  ;

formalParamList :=
  formalParamListNode | emptyNode
  ;

Subrange Type Definition Node

The SUBR node encodes a subrange type definition.

Graph

subrange

S-Expression

subrTypeNode :=
  '(' SUBR lowerBound upperBound subrBaseType ')'
  ;

lowerBound := exprNode ;

upperBound := exprNode ;

subrBaseType :=
  identNode | qualidentNode | emptyNode
  ;

Enumeration Type Definition Node

The ENUM node encodes an enumeration type definition.

Graph

enumeration

S-Expression

enumTypeNode :=
  '(' ENUM identListNode ')'
  ;

Set Type Definition Node

The SET node encodes a set type definition.

Graph

set

S-Expression

setTypeNode :=
  '(' SET countableType ')'
  ;

countableType :=
  identNode | qualidentNode | subrTypeNode | enumTypeNode
  ; 

Array Type Definition Node

The ARRAY node encodes an array type definition.

Graph

array

S-Expression

arrayTypeNode :=
  '(' ARRAY indexTypeListNode arrayBaseType ')'
  ;

arrayBaseType := fieldType ;

Simple Record Type Definition Node

The RECORD node encodes a non-variant non-extensible record type definition.

Graph

record

S-Expression

recTypeNode :=
  '(' RECORD fieldListSeqNode ')'
  ;

Pointer Type Definition Node

The POINTER node encodes a pointer type definition.

Graph

pointer

S-Expression

pointerTypeNode :=
  '(' POINTER typeNode ')'
  ;

Procedure Type Definition Node

The PROCTYPE node encodes a procedure type definition.

Graph

proctype

S-Expression

procTypeNode :=
  '(' PROCTYPE formalTypeList returnedType ')'
  ;

formalTypeList :=
  formalTypeListNode | emptyNode
  ;

returnedType :=
   identNode | qualidentNode | emptyNode
   ;

Extensible Record Type Definition Node

The EXTREC node encodes an extensible record type definition.

Graph

extrec

S-Expression

extRecTypeNode :=
  '(' EXTREC recBaseType fieldListSeqNode ')'
  ;

recBaseType :=
  identNode | qualidentNode
  ;

Variant Record Type Definition Node

The VRNTREC node encodes a variant record type definition.

Graph

vrntrec

S-Expression

variantRecTypeNode :=
  '(' VRNTREC variantFieldListSeqNode ')'
  ;

Array Index Type List Node

The INDEXLIST node encodes one or more index types within an array type definition.

Graph

indexlist

S-Expression

indexTypeListNode :=
  '(' INDEXLIST indexType+ ')'
  ;

indexType := countableType ;

Simple FieldList Sequence Node

The FIELDLISTSEQ node encodes a non-variant field list sequence within a record type definition.

fieldListSeqNode :=
  '(' FIELDLISTSEQ fieldListNode+ ')'
  ;

Simple FieldList Node

The FIELDLIST node encodes a non-variant field list within a field list sequence

Graph

fieldlist

S-Expression

fieldListNode :=
  '(' FIELDLIST identListNode fieldType ')'
  ;

fieldType :=
  identNode | qualidentNode | subrTypeNode | enumTypeNode | setTypeNode |
  arrayTypeNode | recTypeNode | pointerTypeNode | procTypeNode
  ;

Variant Record FieldList Sequence Node

The VFLISTSEQ node encodes a variant field list sequence within a variant record type definition.

variantFieldListSeqNode :=
  '(' VFLISTSEQ ( fieldListNode | variantFieldListNode )+ ')'
  ;

Variant FieldList Node

The VFLIST node encodes a variant field list within a variant field list sequence.

variantFieldListNode :=
  '(' VFLIST caseIdent caseType variantList defaultFieldListSeq ')'
  ;

caseIdent :=
  identNode | emptyNode
  ;

caseType :=
  identNode | qualidentNode
  ;

defaultFieldListSeq :=
  fieldListSeqNode | emptyNode
  ;

Variant List Node

The VARIANTLIST node encodes a variant list within a variant field list.

variantList :=
  '(' VARIANTLIST variantNode+ ')'
  ;

Variant Node

The VARIANT node encodes a variant within a variant list.

variantNode :=
  '(' VARIANT caseLabelListNode fieldListSeqNode ')'
  ;

Case Label List Node

The CLABELLIST node encodes a case label list within a variant record definition or case statement.

caseLabelListNode :=
  '(' CLABELLIST caseLabelsNode+ ')
  ;

Case Labels Node

The CLABELS node encodes start and end labels within a case label list.

caseLabelsNode :=
  '(' CLABELS startLabel endLabel ')'
  ;

startLabel := exprNode ;

endLabel :=  exprNode | emptyNode ;

Formal Type List Node

The FTYPELIST node encodes a formal type list within a procedure type definition.

formalTypeListNode :
  '(' FTYPELIST formalType+ ')'
  ;

formalType :=
  simpleFormalType | attrFormalType
  ;

simpleFormalType :=
  typeIdent | openArrayTypeNode
  ;

attrFormalType :=
  constAttrFormalTypeNode | varAttrFormalTypeNode
  ;

Open Array Parameter Node

The OPENARRAY node encodes an open array parameter within a formal type list.

openArrayTypeNode :=
  '(' OPENARRAY typeIdent ')'
  ;

typeIdent :=
  identNode | qualidentNode
  ;

CONST Parameter Node

The CONSTP node encodes a CONST parameter within a formal type list.

constAttrFormalTypeNode :=
  '(' CONSTP simpleFormalType ')'
  ;

VAR Parameter Node

The VARP node encodes a VAR parameter within a formal type list.

varAttrFormalTypeNode :=
  '(' VARP simpleFormalType ')'
  ;

Formal Parameter List Node

The FPARAMLIST node encodes a formal parameter list within a procedure type definition or procedure signature.

Graph

fparamlist

S-Expression

formalParamListNode :=
  '(' FPARAMLIST formalParamsNode+ ')'
  ;

Formal Parameters Node

The FPARAMS node encodes formal parameters within a formal parameter list.

Graph

fparams

S-Expression

formalParamsNode :=
  '(' FPARAMS identListNode formalTypeNode ')'
  ;

Program Or Implementation Module Node

The IMPMOD node encodes an implementation module.

Graph

impmod

S-Expression

impModuleNode :=
  '(' IMPMOD moduleIdent priority importListNode blockNode ')'
  ;

priority :=
  exprNode | emptyNode
  ;

Block Node

The BLOCK node encodes a block within a module or procedure.

Graph

block

S-Expression

blockNode :=
  '(' BLOCK declarationList body ')'
  ;

declarationList :=
  declarationListNode | emptyNode
  ;

body :=
  statementSeqNode | emptyNode
  ;

Declaration List Node

The DECLLIST node encodes one or more declarations within a block.

declarationListNode :=
  '(' DECLLIST declarationNode+ ')'
  ;

declarationNode :=
  constDefNode | typeDeclNode | varDeclNode | procDeclNode | modDeclNode
  ;

Type Declaration Node

The TYPEDECL node encodes a type declaration.

typeDeclNode :=
  '(' TYPEDECL identNode ( typeNode | vsrTypeNode ) ')'
  ;

Variable Declaration Node

The VARDECL node encodes a variable declaration.

varDeclNode :=
  '(' VARDECL identListNode fieldType ')'
  ;

Procedure Declaration Node

The PROC node encodes a procedure declaration.

procDeclNode :=
  '(' PROC procDefNode blockNode ')'
  ;

Module Declaration Node

The MODDECL node encodes a local module declaration.

Graph

moddecl

S-Expression

modDeclNode :=
  '(' MODDECL moduleIdent priority importListNode exportList blockNode ')'
  ;

exportList :=
  unqualExportNode | qualExportNode | emptyNode
  ;

Variable Size Record Type Declaration Node

The VSREC node encodes a variable size record type declaration.

Graph

vsrec

S-Expression

vsrTypeNode :=
  '(' VSREC fieldListSeqNode varSizeFieldNode ')'
  ;

Variable Size Field Node

The VSFIELD node encodes the indeterminate field of a variable size record type.

varSizeFieldNode :=
  '(' VSFIELD varSizeField determinantField varSizeFieldType ')'
  ;

varSizeField := IdentNode ;

determinantField := IdentNode ;

varSizeFieldType := qualidentNode ;

Unqualified Export Node

The EXPORT node encodes an unqualified export directive within a local module declaration.

unqualExportNode :=
  '(' EXPORT identListNode ')'
  ;

Qualified Export Node

The QUALEXP node encodes a qualified export directive within a local module declaration.

qualExportNode :=
  '(' QUALEXP identListNode ')'
  ;

Statement Sequence Node

The STMTSEQ node encodes a statement sequence.

statementSeqNode :=
  '(' STMTSEQ statementNode+ ')'
  ;

statementNode :=
  assignmentNode | procCallNode | returnStmtNode | withStmtNode | ifStmtNode |
  caseStmtNode | loopStmtNode | whileStmtNode | repeatStmtNode | forStmtNode |
  exitStmtNode
  ;

Assignment Node

The ASSIGN node encodes an assignment statement.

Graph

assign

S-Expression

assignmentNode :=
  '(' ASSIGN designator exprNode ')'
  ;

designator :=
  identNode | qualidentNode | derefNode | designatorNode
  ;

Procedure Call Node

The PCALL node encodes a procedure call statement.

procCallNode :=
  '( PCALL designator actualParams ')'
  ;

actualParams :=
  actualParamsNode | emptyNode
  ;

RETURN Statement Node

The RETURN node encodes a RETURN statement.

returnStmtNode :=
  '(' RETURN returnValue ')'
  ;

returnValue :=
  exprNode | emptyNode
  ;

WITH Statement Node

The WITH node encodes a WITH statement.

Graph

with

S-Expression

withStmtNode :=
  '(' WITH designator statementSeqNode ')'
  ;

IF Statement Node

The IF node encodes an IF statement.

Graph

if

S-Expression

ifStmtNode :=
  '(' IF exprNode ifBranch elsifSeq elseBranch ')'
  ;

ifBranch := statementSeqNode ;

elsifSeq :=
  elsifSeqNode | emptyNode
  ;

elseBranch :=
  statementSeqNode | emptyNode
  ;

CASE Statement Node

The SWITCH statement encodes a CASE statement.

caseStmtNode :=
  '(' SWITCH exprNode caseListNode elseBranch ')'
  ;

LOOP Statement Node

The LOOP node encodes a LOOP statement.

Graph

loop

S-Expression

loopStmtNode :=
  '(' LOOP statementSeqNode ')'
  ;

WHILE Statement Node

The WHILE node encodes a WHILE statement.

Graph

while

S-Expression

whileStmtNode :=
  '(' WHILE exprNode statementSeqNode ')'
  ;

REPEAT Statement Node

The REPEAT node encodes a REPEAT statement.

Graph

repeat

S-Expression

repeatStmtNode :=
  '(' REPEAT statementSeqNode exprNode ')'
  ;

FOR Statement Node

The FORTO node encodes a FOR statement.

Graph

forto

S-Expression

forStmtNode :=
  '(' FORTO identNode startValue endValue stepValue statementSeqNode ')'
  ;

startValue : exprNode ;

endValue := expNode ;

stepValue :=
  exprNode | emptyNode
  ;

EXIT Statement Node

The EXIT encodes an EXIT statement.

exitStmtNode :=
  '(' EXIT ')'
  ;

Actual Parameters Node

The ARGS node encodes actual parameters in a procedure or function call.

actualParamsNode :=
  '(' ARGS exprNode+ ')'
  ;

ELSIFSEQ Node

The ELSIFSEQ node encodes an ELSIF sequence within an IF statement.

elsifSeqNode :=
  '(' ELSIFSEQ elsifNode+ ')'
  ;

ELSIF Node

The ELSIF node encodes a single ELSIF branch within an IF statement.

Graph

elsif

S-Expression

elsifNode :=
  '(' ELSIF exprNode statementSeqNode ')'
  ;

CASE List Node

The CASELIST node encodes a case list within a CASE statement.

caseListNode :=
  '(' CASELIST caseBranchNode+ ')'
  ;

CASE Branch Node

The CASE node encodes a case branch within a CASE statement.

caseBranchNode :=
  '(' CASE caseLabelListNode statementSeqNode ')'
  ;

Set Element List Node

The ELEMLIST node encodes the element list within a set value.

elementListNode :=
  '(' ELEMLIST element+ ')'
  ;

element :=
  expr | range
  ;

Expression Range Node

The RANGE node encodes a value range.

range :=
  '(' RANGE lowerValue upperValue ')'
  ;

lowerValue := expr ;

upperValue := expr ;

Record Field Selector Node

The FIELD node encodes a record field selector.

fieldSelectorNode :=
  '(' FIELD selector ')'
  ;

selector :=
  identNode | qualidentNode | designatorNode
  ;

Array Index Node

The INDEX node encodes an array subscript selector.

arrayIndexNode :=
  '(' INDEX subscript+ ')'
  ;

subscript := exprNode ;

exprNode :=
  negNode |  notNode | eqNode | neqNode | ltNode | ltEqNode | gtNode |
  gtEqNode | inNode | plusNode | minusNode | orNode | asteriskNode |
  solidusNode | divNode | modulusNode | andNode | designator |
  intValNode | realValNode | chrValNode | quotedValNode |
  funcCallNode | setValNode
  ;

Designator Node

The DESIG node encodes a designator.

Graph

desig

S-Expression

designatorNode :=
  '(' DESIG head tail ')'
  ;

head :=
  identNode | qualidentNode | derefNode
  ;

tail :=
  fieldSelectorNode | arrayIndexNode
  ;

Pointer Dereference Node

The DEREF node encodes a pointer dereference.

derefNode :=
  '(' DEREF designator ')'
  ;

Arithmetic Negation Sub-Expression Node

The NEQ node encodes a sub-expression of the form - expr.

negNode :=
  '(' NEG right ')'
  ;

right : exprNode ;

Logical Negation Sub-Expression Node

The NOT node encodes a sub-expression of the form NOT expr.

notNode :=
  '(' NOT right ')'
  ;

Equality Sub-Expression Node

The EQ node encodes a sub-expression of the form expr1 = expr2.

eqNode :=
  '(' EQ left right ')'
  ;

left : exprNode ;

Inequality Sub-Expression Node

The NEQ node encodes a sub-expression of the form expr1 # expr2.

neqNode :=
  '(' NEQ left right ')'
  ;

Less-Than Sub-Expression Node

The LT node encodes a sub-expression of the form expr1 < expr2.

ltNode :=
  '(' LT left right ')'
  ;

Less-Than-Or-Equal Sub-Expression Node

The LTEQ node encodes a sub-expression of the form expr1 <= expr2.

ltEqNode :=
  '(' LTEQ left right ')'
  ;

Greater-Than Sub-Expression Node

The LT node encodes a sub-expression of the form expr1 > expr2.

gtNode :=
  '(' GT left right ')'
  ;

Greater-Than-Or-Equal Sub-Expression Node

The GTEQ node encodes a sub-expression of the form expr1 >= expr2.

gtEqNode :=
  '(' GTEQ left right ')'
  ;

Set Membership Sub-Expression Node

The IN node encodes a sub-expression of the form expr1 IN expr2.

inNode :=
  '(' IN left right ')'
  ;

Plus Sub-Expression Node

The PLUS node encodes a sub-expression of the form expr1 + expr2.

plusNode :=
  '(' PLUS left right ')'
  ;

Minus Sub-Expression Node

The MINUS node encodes a sub-expression of the form expr1 - expr2.

minusNode :=
  '(' '-' left right ')'
  ;

Logical Disjunction Sub-Expression Node

The OR node encodes a sub-expression of the form expr1 OR expr2.

orNode :=
  '(' OR left right ')'
  ;

Asterisk Sub-Expression Node

The ASTERISK node encodes a sub-expression of the form expr1 * expr2.

asteriskNode :=
  '(' ASTERISK left right ')'
  ;

Solidus Sub-Expression Node

The SOLIDUS node encodes a sub-expression of the form expr1 / expr2.

solidusNode :=
  '(' SOLIDUS left right ')'
  ;

Euclidean Division Sub-Expression Node

The DIV node encodes a sub-expression of the form expr1 DIV expr2.

divNode :=
  '(' DIV left right ')'
  ;

Remainder of Euclidean Division Sub-Expression Node

The MOD node encodes a sub-expression of the form expr1 MOD expr2.

modulusNode :=
  '(' MOD left right ')'
  ;

Logical Conjunction Sub-Expression Node

The AND node encodes a sub-expression of the form expr1 AND expr2.

andNode :=
  '(' AND left right ')'
  ;

Function Call Sub-Expression Node

The FCALL node encodes a function call sub-expression.

Graph

fcall

S-Expression

funcCallNode :=
  '( FCALL designator actualParams ')'
  ;

Set Value Sub-Expression Node

The SETVAL node encodes a set value sub-expression.

Graph

setval

S-Expression

setValNode :=
  '( SETVAL setTypeIdent elementList ')'
  ;

setTypeIdent :=
  ident | qualident | emptyNode
  ;

elementList :=
  actualParams | emptyNode
  ;

(87) FILENAME -- File Node

Signature: (FILENAME "filename")

filenameNode := '(' FILENAME '"' filename '"' ')' ;

(88) OPTIONS -- Compiler Options Node

Signature: (OPTIONS "foo" "bar" "baz" ...)

optionsNode := '(' OPTIONS ( '"' option-name '"' )+ ')' ;

(89) IDENT -- Identifier Node

Signature: (IDENT "identifier")

identNode := '(' IDENT '"' Ident '"' ')' ;

Identifier List Node

The IDENTLIST node encodes an identifier list.

Graph

identlist

S-Expression

identListNode :=
  '(' IDENTLIST ( '"' Ident '"' )+ ')'
  ;

Example

(IDENTLIST "foo" "bar" "baz" ...)

Qualified Identifier Node

The QUALIDENT node encodes the component identifiers of a qualified identifier.

Graph

qualident

S-Expression

qualidentNode :=
  '(' QUALIDENT ( '"' Ident '"' ) ( '"' Ident '"' )+ ')'
  ;

Example

(QUALIDENT "foo" "bar" ...)

(92) INTVAL -- Whole Number Value Node

Signature: (INTVAL 12345) | (INTVAL #0x7FFF)

intValNode := '(' INTVAL ( lexeme | '#' lexeme ) ')' ;

(93) REALVAL -- Real Number Value Node

Signature: (REALVAL 1.23e45)

realValNode := '(' REALVAL lexeme ')' ;

(94) CHRVAL -- Character Code Value Node

Signature: (CHRVAL #0u7F)

chrValNode := '(' CHRVAL '#' lexeme ')' ;

(95) QUOTEDVAL -- Quoted Character or String Value Node

Signature: (QUOTEDVAL "quoted character or string")

quotedValNode := '(' QUOTEDVAL '"' lexeme '"' ')' ;

+++

Clone this wiki locally