Difference between revisions of "S2 Guide: Troubleshooting"

From Dreamwidth Notes
Jump to: navigation, search
m
Line 10: Line 10:
  
 
The layer editor won't let you save a layer that contains compiler errors.  Let's say that in the [[S2 Cookbook: A Testbed Layout]], I test some code that has syntax errors where it says "# Code you want to test goes here".  Here are some example situations of the kinds of compile errors I can encounter, and their solution.
 
The layer editor won't let you save a layer that contains compiler errors.  Let's say that in the [[S2 Cookbook: A Testbed Layout]], I test some code that has syntax errors where it says "# Code you want to test goes here".  Here are some example situations of the kinds of compile errors I can encounter, and their solution.
 +
 +
=== Compiler background ===
 +
 +
The compiler is a program that:
 +
 +
* Breaks up the S2 code into little chunks called "tokens" or "nodes"
 +
* Assembles all those tokens into a working program in Perl
 +
 +
If we break the rules of the S2 programming language, the compiler can give errors.
  
 
=== Forgetting to declare a variable ===
 
=== Forgetting to declare a variable ===
Line 53: Line 62:
 
You'll notice that the compiler gives us the line and column (how many characters from the start of the line) the error starts on.  The message in this instance is pretty obvious--it's telling us that that the variable <tt>$test</tt> is unknown.  The traceback afterwards probably isn't too useful to us most people, however.
 
You'll notice that the compiler gives us the line and column (how many characters from the start of the line) the error starts on.  The message in this instance is pretty obvious--it's telling us that that the variable <tt>$test</tt> is unknown.  The traceback afterwards probably isn't too useful to us most people, however.
  
After the error message and traceback, the compiler helpfully gives us some context consisting of the line it had trouble with along with the some surrounding lines.  This helps us find the troublesome place in the code, or see if we can see what the problem is.
+
After the error message and traceback, the compiler helpfully gives us some context consisting of the line it had trouble with, emphasized, along with the some surrounding lines.  This helps us find the troublesome place in the code, or see if we can see what the problem is.
  
 
To fix this problem, we just need to declare the variable before we use it:
 
To fix this problem, we just need to declare the variable before we use it:
Line 130: Line 139:
 
   19:    """</html>""";
 
   19:    """</html>""";
 
   20: }
 
   20: }
 +
 +
Fixing this problem depends on what you were trying to achieve, but you need to make sure you're not trying to match up two values of a different type.
  
 
=== Forgetting the semicolon (;) at the end of a statement ===
 
=== Forgetting the semicolon (;) at the end of a statement ===
Line 160: Line 171:
 
   18:    """</html>""";
 
   18:    """</html>""";
 
   19: }
 
   19: }
   
+
 
 +
The compiler tells us it was expecting a ";" character instead of what it found. Notice that this time, the line the compiler has trouble with is the line <em>after</em> the line we forgot the semicolon on.  That's because you could split statements into two lines, if you wanted to, so the compiler doesn't know that you meant to end that statement there.  Here's an example of that statement (properly ended) across two lines:
 +
 
 +
<syntaxhighlight lang="s2">
 +
    var string test =
 +
        "test";
 +
    var int length = $test->length();
 +
</syntaxhighlight>
 +
 
 +
To fix this problem, we need to put a semicolon at the end of the appropriate line:
 +
 
 +
<syntaxhighlight lang="s2">
 +
    var string test = "test";
 +
    var int length = $test->length();
 +
</syntaxhighlight>
 +
 
 
=== Not putting $ in front of a variable being accessed ===
 
=== Not putting $ in front of a variable being accessed ===
  
Line 201: Line 227:
 
   S2::Compiler, S2/Compiler.pm, 27
 
   S2::Compiler, S2/Compiler.pm, 27
 
    
 
    
 
+
 
  Context
 
  Context
 
   
 
   
Line 218: Line 244:
 
I'm going to put a bracket set ([]) into the exact position the compile error is complaining about:
 
