Commits

Anonymous committed 4d81ada Merge

Merge parser.test with lispdev

Comments (0)

Files changed (7)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.lispdev.parser.test</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

.settings/org.eclipse.jdt.core.prefs

+#Mon Jun 22 16:01:33 BST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

META-INF/MANIFEST.MF

+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Test
+Bundle-SymbolicName: org.lispdev.parser.test
+Bundle-Version: 1.0.0.qualifier
+Fragment-Host: org.lispdev.parser;bundle-version="0.0.1"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.junit4
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .

src/org/lispdev/parser/test/lexerTest.java

+package org.lispdev.parser.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.lispdev.parser.LispCharStream;
+import org.lispdev.parser.LispLexer;
+
+public class lexerTest
+{
+  @Test
+  public void general()
+  {
+    String code = "|good|";
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals("[<sym:0+6:|good|>, <EOF:6>]", res);
+
+    code = ":";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<key:0+1::>, <EOF:1>]",
+        res);
+
+    code = "(documentation 'fliptree 'function)\n";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<TL(:0>, " +
+        "<sym:1+13:documentation>, " +
+        "<ws:14+1: >, " +
+        "<':15>, " +
+        "<sym:16+8:fliptree>, " +
+        "<ws:24+1: >, " +
+        "<':25>, " +
+        "<sym:26+8:function>, " +
+        "<):34>, " +
+        "<ws:35+1:\\n>, " +
+        "<EOF:36>]",
+        res);
+
+    code = " (do-randomly \r\n" +
+            "    (print \"zero\")\r\n" +
+            "    (print \"one\")\r\n" +
+            "    (print \"two)\r\n" +
+            "    (print \"three\"))\r\n" +
+            "";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<ws:0+1: >, " +
+        "<(:1>, " +
+        "<sym:2+11:do-randomly>, " +
+        "<ws:13+7: \\r\\n    >, " +
+        "<(:20>, " +
+        "<sym:21+5:print>, " +
+        "<ws:26+1: >, " +
+        "<str:27+6:\"zero\">, " +
+        "<):33>, " +
+        "<ws:34+6:\\r\\n    >, " +
+        "<(:40>, " +
+        "<sym:41+5:print>, " +
+        "<ws:46+1: >, " +
+        "<str:47+5:\"one\">, " +
+        "<):52>, " +
+        "<ws:53+6:\\r\\n    >, " +
+        "<(:59>, " +
+        "<sym:60+5:print>, " +
+        "<ws:65+1: >, " +
+        "<str:66+19:\"two)\\r\\n    (print \">, " +
+        "<sym:85+5:three>, " +
+        "<str:90+3:\")):E(93+1:\"<-\\r)>, " +
+        "<ws:93+2:\\r\\n>, " +
+        "<EOF:95>]", res);
+
+    code = "\"this is not \\\" finished string";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<str:0+31:\"this is not \\\" finished string:E(31+1:\"<-EOF)>, " +
+        "<EOF:31>]",
+        res);
+  }
+
+
+  @Test
+  public void testReadSLC()
+  {
+    LispCharStream stream =
+      new LispCharStream(";; this and that\r\n; an again");
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals("[<slc:0+16:;; this and that>, <ws:16+2:\\r\\n>, " +
+    		"<slc:18+10:; an again>, <EOF:28>]",
+    		res);
+  }
+
+  @Test
+  public void testReadBarSymbol()
+  {
+    String code = "|good|";
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals("[<sym:0+6:|good|>, <EOF:6>]", res);
+
+    code = "ab|some more\r";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+7:ab|some:E(7+1:|<- )>, " +
+        "<ws:7+1: >, <sym:8+4:more>, <ws:12+1:\\r>, " +
+        "<EOF:13>]",
+        res);
+
+    code = "ab|some more\r\n and more";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    lexer.setMaxSymbolLines(2);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+7:ab|some:E(7+1:|<- )>, " +
+        "<ws:7+1: >, " +
+        "<sym:8+4:more>, " +
+        "<ws:12+3:\\r\\n >, " +
+        "<sym:15+3:and>, " +
+        "<ws:18+1: >, " +
+        "<sym:19+4:more>, " +
+        "<EOF:23>]",
+        res);
+
+    code = "ab|some more\r\n and more|a";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    lexer.setMaxSymbolLines(2);
+    res = lexer.parse().toString();
+    assertEquals("[<sym:0+25:ab|some more\\r\\n and more|a>, <EOF:25>]",
+        res);
+
+    code = "ab|some more";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+7:ab|some:E(7+1:|<- )>, " +
+        "<ws:7+1: >, " +
+        "<sym:8+4:more>, " +
+        "<EOF:12>]",
+        res);
+
+    code = "ab|some \\| more|d";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals("[<sym:0+17:ab|some \\| more|d>, <EOF:17>]", res);
+
+    code = "ab|some\\ and more";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+12:ab|some\\ and:E(12+1:|<- )>, " +
+        "<ws:12+1: >, " +
+        "<sym:13+4:more>, " +
+        "<EOF:17>]",
+        res);
+
+    code = "ab|some\\ and more|\\a\\\\a\\||\\n this\\|\\ |ab(";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+40:ab|some\\ and more|\\a\\\\a\\||\\n this\\|\\ |ab>, " +
+        "<(:40>, " +
+        "<EOF:41>]",
+        res);
+
+    code = "ab|some\\ and more|\\a\\\\a\\||\n this\\|\\ ab(";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+26:ab|some\\ and more|\\a\\\\a\\||:E(26+1:|<-\\n)>, " +
+        "<ws:26+2:\\n >, " +
+        "<sym:28+10:this\\|\\ ab>, " +
+        "<(:38>, " +
+        "<EOF:39>]",
+        res);
+
+    code = "ab|cd\n";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+5:ab|cd:E(5+1:|<-\\n)>, <ws:5+1:\\n>, <EOF:6>]",
+        res);
+
+    code = "ab|cd";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+5:ab|cd:E(5+1:|<-EOF)>, <EOF:5>]",
+        res);
+  }
+
+  @Test
+  public void parseErrorsTest1()
+  {
+    final String code = "(a f (x) \"this is a string\" "
+      + "(\"and this\" 1) \"finally this\")\n\n"
+      + "\n;;;;; 0.1 s(ect)ion\n"
+      + "(a 1 2 \"tt\"\n"
+      + "(defun g (x) 4\n\n" //<-- no closing bracket
+      + ";;;; 1. section"
+      + "\n;;;;; 1.1 section \n\n"
+      + "(defun g (x) 3)\n\n" //<-- no closing bracket
+      + ";;;; 2. section";
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals(
+        "[<TL(:0>, " +
+        "<sym:1+1:a>, " +
+        "<ws:2+1: >, " +
+        "<sym:3+1:f>, " +
+        "<ws:4+1: >, " +
+        "<(:5>, " +
+        "<sym:6+1:x>, " +
+        "<):7>, " +
+        "<ws:8+1: >, " +
+        "<str:9+18:\"this is a string\">, " +
+        "<ws:27+1: >, " +
+        "<(:28>, " +
+        "<str:29+10:\"and this\">, " +
+        "<ws:39+1: >, " +
+        "<num:40+1:1>, " +
+        "<):41>, " +
+        "<ws:42+1: >, " +
+        "<str:43+14:\"finally this\">, " +
+        "<):57>, " +
+        "<ws:58+3:\\n\\n\\n>, " +
+        "<outline:61+19:;;;;; 0.1 s(ect)ion>, " +
+        "<ws:80+1:\\n>, " +
+        "<TL(:81>, " +
+        "<sym:82+1:a>, " +
+        "<ws:83+1: >, " +
+        "<num:84+1:1>, " +
+        "<ws:85+1: >, " +
+        "<num:86+1:2>, " +
+        "<ws:87+1: >, " +
+        "<str:88+4:\"tt\">, " +
+        "<ws:92+1:\\n>, " +
+        "<TL(:93>, " +
+        "<sym:94+5:defun>, " +
+        "<ws:99+1: >, " +
+        "<sym:100+1:g>, " +
+        "<ws:101+1: >, " +
+        "<(:102>, " +
+        "<sym:103+1:x>, " +
+        "<):104>, " +
+        "<ws:105+1: >, " +
+        "<num:106+1:4>, " +
+        "<ws:107+2:\\n\\n>, " +
+        "<outline:109+15:;;;; 1. section>, " +
+        "<ws:124+1:\\n>, " +
+        "<outline:125+18:;;;;; 1.1 section >, " +
+        "<ws:143+2:\\n\\n>, " +
+        "<TL(:145>, " +
+        "<sym:146+5:defun>, " +
+        "<ws:151+1: >, " +
+        "<sym:152+1:g>, " +
+        "<ws:153+1: >, " +
+        "<(:154>, " +
+        "<sym:155+1:x>, " +
+        "<):156>, " +
+        "<ws:157+1: >, " +
+        "<num:158+1:3>, " +
+        "<):159>, " +
+        "<ws:160+2:\\n\\n>, " +
+        "<outline:162+15:;;;; 2. section>, " +
+        "<EOF:177>]",
+        res);
+  }
+
+  @Test
+  public void parseMLCErrorsTest2()
+  {
+    String code =
+      "((a b) |# c)\n()\n abc \n(c ( ( #|aa a#b)\n\n(a (\"(a#g b)))\n(a)\n#|this";
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals(
+        "[<TL(:0>, " +
+        "<(:1>, " +
+        "<sym:2+1:a>, " +
+        "<ws:3+1: >, " +
+        "<sym:4+1:b>, " +
+        "<):5>, " +
+        "<ws:6+1: >, " +
+        "<sym:7+2:|#:E(9+1:|<- )>, " +
+        "<ws:9+1: >, " +
+        "<sym:10+1:c>, " +
+        "<):11>, " +
+        "<ws:12+1:\\n>, " +
+        "<TL(:13>, " +
+        "<):14>, " +
+        "<ws:15+2:\\n >, " +
+        "<sym:17+3:abc>, " +
+        "<ws:20+2: \\n>, " +
+        "<TL(:22>, " +
+        "<sym:23+1:c>, " +
+        "<ws:24+1: >, " +
+        "<(:25>, " +
+        "<ws:26+1: >, " +
+        "<(:27>, " +
+        "<ws:28+1: >, " +
+        "<mlc:29+9:#|aa a#b):E(38+1:|#<-\\n)>, " +
+        "<ws:38+2:\\n\\n>, " +
+        "<TL(:40>, " +
+        "<sym:41+1:a>, " +
+        "<ws:42+1: >, " +
+        "<(:43>, " +
+        "<str:44+10:\"(a#g b))):E(54+1:\"<-\\n)>, " +
+        "<ws:54+1:\\n>, " +
+        "<TL(:55>, " +
+        "<sym:56+1:a>, " +
+        "<):57>, " +
+        "<ws:58+1:\\n>, " +
+        "<mlc:59+6:#|this:E(65+1:|#<-EOF)>, " +
+        "<EOF:65>]",
+        res);
+
+    code =
+      "a#|this|# #|multilevel #|comment|#stop |#";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<sym:0+9:a#|this|#>, " +
+        "<ws:9+1: >, " +
+        "<mlc:10+31:#|multilevel #|comment|#stop |#>, " +
+        "<EOF:41>]",
+        res);
+  }
+
+  @Test
+  public void quotesAndOthers()
+  {
+    // back quote, comma, @, quote
+    String code = "(`a f `(x) \"this is a string\" (`\"and this\" 1))\n\n"
+      + "(defun g ,(x) 4`\n\n" //<-- no closing bracket
+      + "\n`;;;;; 1.1 section \n\n"
+      + "(defun ,@g '(x) ' 3`2)\n\n"; //<-- no closing bracket
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals(
+        "[<TL(:0>, " +
+        "<`:1>, " +
+        "<sym:2+1:a>, " +
+        "<ws:3+1: >, " +
+        "<sym:4+1:f>, " +
+        "<ws:5+1: >, " +
+        "<`:6>, " +
+        "<(:7>, " +
+        "<sym:8+1:x>, " +
+        "<):9>, " +
+        "<ws:10+1: >, " +
+        "<str:11+18:\"this is a string\">, " +
+        "<ws:29+1: >, " +
+        "<(:30>, " +
+        "<`:31>, " +
+        "<str:32+10:\"and this\">, " +
+        "<ws:42+1: >, " +
+        "<num:43+1:1>, " +
+        "<):44>, " +
+        "<):45>, " +
+        "<ws:46+2:\\n\\n>, " +
+        "<TL(:48>, " +
+        "<sym:49+5:defun>, " +
+        "<ws:54+1: >, " +
+        "<sym:55+1:g>, " +
+        "<ws:56+1: >, " +
+        "<,:57>, " +
+        "<(:58>, " +
+        "<sym:59+1:x>, " +
+        "<):60>, " +
+        "<ws:61+1: >, " +
+        "<num:62+1:4>, " +
+        "<`:63>, " +
+        "<ws:64+3:\\n\\n\\n>, " +
+        "<`:67>, " +
+        "<slc:68+18:;;;;; 1.1 section >, " +
+        "<ws:86+2:\\n\\n>, " +
+        "<TL(:88>, " +
+        "<sym:89+5:defun>, " +
+        "<ws:94+1: >, " +
+        "<,@:95>, " +
+        "<sym:97+1:g>, " +
+        "<ws:98+1: >, " +
+        "<':99>, " +
+        "<(:100>, " +
+        "<sym:101+1:x>, " +
+        "<):102>, " +
+        "<ws:103+1: >, " +
+        "<':104>, " +
+        "<ws:105+1: >, " +
+        "<num:106+1:3>, " +
+        "<`:107>, " +
+        "<num:108+1:2>, " +
+        "<):109>, " +
+        "<ws:110+2:\\n\\n>, " +
+        "<EOF:112>]",
+        res);
+
+    // period
+    code = "(this . that .. and ...a and .1 .| )"; //just one dot
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<TL(:0>, " +
+        "<sym:1+4:this>, " +
+        "<ws:5+1: >, " +
+        "<.:6>, " +
+        "<ws:7+1: >, " +
+        "<sym:8+4:that>, " +
+        "<ws:12+1: >, " +
+        "<sym:13+2:..:E(13+2:null<-too many dots)>, " +
+        "<ws:15+1: >, " +
+        "<sym:16+3:and>, " +
+        "<ws:19+1: >, " +
+        "<sym:20+4:...a>, " +
+        "<ws:24+1: >, " +
+        "<sym:25+3:and>, " +
+        "<ws:28+1: >, " +
+        "<num:29+2:.1>, " +
+        "<ws:31+1: >, " +
+        "<sym:32+2:.|:E(34+1:|<- )>, " +
+        "<ws:34+1: >, " +
+        "<):35>, " +
+        "<EOF:36>]",
+        res);
+  }
+
+  @Test
+  public void testMacro()
+  {
+    // bit vector and EOF
+    String code = "#*101af31 #*101101(#* #*13|ab\n #";
+    LispCharStream stream = new LispCharStream(code);
+    LispLexer lexer = new LispLexer(stream);
+    String res = lexer.parse().toString();
+    assertEquals(
+        "[<#*:0+9:#*101af31>, " +
+        "<ws:9+1: >, " +
+        "<#*:10+8:#*101101>, " +
+        "<(:18>, " +
+        "<#*:19+2:#*:E(21+1:0 or 1<- )>, " +
+        "<ws:21+1: >, " +
+        "<#*:22+7:#*13|ab:E(29+1:|<-\\n)>, " +
+        "<ws:29+2:\\n >, " +
+        "<bad:31+1:#:E(31+1:null<-null)>, " +
+        "<EOF:32>]",
+        res);
+
+    // char
+    code = "#\\abcd #\\! #\\\\ #\\\na|a\nbs #\\\n #\\";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<char:0+6:#\\abcd>, " +
+        "<ws:6+1: >, " +
+        "<char:7+3:#\\!>, " +
+        "<ws:10+1: >, " +
+        "<char:11+3:#\\\\>, " +
+        "<ws:14+1: >, " +
+        "<char:15+6:#\\\\na|a:E(21+1:|<-\\n)>, " +
+        "<ws:21+1:\\n>, " +
+        "<sym:22+2:bs>, " +
+        "<ws:24+1: >, " +
+        "<char:25+3:#\\\\n>, " +
+        "<ws:28+1: >, " +
+        "<char:29+2:#\\:E(30+1:any char<-EOF)>, " +
+        "<EOF:31>]",
+        res);
+
+    // vector, structure, complex, fun namespace
+    code = "#() #s (a b) #Sab #C#c #c #'ab # ";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<#(:0>, " +
+        "<):2>, " +
+        "<ws:3+1: >, " +
+        "<#s:4>, " +
+        "<ws:6+1: >, " +
+        "<(:7>, " +
+        "<sym:8+1:a>, " +
+        "<ws:9+1: >, " +
+        "<sym:10+1:b>, " +
+        "<):11>, " +
+        "<ws:12+1: >, " +
+        "<#s:13>, " +
+        "<sym:15+2:ab>, " +
+        "<ws:17+1: >, " +
+        "<#c:18>, " +
+        "<#c:20>, " +
+        "<ws:22+1: >, " +
+        "<#c:23>, " +
+        "<ws:25+1: >, " +
+        "<#':26>, " +
+        "<sym:28+2:ab>, " +
+        "<ws:30+1: >, " +
+        "<bad:31+1:#:E(31+1:null<-null)>, " +
+        "<ws:32+1: >, " +
+        "<EOF:33>]",
+        res);
+
+    // unreadable
+    code = "#<this is an object> #<and this\n";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<T:0+20:#<this is an object>>, " +
+        "<ws:20+1: >, " +
+        "<T:21+10:#<and this:E(31+1:><-\\n)>, " +
+        "<ws:31+1:\\n>, " +
+        "<EOF:32>]",
+        res);
+
+    // radix
+    code = "#adfadf;kajga \n#x123134 #01r3124\\\na #1a|a";
+    stream = new LispCharStream(code);
+    lexer = new LispLexer(stream);
+    res = lexer.parse().toString();
+    assertEquals(
+        "[<num:0+7:#adfadf>, " +
+        "<slc:7+7:;kajga >, " +
+        "<ws:14+1:\\n>, " +
+        "<num:15+8:#x123134>, " +
+        "<ws:23+1: >, " +
+        "<num:24+11:#01r3124\\\\na>, " +
+        "<ws:35+1: >, " +
+        "<num:36+5:#1a|a:E(41+1:|<-EOF)>, " +
+        "<EOF:41>]",
+        res);
+
+  }
+
+}

