Revisions:

  1. (Mar 14) Fixed typos on scope production

This document outlines the processing required to perform a full semantic analysis for a Source language program. The annotated grammar below adds references to additional semantic analysis operators in blue that refer to specific semantic checks that should be performed.

Annotated grammar

program: SCtopBegin bareScope SCtopEnd # program top-level

bareScope: declarations SCdecls # only declarations
| declarations SCdecls statements # both declarations and statements
| statements # only statements

scope: SCminorBegin { bareScope } SCminorEnd # scope enclosed with braces
| { } # empty scope

statements: variable = expression CTassign # assignment
| if expression CTbool scope # conditional statement
| if expression CTbool scope elseIfArms
| if expression CTbool scope else scope
| if expression CTbool scope elseIfArms else scope
| while expression CTbool scope # loop while expression is true
| repeat scope until expression CTbool # loop until expression is true
| break STbreak # exit out of enclosing loop
| break integer STbreak STloopDepth # exit out of multiple enclosing loops
| return ( expression ) STreturnFunc CTreturn # return from a function
| return STreturnProc # return from a procedure
| print outputs # print to standard output
| input inputs # input from standard input
| procedureName ( ) RzeroArgs # procedure call (no arguments)
| procedureName ( arguments ) RmatchArgs # procedure call (with arguments)
| scope # nested scope
| statements statements # sequence of statements

elseIfArms: else if expression CTbool scope # else-if arm
| elseIfArms elseIfArms # sequence of else-if arms

declarations: var variableNames compoundType Dvariables # declare variables
| func SCprocBegin procedureName ( ) Dproc scope SCprocEnd DlinkScope
| func SCprocBegin procedureName ( parameters ) Dproc scope SCprocEnd DlinkScope
| func SCfuncBegin functionName ( ) scalarType Dfunc scope SCfuncEnd SThasReturn DlinkScope
| func SCfuncBegin functionName ( parameters ) scalarType Dfunc scope SCfuncEnd SThasReturn DlinkScope
| declarations declarations # sequence of declarations

variableNames: variableName
| variableNames , variableNames # comma separated sequence of variable names

scalarType: integer Tint # integer type
| boolean Tbool # Boolean type

compoundType: scalarType
| [ bound ] scalarType # 1-dimensional array type
| [ bound ] [ bound ] scalarType # 2-dimensional array type

bound: integer # array of length integer

parameters: parameterNames scalarType Dparams # declare one or more formal parameters
| parameters , parameters # sequence of formal parameters

parameterNames: parameterName
| parameterNames , parameterNames # comma separated sequence of parameter names

arguments: expression CTargument
| arguments , arguments # comma separated sequence of arguments

outputs: expression # integer or Boolean expression value to be printed
| text # string constant to be printed
| newline # print newline
| outputs , outputs # sequence of output arguments

inputs: variable CTint # input to this integer variable
| inputs , inputs # input sequence

variable: variableName Tvar # reference to scalar variable
| arrayName [ expression CTint ] Tarr # reference to 1-dimensional array element
| arrayName [ expression CTint ] [ expression CTint ] Tarr # reference to 2-dimensional array element

expression: integer Tint # literal integer constant
| - expression CTint Tint # unary minus
| expression CTint + expression CTint Tint # addition
| expression CTint - expression CTint Tint # subtraction
| expression CTint * expression CTint Tint # multiplication
| expression CTint / expression CTint Tint # integer division
| true Tbool # Boolean constant true
| false Tbool # Boolean constant false
| not expression CTbool Tbool # Boolean not
| expression CTbool and expression CTbool Tbool # Conditional Boolean and
| expression CTbool or expression CTbool Tbool # Conditional Boolean or
| expression = expression CTmatch Tbool # equality comparison
| expression != expression CTmatch Tbool # inequality comparison
| expression CTint < expression CTint Tbool # less-than comparison
| expression CTint <= expression CTint Tbool # less-than-or-equal comparison
| expression CTint > expression CTint Tbool # greater-than comparison
| expression CTint >= expression CTint Tbool # greater-than-or-equal comparison
| ( expression ) Texpr
| ( expression if expression CTbool else expression ) CTvalues Tcond # Python-style ternary conditional expression
| variable # reference to local variable
| functionName ( ) RzeroArgs Treturn # function call (no arguments)
| functionName ( arguments ) RmatchArgs Treturn # function call (with arguments)
| parameterName Tparam # reference to a formal parameter

variableName: identifier CTscalar
arrayName: identifier CTarray
functionName: identifier RfuncId
parameterName: identifier CTparam
procedureName: identifier RprocId

Semantic analysis operators

Scopes

Declarations

Statements

Expression types

Expression type checking

Functions and procedures

Analysis summary

Correct operation of a semantic analyzer

The meaning of "directly inside"

The definitions of STbreak, STloopDepth, STreturnFunc and STreturnProc refer to being directly inside of, or within a directly enclosing loop, function or procedure. This refers to statements that would otherwise be legal, except for the presence of the loop or procedure/function between the statement and the intended enclosing context. These restrictions should reset at procedure and function boundaries. For example:

func F() integer {
    func P() {
        return (488)    // illegal, violates STreturnFunc
    }
}
func Q() {
    func G() integer {
        return          // illegal, violates STreturnProc
    }
}
while true {
    func R() {
        break           // illegal, violates STbreak
    }

    func H() integer {
        break 1         // still illegal
    }
}
while true {
    func S() {
        while true {
            break 2     // illegal, violates STloopDepth
        }
    }
}
func J() boolean {
    while true {
        func T() {
            repeat {
                if false {
                    break       // legal, within a loop
                } else {
                    return      // legal, also within a procedure
                }
            } until true
        }
    }
}

Do not change the Source language syntax

This document is a companion to the Source language specification, and should not be seen to change that specification in any way. Nor should you, through your implementation of a semantic analyzer, change the syntax of the language in any way. If you find any point on which these two documents disagree, please report this to the instructor and consider this document to be in error.