I'm going to put a bracket set ([]) into the exact position the compile error is complaining about:
  
  var int length = test[]->length();</em>
+
  var int length = test[-]>length();</em>
  
 
We can note that if the token the compiler was expecting (<tt>(</tt>) was in that position, it would be as if we were calling a global function. That's because there's no <tt>$</tt> to make the compiler expect a variable instead. If we run through the checklist listed above on this line, however, we'll find that we've broken the rule about <tt>$</tt>s indicating we're using a variable.
 
We can note that if the token the compiler was expecting (<tt>(</tt>) was in that position, it would be as if we were calling a global function. That's because there's no <tt>$</tt> to make the compiler expect a variable instead. If we run through the checklist listed above on this line, however, we'll find that we've broken the rule about <tt>$</tt>s indicating we're using a variable.
Line 265: Line 291:
 
   S2::Compiler, S2/Compiler.pm, 27
 
   S2::Compiler, S2/Compiler.pm, 27
 
    
 
    
+
 
 
  Context
 
  Context
 
   
 
   
Line 277: Line 303:
 
   18:    """</html>""";
 
   18:    """</html>""";
 
   19: }
 
   19: }
 +
 +
Here's a bracket set ([]) in the position the compiler has trouble with:
 +
 +
<syntaxhighlight lang="s2">
 +
    var string test = "test";
 +
    var int length = $test->length[;]
 +
</syntaxhighlight>
 +
 +
Since the compiler is complaining that it didn't expect the token it got, ";", and was expecting a "(" instead, and what we're trying to do is call a function, we put in the brackets and can fix the error:
 +
 +
<syntaxhighlight lang="s2">
 +
    var string test = "test";
 +
    var int length = $test->length();
 +
</syntaxhighlight>
  
 
=== Forgetting the end parentheses on a function call ===
 
=== Forgetting the end parentheses on a function call ===
Line 327: Line 367:
 
   S2::Compiler, S2/Compiler.pm, 27
 
   S2::Compiler, S2/Compiler.pm, 27
 
    
 
    
+
 
 
  Context
 
  Context
 
   
 
   
Line 340: Line 380:
 
   19: }
 
   19: }
 
   
 
   
 +
This isn't a very clear error!  The character it's having trouble with in a bracket set ([]) is:
 +
 +
<syntaxhighlight lang="s2">
 +
    var string test = "test";
 +
    var int length = $test->length([;]
 +
</syntaxhighlight>
 +
 +
We can see that there's a parentheses before it that doesn't get closed, and that's probably why it's telling us it can't parse this particular "node".
 +
 +
Close the parenthesis and things will be fine:
 +
 +
<syntaxhighlight lang="s2">
 +
    var string test = "test";
 +
    var int length = $test->length();
 +
</syntaxhighlight>
 +
 
=== Forgetting code block brackets ===
 
=== Forgetting code block brackets ===
  
Line 377: Line 433:
 
   20:    """</html>""";
 
   20:    """</html>""";
 
   21: }
 
   21: }
 +
 +
This instance is a lot like the missing semicolon ending a statement--the compiler is saying it's expecting a "{" instead of the token it ends up getting.
 +
 +
To fix, add the starting bracket:
 +
 +
<syntaxhighlight lang="s2">
 +
    var int length = 5;
 +
 +
    if ( $length > 4 ) {
 +
        print """This is too big!"""; }
 +
</syntaxhighlight>
  
 
==== Closing ====
 
==== Closing ====
Line 409: Line 476:
 
   10:    """<title>S2 Testbed Layout</title>\n""";
 
   10:    """<title>S2 Testbed Layout</title>\n""";
 
    
 
    
 +
This error is much trickier than the other errors!  Instead of giving us an error anywhere around the code we made the mistake in, it's giving us the line with the <em>previous</em> open bracket, way up at the start of the function we're working in.  However, from the error we know that the compiler wasn't able to match up a set of braces.  It can be hard to figure out where the problem is, but if you go through your program checking to make sure all of your starting braces have closing braces, you'll manage to fix the problem:
 +
 +