src/org/lispdev/parser/test/parserTest.java

+package org.lispdev.parser.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.lispdev.parser.nodes.TreeRoot;
+
+public class parserTest
+{
+  @Test
+  public void updateTest()
+  {
+    final String code =
+      "(a f (x) \"this is a string\" (\"and this\" 1) \"finally this\")\n\n" //60 characters
+        + "(a 1 2 \"tt\")\n\n\n\n" //16 characters, offset = 60
+        + "(defun g (x) 3)\n\n"; //17 characters, offset = 76
+    TreeRoot tree = TreeRoot.parse(code,null);
+    assertNotNull(tree);
+    assertEquals(true, tree.sanityCheck());
+    assertEquals(
+        "TreeRoot:\n" +
+        "  Sexp:\n" +
+        "    <TL(:0>\n" +
+        "    <sym:1+1:a>\n" +
+        "    H[<ws:2+1: >]\n" +
+        "    <sym:3+1:f>\n" +
+        "    H[<ws:4+1: >]\n" +
+        "    Sexp:\n" +
+        "      <(:5>\n" +
+        "      <sym:6+1:x>\n" +
+        "      <):7>\n" +
+        "    H[<ws:8+1: >]\n" +
+        "    <str:9+18:\"this is a string\">\n" +
+        "    H[<ws:27+1: >]\n" +
+        "    Sexp:\n" +
+        "      <(:28>\n" +
+        "      <str:29+10:\"and this\">\n" +
+        "      H[<ws:39+1: >]\n" +
+        "      <num:40+1:1>\n" +
+        "      <):41>\n" +
+        "    H[<ws:42+1: >]\n" +
+        "    <str:43+14:\"finally this\">\n" +
+        "    <):57>\n" +
+        "  H[<ws:58+2:\\n\\n>]\n" +
+        "  Sexp:\n" +
+        "    <TL(:60>\n" +
+        "    <sym:61+1:a>\n" +
+        "    H[<ws:62+1: >]\n" +
+        "    <num:63+1:1>\n" +
+        "    H[<ws:64+1: >]\n" +
+        "    <num:65+1:2>\n" +
+        "    H[<ws:66+1: >]\n" +
+        "    <str:67+4:\"tt\">\n" +
+        "    <):71>\n" +
+        "  H[<ws:72+4:\\n\\n\\n\\n>]\n" +
+        "  Sexp:\n" +
+        "    <TL(:76>\n" +
+        "    <sym:77+5:defun>\n" +
+        "    H[<ws:82+1: >]\n" +
+        "    <sym:83+1:g>\n" +
+        "    H[<ws:84+1: >]\n" +
+        "    Sexp:\n" +
+        "      <(:85>\n" +
+        "      <sym:86+1:x>\n" +
+        "      <):87>\n" +
+        "    H[<ws:88+1: >]\n" +
+        "    <num:89+1:3>\n" +
+        "    <):90>\n" +
+        "  H[<ws:91+2:\\n\\n>]"
+        , tree.toString());
+
+    // add characters to a string in first TLF
+    int[] res = tree.update(11, 0, "11");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,62}, res);
+    assertEquals(code.replaceFirst("this", "t11his"),tree.text());
+
+    // delete just added characters
+    res = tree.update(11, 2, "");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,60}, res);
+    assertEquals(code,tree.text());
+
+    // modification overlaps first two TLFs
+    res = tree.update(56, 12, " ");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,65},res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\")\n\n\n\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+    // modification is in the end of the first TLF, corresponding hidden TLF
+    // stays hidden
+    res = tree.update(61, 0, " ");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,66}, res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\") \n\n\n\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+    // modification is in the end of the first TLF - creating new TLF
+    res = tree.update(61,0,"\n(a b c)");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,74},res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\")\n"
+        +"(a b c) \n\n\n\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+    // modification starts in hidden[1], ends in hidden[2] and deletes TLF
+    // between
+    res = tree.update(61,10,"");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,64}, res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\")\n"
+        + "\n\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+    // modification adds code with unmatched " error into space after
+    // the first TLF
+    res = tree.update(61, 0, "\n(a b \")");
+    //assertEquals(tree.hasErrors(),true);
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,72},res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\")\n"
+        + "(a b \")\n\n\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+
+    // modification adds another code with another unmatched " error
+    // errors should get removed
+    res = tree.update(71,0,"\n(c d \")");
+    //assertEquals(tree.hasErrors(),false);
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{61,19},res);
+    assertEquals("(a f (x) \"this is a string\" (\"and this\" 1) " +
+            "\"finally this tt\")\n"
+        + "(a b \")\n\n\n(c d \")\n"
+        + "(defun g (x) 3)\n\n",tree.text());
+
+    // start with empty text
+    tree = TreeRoot.parse("",null);
+    assertEquals(true, tree.sanityCheck());
+    res = tree.update(0, 0, "(a b c)\n");
+    assertEquals(true, tree.sanityCheck());
+    assertArrayEquals(new int[]{0,8},res);
+  }
+
+  @Test
+  public void otherTest()
+  {
+    final String code = "a\r\n";
+    TreeRoot tree = TreeRoot.parse(code,null);
+    assertEquals(true, tree.sanityCheck());
+  }
+
+  @Test
+  public void updateTest1()
+  {
+    final String code = "";
+    TreeRoot tree = TreeRoot.parse(code,null);
+    assertEquals(true, tree.sanityCheck());
+
+    int[] res = tree.update(0, 0, "a");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(1, 0, "\r\n");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(3, 0, "\r\n");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+  }
+
+  @Test
+  public void updateTest2()
+  {
+    final String code = "";
+    TreeRoot tree = TreeRoot.parse(code,null);
+    assertEquals(true, tree.sanityCheck());
+
+    int[] res = tree.update(0, 0, "a");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(1, 0, "\r\n");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(3, 0, "b");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(4, 0, "\r\n");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+
+    res = tree.update(3, 0, "\r\n");
+    assertNotNull(res);
+    assertEquals(true, tree.sanityCheck());
+  }
+
+  @Test
+  public void simpleTest()
+  {
+    String code =
+      "(do-randomly \r\n" +
+      "    ('print \"zero)\r\n" +
+      "    (print \"three\"))\r\n" +
+      "(#c(1 a ) )";
+    TreeRoot tree = TreeRoot.parse(code,null);
+    String text = tree.text();
+    assertEquals(code, text);
+    assertEquals(tree.sanityCheck(), true);
+    assertEquals(
+        "TreeRoot:\n" +
+        "  Sexp:\n" +
+        "    <TL(:0>\n" +
+        "    <sym:1+11:do-randomly>\n" +
+        "    H[<ws:12+7: \\r\\n    >]\n" +
+        "    Sexp:\n" +
+        "      <(:19>\n" +
+        "      OperatorNode:\n" +
+        "        <':20>\n" +
+        "        <sym:21+5:print>\n" +
+        "      H[<ws:26+1: >]\n" +
+        "      <str:27+20:\"zero)\\r\\n    (print \">\n" +
+        "      <sym:47+5:three>\n" +
+        "      <str:52+3:\")):E(55+1:\"<-\\r)>\n" +
+        "      H[<ws:55+2:\\r\\n>]\n" +
+        "  Sexp:\n" +
+        "    <TL(:57>\n" +
+        "    OperatorNode:\n" +
+        "      <#c:58>\n" +
+        "      Sexp:\n" +
+        "        <(:60>\n" +
+        "        <num:61+1:1>\n" +
+        "        H[<ws:62+1: >]\n" +
+        "        <sym:63+1:a>\n" +
+        "        H[<ws:64+1: >]\n" +
+        "        <):65>\n" +
+        "    H[<ws:66+1: >]\n" +
+        "    <):67>"
+        , tree.toString());
+  }
+
+  @Test
+  public void simpleTest1()
+  {
+    String code =
+      "(this and that)\n\n;;;;outline1\n(this and that1)\n";
+    TreeRoot tree = TreeRoot.parse(code,null);
+    assertEquals(tree.sanityCheck(), true);
+
+    code = "(. )";
+    tree = TreeRoot.parse(code,null);
+    assertEquals(tree.sanityCheck(), true);
+  }
+
+}