<syntaxhighlight lang="s2">
 +
    var int length = 5;
 +
 +
    if ( $length > 4 ) {
 +
        print """This is too big!""";
 +
    }
 +
</syntaxhighlight>
  
 
[[Category: S2 Guide]]
 
[[Category: S2 Guide]]

Revision as of 01:23, 18 June 2010

Syntax checklist

  • Are you ending all statements with a semicolon (;)?
  • Have you declared all variables you are using?
  • Are you using $ when you're accessing variables?
  • Do your function calls have matching parentheses?
  • Do your code blocks have matching brackets?

Deciphering compile errors

The layer editor won't let you save a layer that contains compiler errors. Let's say that in the S2 Cookbook: A Testbed Layout, I test some code that has syntax errors where it says "# Code you want to test goes here". Here are some example situations of the kinds of compile errors I can encounter, and their solution.

Compiler background

The compiler is a program that:

  • Breaks up the S2 code into little chunks called "tokens" or "nodes"
  • Assembles all those tokens into a working program in Perl

If we break the rules of the S2 programming language, the compiler can give errors.

Forgetting to declare a variable

Let's make a really easy error first, to get through the basics. Here's an example where I forget to declare the $test variable before I use it:

    var int length = $test->length();

(This kind of a situation could also happen if I meant to use an existing variable but misspelled its name!)

When I try to save and compile, this is the compiler error I get:

 S2 Compiler Output at Thu Jun 17 10:23:17 2010
Error compiling layer:

Compile error: line 15, column 22: Unknown local variable $test
  S2::NodeVarRef, S2/NodeVarRef.pm, 180
  S2::NodeVarRef, S2/NodeVarRef.pm, 151
  S2::NodeTerm, S2/NodeTerm.pm, 182
  S2::NodeTerm, S2/NodeTerm.pm, 66
  S2::NodeExpr, S2/NodeExpr.pm, 46
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 54
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 108
  S2::NodeFunction, S2/NodeFunction.pm, 230
  S2::Checker, S2/Checker.pm, 374
  S2::Compiler, S2/Compiler.pm, 34
  

Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14: 
 15:     var int length = $test->length();
 16:     
 17:     """</body>""";
 18:     """</html>""";
 19: }

You'll notice that the compiler gives us the line and column (how many characters from the start of the line) the error starts on. The message in this instance is pretty obvious--it's telling us that that the variable $test is unknown. The traceback afterwards probably isn't too useful to us most people, however.

After the error message and traceback, the compiler helpfully gives us some context consisting of the line it had trouble with, emphasized, along with the some surrounding lines. This helps us find the troublesome place in the code, or see if we can see what the problem is.

To fix this problem, we just need to declare the variable before we use it:

    var string test = "test";
    var int length = $test->length();

Mixing up variable types

What happens if we try to assign the value from one type of variable to a variable with a different type?

    var string test = "test";
    var int length = $test;

Resulting compile error:

 S2 Compiler Output at Thu Jun 17 16:06:44 2010
Error compiling layer:

Compile error: line 15, column 5: Can't initialize variable 'length' of type int with expression of type string
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 55
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 108
  S2::NodeFunction, S2/NodeFunction.pm, 230
  S2::Checker, S2/Checker.pm, 374
  S2::Compiler, S2/Compiler.pm, 34
  

Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14:     var string test = "test";
 15:     var int length = $test;
 16:     
 17:     """</body>""";
 18:     """</html>""";
 19: }

If we're assigning to a variable that's not being declared at the same time:

    var string test = "test";
    var int length;
    $length = $test;

The error is slightly different:

 S2 Compiler Output at Thu Jun 17 16:12:35 2010
Error compiling layer:

Compile error: line 16, column 5: Can't assign type string to int
  S2::NodeAssignExpr, S2/NodeAssignExpr.pm, 73
  S2::NodeExpr, S2/NodeExpr.pm, 46
  S2::NodeExprStmt, S2/NodeExprStmt.pm, 35
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 108
  S2::NodeFunction, S2/NodeFunction.pm, 230
  S2::Checker, S2/Checker.pm, 374
  S2::Compiler, S2/Compiler.pm, 34
  

Context

 12:     """<body>""";
 13: 
 14:     var string test = "test";
 15:     var int length;
 16:     $length = $test;
 17: 
 18:     """</body>""";
 19:     """</html>""";
 20: }

Fixing this problem depends on what you were trying to achieve, but you need to make sure you're not trying to match up two values of a different type.

Forgetting the semicolon (;) at the end of a statement

    var string test = "test"
    var int length = $test->length();
Compile error: line 15, column 5: Unexpected token found.  Expecting: [TokenPunct] = ;
Got: [TokenKeyword] = var
  S2::Node, S2/Node.pm, 144
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 35
  S2::NodeStmt, S2/NodeStmt.pm, 62
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 43
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
  

Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14:     var string test = "test"
 15:     var int length = $test->length();
 16: 
 17:     """</body>""";
 18:     """</html>""";
 19: }

The compiler tells us it was expecting a ";" character instead of what it found. Notice that this time, the line the compiler has trouble with is the line after the line we forgot the semicolon on. That's because you could split statements into two lines, if you wanted to, so the compiler doesn't know that you meant to end that statement there. Here's an example of that statement (properly ended) across two lines:

    var string test = 
        "test";
    var int length = $test->length();

To fix this problem, we need to put a semicolon at the end of the appropriate line:

    var string test = "test";
    var int length = $test->length();

Not putting $ in front of a variable being accessed

Here's some code where I forgot to put a $ in front of a variable I am using:

    var string test = "test";
    var int length = test->length();

This is the compiler error I get:

S2 Compiler Output at Thu Jun 17 10:13:02 2010
Error compiling layer:

Compile error: line 15, column 26: Unexpected token found.  Expecting [TokenPunct] = (
Got: [TokenPunct] = ->
  S2::Node, S2/Node.pm, 144
  S2::NodeArguments, S2/NodeArguments.pm, 25
  S2::NodeTerm, S2/NodeTerm.pm, 471
  S2::NodeIncExpr, S2/NodeIncExpr.pm, 41
  S2::NodeTypeCastOp, S2/NodeTypeCastOp.pm, 29
  S2::NodeInstanceOf, S2/NodeInstanceOf.pm, 29
  S2::NodeUnaryExpr, S2/NodeUnaryExpr.pm, 40
  S2::NodeProduct, S2/NodeProduct.pm, 28
  S2::NodeSum, S2/NodeSum.pm, 31
  S2::NodeRelExpr, S2/NodeRelExpr.pm, 29
  S2::NodeEqExpr, S2/NodeEqExpr.pm, 29
  S2::NodeLogAndExpr, S2/NodeLogAndExpr.pm, 29
  S2::NodeLogOrExpr, S2/NodeLogOrExpr.pm, 29
  S2::NodeRange, S2/NodeRange.pm, 29
  S2::NodeCondExpr, S2/NodeCondExpr.pm, 29
  S2::NodeAssignExpr, S2/NodeAssignExpr.pm, 29
  S2::NodeExpr, S2/NodeExpr.pm, 29
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 33
  S2::NodeStmt, S2/NodeStmt.pm, 62
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 43
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
 

Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14:     var string test = "test";
 15:     var int length = test->length();
 16:     
 17:     """</body>""";
 18:     """</html>""";
 19: }

You'll note that the compiler error doesn't tell us exactly what the problem is. It tells us what "token" (part of the programming language) it was expecting, and what it got.

I'm going to put a bracket set ([]) into the exact position the compile error is complaining about:

var int length = test[-]>length();</em>

We can note that if the token the compiler was expecting (() was in that position, it would be as if we were calling a global function. That's because there's no $ to make the compiler expect a variable instead. If we run through the checklist listed above on this line, however, we'll find that we've broken the rule about $s indicating we're using a variable.

To fix the error, we put the $ character in front of the variable we're trying to access.

    var string test = "test";
    var int length = $test->length();

Forgetting to use parentheses on a function call

    var string test = "test";
    var int length = $test->length;
 S2 Compiler Output at Thu Jun 17 16:30:31 2010
Error compiling layer:

Compile error: line 15, column 35: Unexpected token found.  Expecting: [TokenPunct] = (
Got: [TokenPunct] = ;
  S2::Node, S2/Node.pm, 144
  S2::NodeArguments, S2/NodeArguments.pm, 25
  S2::NodeTerm, S2/NodeTerm.pm, 471
  S2::NodeIncExpr, S2/NodeIncExpr.pm, 41
  S2::NodeTypeCastOp, S2/NodeTypeCastOp.pm, 29
  S2::NodeInstanceOf, S2/NodeInstanceOf.pm, 29
  S2::NodeUnaryExpr, S2/NodeUnaryExpr.pm, 40
  S2::NodeProduct, S2/NodeProduct.pm, 28
  S2::NodeSum, S2/NodeSum.pm, 31
  S2::NodeRelExpr, S2/NodeRelExpr.pm, 29
  S2::NodeEqExpr, S2/NodeEqExpr.pm, 29
  S2::NodeLogAndExpr, S2/NodeLogAndExpr.pm, 29
  S2::NodeLogOrExpr, S2/NodeLogOrExpr.pm, 29
  S2::NodeRange, S2/NodeRange.pm, 29
  S2::NodeCondExpr, S2/NodeCondExpr.pm, 29
  S2::NodeAssignExpr, S2/NodeAssignExpr.pm, 29
  S2::NodeExpr, S2/NodeExpr.pm, 29
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 33
  S2::NodeStmt, S2/NodeStmt.pm, 62
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 43
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
  
  
Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14:     var string test = "test";
 15:     var int length = $test->length;
 16: 
 17:     """</body>""";
 18:     """</html>""";
 19: }

Here's a bracket set ([]) in the position the compiler has trouble with:

    var string test = "test";
    var int length = $test->length[;]

Since the compiler is complaining that it didn't expect the token it got, ";", and was expecting a "(" instead, and what we're trying to do is call a function, we put in the brackets and can fix the error:

    var string test = "test";
    var int length = $test->length();

Forgetting the end parentheses on a function call

    var string test = "test";
    var int length = $test->length(;
 S2 Compiler Output at Thu Jun 17 16:37:46 2010
Error compiling layer:

Compile error: line 15, column 36: Can't finish parsing NodeTerm
  S2::NodeTerm, S2/NodeTerm.pm, 484
  S2::NodeIncExpr, S2/NodeIncExpr.pm, 41
  S2::NodeTypeCastOp, S2/NodeTypeCastOp.pm, 29
  S2::NodeInstanceOf, S2/NodeInstanceOf.pm, 29
  S2::NodeUnaryExpr, S2/NodeUnaryExpr.pm, 40
  S2::NodeProduct, S2/NodeProduct.pm, 28
  S2::NodeSum, S2/NodeSum.pm, 31
  S2::NodeRelExpr, S2/NodeRelExpr.pm, 29
  S2::NodeEqExpr, S2/NodeEqExpr.pm, 29
  S2::NodeLogAndExpr, S2/NodeLogAndExpr.pm, 29
  S2::NodeLogOrExpr, S2/NodeLogOrExpr.pm, 29
  S2::NodeRange, S2/NodeRange.pm, 29
  S2::NodeCondExpr, S2/NodeCondExpr.pm, 29
  S2::NodeAssignExpr, S2/NodeAssignExpr.pm, 29
  S2::NodeExpr, S2/NodeExpr.pm, 29
  S2::NodeArguments, S2/NodeArguments.pm, 33
  S2::NodeTerm, S2/NodeTerm.pm, 471
  S2::NodeIncExpr, S2/NodeIncExpr.pm, 41
  S2::NodeTypeCastOp, S2/NodeTypeCastOp.pm, 29
  S2::NodeInstanceOf, S2/NodeInstanceOf.pm, 29
  S2::NodeUnaryExpr, S2/NodeUnaryExpr.pm, 40
  S2::NodeProduct, S2/NodeProduct.pm, 28
  S2::NodeSum, S2/NodeSum.pm, 31
  S2::NodeRelExpr, S2/NodeRelExpr.pm, 29
  S2::NodeEqExpr, S2/NodeEqExpr.pm, 29
  S2::NodeLogAndExpr, S2/NodeLogAndExpr.pm, 29
  S2::NodeLogOrExpr, S2/NodeLogOrExpr.pm, 29
  S2::NodeRange, S2/NodeRange.pm, 29
  S2::NodeCondExpr, S2/NodeCondExpr.pm, 29
  S2::NodeAssignExpr, S2/NodeAssignExpr.pm, 29
  S2::NodeExpr, S2/NodeExpr.pm, 29
  S2::NodeVarDeclStmt, S2/NodeVarDeclStmt.pm, 33
  S2::NodeStmt, S2/NodeStmt.pm, 62
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 43
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
  
 
Context

 11:     """</head>""";
 12:     """<body>""";
 13: 
 14:     var string test = "test";
 15:     var int length = $test->length(;
 16: 
 17:     """</body>""";
 18:     """</html>""";
 19: }

This isn't a very clear error! The character it's having trouble with in a bracket set ([]) is:

    var string test = "test";
    var int length = $test->length([;]

We can see that there's a parentheses before it that doesn't get closed, and that's probably why it's telling us it can't parse this particular "node".

Close the parenthesis and things will be fine:

    var string test = "test";
    var int length = $test->length();

Forgetting code block brackets

Starting

    var int length = 5;
 
    if ( $length > 4 ) 
        print """This is too big!"""; }
 S2 Compiler Output at Thu Jun 17 16:37:46 2010
Error compiling layer:

Compile error: line 17, column 9: Unexpected token found.  Expecting: [TokenPunct] = {
Got: [TokenKeyword] = print
  S2::Node, S2/Node.pm, 144
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 27
  S2::NodeIfStmt, S2/NodeIfStmt.pm, 35
  S2::NodeStmt, S2/NodeStmt.pm, 41
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 43
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
  

Context

 13: 
 14:     var int length = 5;
 15: 
 16:     if ( $length > 4 ) 
 17:         print """This is too big!"""; }
 18: 
 19:     """</body>""";
 20:     """</html>""";
 21: }

This instance is a lot like the missing semicolon ending a statement--the compiler is saying it's expecting a "{" instead of the token it ends up getting.

To fix, add the starting bracket:

    var int length = 5;
 
    if ( $length > 4 ) {
        print """This is too big!"""; }

Closing

    var int length = 5;
 
    if ( $length > 4 ) {
        print """This is too big!""";
 S2 Compiler Output at Thu Jun 17 16:37:46 2010
Error compiling layer:

Compile error: line 6, column 1: Didn't find closing brace in statement block
  S2::NodeStmtBlock, S2/NodeStmtBlock.pm, 52
  S2::NodeFunction, S2/NodeFunction.pm, 104
  S2::Layer, S2/Layer.pm, 59
  S2::Compiler, S2/Compiler.pm, 27
  

Context

  2: layerinfo "name" = "S2 Testbed Layout";
  3: 
  4: function Page::print()
  5: "This is a skeleton page function, for testing."
  6: {
  7:     """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" """;
  8:     """"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n""";
  9:     """<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n""";
 10:     """<title>S2 Testbed Layout</title>\n""";
 

This error is much trickier than the other errors! Instead of giving us an error anywhere around the code we made the mistake in, it's giving us the line with the previous open bracket, way up at the start of the function we're working in. However, from the error we know that the compiler wasn't able to match up a set of braces. It can be hard to figure out where the problem is, but if you go through your program checking to make sure all of your starting braces have closing braces, you'll manage to fix the problem:

    var int length = 5;
 
    if ( $length > 4 ) {
        print """This is too big!""";
    }