flex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aha...@apache.org
Subject [45/46] FlexPMD Donation from Adobe Systems Inc
Date Fri, 25 Apr 2014 06:18:44 GMT
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/pom.xml
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/pom.xml b/FlexPMD/as3-parser/pom.xml
new file mode 100644
index 0000000..e2c6f5c
--- /dev/null
+++ b/FlexPMD/as3-parser/pom.xml
@@ -0,0 +1,46 @@
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.adobe.ac</groupId>
+  <artifactId>as3-parser</artifactId>
+  <packaging>jar</packaging>
+  <name>As3 Parser</name>
+
+  <parent>
+	<groupId>com.adobe.ac</groupId>
+	<artifactId>flex-pmd-java-parent</artifactId>
+	<version>1.3-SNAPSHOT</version>
+	<relativePath>../flex-pmd-java-parent/pom.xml</relativePath>
+  </parent>
+  
+  <dependencies>
+      <dependency>
+         <groupId>${project.groupId}</groupId>
+         <version>${project.parent.version}</version>
+         <artifactId>${project.artifactId}-api</artifactId>
+      </dependency>
+      <dependency>
+         <groupId>${project.groupId}</groupId>
+         <version>${project.parent.version}</version>
+         <artifactId>flex-pmd-files</artifactId>
+      </dependency>
+  </dependencies>
+  
+</project>

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/b0fc5f17/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Parser.java
----------------------------------------------------------------------
diff --git a/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Parser.java b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Parser.java
new file mode 100644
index 0000000..d12f099
--- /dev/null
+++ b/FlexPMD/as3-parser/src/main/java/de/bokelberg/flex/parser/AS3Parser.java
@@ -0,0 +1,2360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package de.bokelberg.flex.parser;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.adobe.ac.pmd.files.impl.FileUtils;
+import com.adobe.ac.pmd.parser.IAS3Parser;
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.KeyWords;
+import com.adobe.ac.pmd.parser.NodeKind;
+import com.adobe.ac.pmd.parser.Operators;
+import com.adobe.ac.pmd.parser.exceptions.NullTokenException;
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+import com.adobe.ac.pmd.parser.exceptions.UnExpectedTokenException;
+import com.adobe.ac.pmd.parser.exceptions.UnExpectedTokenException.Position;
+
+import de.bokelberg.flex.parser.AS3Scanner.Token;
+
+/**
+ * @author xagnetti
+ */
+public class AS3Parser implements IAS3Parser
+{
+   /**
+    * 
+    */
+   public static final String  ASDOC_COMMENT          = "/**";
+   /**
+    * 
+    */
+   public static final String  MULTIPLE_LINES_COMMENT = "/*";
+   /**
+    * 
+    */
+   public static final String  NEW_LINE               = "\n";
+   /**
+    * 
+    */
+   public static final String  SINGLE_LINE_COMMENT    = "//";
+   private static final String VECTOR                 = "Vector";
+   private Node                currentAsDoc;
+   private Node                currentFunctionNode;
+   private Node                currentMultiLineComment;
+   private String              fileName;
+   private boolean             isInFor;
+   private AS3Scanner          scn;
+   private Token               tok;
+
+   /**
+    * 
+    */
+   public AS3Parser()
+   {
+      this.scn = new AS3Scanner();
+      isInFor = false;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see de.bokelberg.flex.parser.IAS3Parser#buildAst(java.lang.String)
+    */
+   public final IParserNode buildAst( final String filePath ) throws IOException,
+                                                             TokenException
+   {
+      return parseLines( filePath,
+                         FileUtils.readLines( new File( filePath ) ) );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.parser.IAS3Parser#buildAst(java.lang.String,
+    * java.lang.String[])
+    */
+   public final IParserNode buildAst( final String filePath,
+                                      final String[] scriptBlockLines ) throws TokenException
+   {
+      return parseLines( filePath,
+                         scriptBlockLines );
+   }
+
+   /**
+    * @return
+    */
+   final AS3Scanner getScn()
+   {
+      return scn;
+   }
+
+   final void nextToken() throws TokenException
+   {
+      nextToken( false );
+   }
+
+   /**
+    * Get the next token Skip comments and newlines for now In the end we want
+    * to keep them though.
+    * 
+    * @throws TokenException
+    */
+   final void nextToken( final boolean ignoreDocumentation ) throws TokenException
+   {
+      do
+      {
+         if ( ignoreDocumentation )
+         {
+            nextTokenIgnoringDocumentation();
+         }
+         else
+         {
+            nextTokenAllowNewLine();
+         }
+      }
+      while ( tok.getText().equals( NEW_LINE ) );
+   }
+
+   /**
+    * tok is first content token
+    * 
+    * @throws TokenException
+    */
+   final Node parseClassContent() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.CONTENT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      final List< Token > modifiers = new ArrayList< Token >();
+      final List< Node > meta = new ArrayList< Node >();
+
+      while ( !tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+      {
+         if ( tokIs( Operators.LEFT_CURLY_BRACKET ) )
+         {
+            result.addChild( parseBlock() );
+         }
+         if ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+         {
+            meta.add( parseMetaData() );
+         }
+         else if ( tokIs( KeyWords.VAR ) )
+         {
+            parseClassField( result,
+                             modifiers,
+                             meta );
+         }
+         else if ( tokIs( KeyWords.CONST ) )
+         {
+            parseClassConstant( result,
+                                modifiers,
+                                meta );
+         }
+         else if ( tokIs( KeyWords.IMPORT ) )
+         {
+            result.addChild( parseImport() );
+         }
+         else if ( tokIs( KeyWords.FUNCTION ) )
+         {
+            parseClassFunctions( result,
+                                 modifiers,
+                                 meta );
+         }
+         else
+         {
+            tryToParseCommentNode( result,
+                                   modifiers );
+         }
+      }
+      return result;
+   }
+
+   /**
+    * tok is empty, since nextToken has not been called before
+    * 
+    * @throws UnExpectedTokenException
+    */
+   final Node parseCompilationUnit() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.COMPILATION_UNIT,
+                                       -1,
+                                       -1 );
+
+      nextTokenIgnoringDocumentation();
+      if ( tokIs( KeyWords.PACKAGE ) )
+      {
+         result.addChild( parsePackage() );
+      }
+      result.addChild( parsePackageContent() );
+      return result;
+   }
+
+   /**
+    * @return
+    * @throws TokenException
+    */
+   final IParserNode parseExpression() throws TokenException
+   {
+      return parseAssignmentExpression();
+   }
+
+   /**
+    * tok is first content token
+    * 
+    * @throws TokenException
+    */
+   final Node parseInterfaceContent() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.CONTENT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      while ( !tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+      {
+         if ( tokIs( KeyWords.IMPORT ) )
+         {
+            result.addChild( parseImport() );
+         }
+         else if ( tokIs( KeyWords.FUNCTION ) )
+         {
+            result.addChild( parseFunctionSignature() );
+         }
+         else if ( tokIs( KeyWords.INCLUDE )
+               || tokIs( KeyWords.INCLUDE_AS2 ) )
+         {
+            result.addChild( parseIncludeExpression() );
+         }
+         else if ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+         {
+            while ( !tokIs( Operators.RIGHT_SQUARE_BRACKET ) )
+            {
+               nextToken();
+            }
+            nextToken();
+         }
+         else
+         {
+            tryToParseCommentNode( result,
+                                   null );
+         }
+      }
+      return result;
+   }
+
+   /**
+    * tok is first token of content
+    * 
+    * @throws UnExpectedTokenException
+    */
+   final Node parsePackageContent() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.CONTENT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      final List< Token > modifiers = new ArrayList< Token >();
+      final List< Node > meta = new ArrayList< Node >();
+
+      while ( !tokIs( Operators.RIGHT_CURLY_BRACKET )
+            && !tokIs( KeyWords.EOF ) )
+      {
+         if ( tokIs( KeyWords.IMPORT ) )
+         {
+            result.addChild( parseImport() );
+         }
+         else if ( tokIs( KeyWords.USE ) )
+         {
+            result.addChild( parseUse() );
+         }
+         else if ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+         {
+            meta.add( parseMetaData() );
+         }
+         else if ( tokIs( KeyWords.CLASS ) )
+         {
+            result.addChild( parseClass( meta,
+                                         modifiers ) );
+
+            modifiers.clear();
+            meta.clear();
+         }
+         else if ( tokIs( KeyWords.INTERFACE ) )
+         {
+            result.addChild( parseInterface( meta,
+                                             modifiers ) );
+            modifiers.clear();
+            meta.clear();
+         }
+         else if ( tokIs( KeyWords.FUNCTION ) )
+         {
+            parseClassFunctions( result,
+                                 modifiers,
+                                 meta );
+         }
+         else if ( tok.getText().startsWith( ASDOC_COMMENT ) )
+         {
+            currentAsDoc = Node.create( NodeKind.AS_DOC,
+                                        tok.getLine(),
+                                        tok.getColumn(),
+                                        tok.getText() );
+            nextToken();
+         }
+         else if ( tok.getText().startsWith( MULTIPLE_LINES_COMMENT ) )
+         {
+            currentMultiLineComment = Node.create( NodeKind.MULTI_LINE_COMMENT,
+                                                   tok.getLine(),
+                                                   tok.getColumn(),
+                                                   tok.getText() );
+            nextToken();
+         }
+         else
+         {
+            modifiers.add( tok );
+            nextTokenIgnoringDocumentation();
+         }
+      }
+      return result;
+   }
+
+   /**
+    * @return
+    * @throws TokenException
+    */
+   final Node parsePrimaryExpression() throws TokenException
+   {
+      Node result = Node.create( NodeKind.PRIMARY,
+                                 tok.getLine(),
+                                 tok.getColumn(),
+                                 tok.getText() );
+
+      if ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+      {
+         result.addChild( parseArrayLiteral() );
+      }
+      else if ( tokIs( Operators.LEFT_CURLY_BRACKET ) )
+      {
+         result.addChild( parseObjectLiteral() );
+      }
+      else if ( tokIs( KeyWords.FUNCTION ) )
+      {
+         result.addChild( parseLambdaExpression() );
+      }
+      else if ( tokIs( KeyWords.NEW ) )
+      {
+         result = parseNewExpression();
+      }
+      else if ( tokIs( Operators.LEFT_PARENTHESIS ) )
+      {
+         result.addChild( parseEncapsulatedExpression() );
+      }
+      else
+      {
+         nextToken( true );
+      }
+      return result;
+   }
+
+   /**
+    * tok is the first token of a statement
+    * 
+    * @throws TokenException
+    */
+   final IParserNode parseStatement() throws TokenException
+   {
+      IParserNode result;
+
+      if ( tokIs( KeyWords.FOR ) )
+      {
+         result = parseFor();
+      }
+      else if ( tokIs( KeyWords.IF ) )
+      {
+         result = parseIf();
+      }
+      else if ( tokIs( KeyWords.SWITCH ) )
+      {
+         result = parseSwitch();
+      }
+      else if ( tokIs( KeyWords.DO ) )
+      {
+         result = parseDo();
+      }
+      else if ( tokIs( KeyWords.WHILE ) )
+      {
+         result = parseWhile();
+      }
+      else if ( tokIs( KeyWords.TRY ) )
+      {
+         result = parseTry();
+      }
+      else if ( tokIs( KeyWords.CATCH ) )
+      {
+         result = parseCatch();
+      }
+      else if ( tokIs( KeyWords.FINALLY ) )
+      {
+         result = parseFinally();
+      }
+      else if ( tokIs( Operators.LEFT_CURLY_BRACKET ) )
+      {
+         result = parseBlock();
+      }
+      else if ( tokIs( KeyWords.VAR ) )
+      {
+         result = parseVar();
+      }
+      else if ( tokIs( KeyWords.CONST ) )
+      {
+         result = parseConst();
+      }
+      else if ( tokIs( KeyWords.RETURN ) )
+      {
+         result = parseReturnStatement();
+      }
+      else if ( tokIs( Operators.SEMI_COLUMN ) )
+      {
+         result = parseEmptyStatement();
+      }
+      else
+      {
+         result = parseExpressionList();
+         skip( Operators.SEMI_COLUMN );
+      }
+      return result;
+   }
+
+   /**
+    * @return
+    * @throws TokenException
+    */
+   final Node parseUnaryExpression() throws TokenException
+   {
+      Node result;
+      if ( tokIs( Operators.INCREMENT ) )
+      {
+         nextToken();
+         result = Node.create( NodeKind.PRE_INC,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseUnaryExpression() );
+      }
+      else if ( tokIs( Operators.DECREMENT ) )
+      {
+         nextToken();
+         result = Node.create( NodeKind.PRE_DEC,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseUnaryExpression() );
+      }
+      else if ( tokIs( Operators.MINUS ) )
+      {
+         nextToken();
+         result = Node.create( NodeKind.MINUS,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseUnaryExpression() );
+      }
+      else if ( tokIs( Operators.PLUS )
+            || tokIs( Operators.PLUS_AS2 ) )
+      {
+         nextToken();
+         result = Node.create( NodeKind.PLUS,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseUnaryExpression() );
+      }
+      else
+      {
+         result = parseUnaryExpressionNotPlusMinus();
+      }
+      return result;
+   }
+
+   private IParserNode collectVarListContent( final Node result ) throws TokenException
+   {
+      result.addChild( parseNameTypeInit() );
+      while ( tokIs( Operators.COMMA ) )
+      {
+         nextToken( true );
+         result.addChild( parseNameTypeInit() );
+      }
+      return result;
+   }
+
+   private void consume( final KeyWords keyword ) throws TokenException
+   {
+      consume( keyword.toString() );
+   }
+
+   private void consume( final Operators operator ) throws TokenException
+   {
+      consume( operator.toString() );
+   }
+
+   /**
+    * Compare the current token to the parameter. If it equals, get the next
+    * token. If not, throw a runtime exception.
+    * 
+    * @param text
+    * @throws UnExpectedTokenException
+    */
+   private void consume( final String text ) throws TokenException
+   {
+      while ( tok.getText().startsWith( "//" ) )
+      {
+         nextToken();
+      }
+
+      if ( !tokIs( text ) )
+      {
+         throw new UnExpectedTokenException( tok.getText(),
+                                             new Position( tok.getLine(), tok.getColumn() ),
+                                             fileName,
+                                             text );
+      }
+      nextToken();
+   }
+
+   private Node convertMeta( final List< Node > metadataList )
+   {
+      if ( metadataList == null
+            || metadataList.isEmpty() )
+      {
+         return null;
+      }
+
+      final Node result = Node.create( NodeKind.META_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+
+      for ( final Node metadataNode : metadataList )
+      {
+         result.addChild( metadataNode );
+      }
+      return result;
+   }
+
+   private Node convertModifiers( final List< Token > modifierList )
+   {
+      if ( modifierList == null )
+      {
+         return null;
+      }
+
+      final Node result = Node.create( NodeKind.MOD_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+
+      for ( final Token modifierToken : modifierList )
+      {
+         result.addChild( NodeKind.MODIFIER,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          modifierToken.getText() );
+      }
+      return result;
+   }
+
+   private Node[] doParseSignature() throws TokenException
+   {
+      consume( KeyWords.FUNCTION );
+
+      Node type = Node.create( NodeKind.TYPE,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               KeyWords.FUNCTION.toString() );
+      if ( tokIs( KeyWords.SET )
+            || tokIs( KeyWords.GET ) )
+      {
+         type = Node.create( NodeKind.TYPE,
+                             tok.getLine(),
+                             tok.getColumn(),
+                             tok.getText() );
+         nextToken(); // set or get
+      }
+      final Node name = Node.create( NodeKind.NAME,
+                                     tok.getLine(),
+                                     tok.getColumn(),
+                                     tok.getText() );
+      nextToken(); // name
+      final Node params = parseParameterList();
+      final Node returnType = parseOptionalType();
+      return new Node[]
+      { type,
+                  name,
+                  params,
+                  returnType };
+   }
+
+   private NodeKind findFunctionTypeFromSignature( final Node[] signature )
+   {
+      for ( final Node node : signature )
+      {
+         if ( node.is( NodeKind.TYPE ) )
+         {
+            if ( node.getStringValue().equals( "set" ) )
+            {
+               return NodeKind.SET;
+            }
+            if ( node.getStringValue().equals( "get" ) )
+            {
+               return NodeKind.GET;
+            }
+            return NodeKind.FUNCTION;
+         }
+      }
+      return NodeKind.FUNCTION;
+   }
+
+   /**
+    * Get the next token Skip comments but keep newlines We need this method for
+    * beeing able to decide if a returnStatement has an expression
+    * 
+    * @throws UnExpectedTokenException
+    */
+   private void nextTokenAllowNewLine() throws TokenException
+   {
+      do
+      {
+         tok = scn.nextToken();
+
+         if ( tok == null )
+         {
+            throw new NullTokenException( fileName );
+
+         }
+         if ( tok.getText() == null )
+         {
+            throw new NullTokenException( fileName );
+         }
+      }
+      while ( tok.getText().startsWith( SINGLE_LINE_COMMENT ) );
+   }
+
+   private void nextTokenIgnoringDocumentation() throws TokenException
+   {
+      do
+      {
+         nextToken();
+      }
+      while ( tok.getText().startsWith( MULTIPLE_LINES_COMMENT ) );
+   }
+
+   private IParserNode parseAdditiveExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.ADD,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseMultiplicativeExpression() );
+      while ( tokIs( Operators.PLUS )
+            || tokIs( Operators.PLUS_AS2 ) || tokIs( Operators.MINUS ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseMultiplicativeExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   // ------------------------------------------------------------------------
+   // language specific recursive descent parsing
+   // ------------------------------------------------------------------------
+
+   private IParserNode parseAndExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.AND,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseBitwiseOrExpression() );
+      while ( tokIs( Operators.AND )
+            || tokIs( Operators.AND_AS2 ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseBitwiseOrExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   /**
+    * tok is ( exit tok is first token after )
+    */
+   private Node parseArgumentList() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+      final Node result = Node.create( NodeKind.ARGUMENTS,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      while ( !tokIs( Operators.RIGHT_PARENTHESIS ) )
+      {
+         result.addChild( parseExpression() );
+         skip( Operators.COMMA );
+      }
+      consume( Operators.RIGHT_PARENTHESIS );
+      return result;
+   }
+
+   private Node parseArrayAccessor( final Node node ) throws TokenException
+   {
+      final Node result = Node.create( NodeKind.ARRAY_ACCESSOR,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( node );
+      while ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+      {
+         nextToken( true );
+         result.addChild( parseExpression() );
+         consume( Operators.RIGHT_SQUARE_BRACKET );
+      }
+      return result;
+   }
+
+   /**
+    * tok is [
+    */
+   private IParserNode parseArrayLiteral() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.ARRAY,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      consume( Operators.LEFT_SQUARE_BRACKET );
+      while ( !tokIs( Operators.RIGHT_SQUARE_BRACKET ) )
+      {
+         result.addChild( parseExpression() );
+         skip( Operators.COMMA );
+      }
+      consume( Operators.RIGHT_SQUARE_BRACKET );
+      return result;
+   }
+
+   private IParserNode parseAssignmentExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.ASSIGN,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseConditionalExpression() );
+      while ( tokIs( Operators.EQUAL )
+            || tokIs( Operators.PLUS_EQUAL ) || tokIs( Operators.MINUS_EQUAL )
+            || tokIs( Operators.TIMES_EQUAL ) || tokIs( Operators.DIVIDED_EQUAL )
+            || tokIs( Operators.MODULO_EQUAL ) || tokIs( Operators.AND_EQUAL ) || tokIs( Operators.OR_EQUAL )
+            || tokIs( Operators.XOR_EQUAL ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private IParserNode parseBitwiseAndExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.B_AND,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseEqualityExpression() );
+      while ( tokIs( Operators.B_AND ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseEqualityExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private IParserNode parseBitwiseOrExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.B_OR,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseBitwiseXorExpression() );
+      while ( tokIs( Operators.B_OR ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseBitwiseXorExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private IParserNode parseBitwiseXorExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.B_XOR,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseBitwiseAndExpression() );
+      while ( tokIs( Operators.B_XOR ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseBitwiseAndExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private Node parseBlock() throws TokenException
+   {
+      return parseBlock( Node.create( NodeKind.BLOCK,
+                                      tok.getLine(),
+                                      tok.getColumn() ) );
+   }
+
+   private Node parseBlock( final Node result ) throws TokenException
+   {
+      consume( Operators.LEFT_CURLY_BRACKET );
+
+      while ( !tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+      {
+         if ( tok.getText().startsWith( MULTIPLE_LINES_COMMENT ) )
+         {
+            currentFunctionNode.addChild( Node.create( NodeKind.MULTI_LINE_COMMENT,
+                                                       tok.getLine(),
+                                                       tok.getColumn(),
+                                                       tok.getText() ) );
+            nextToken();
+         }
+         else
+         {
+            result.addChild( parseStatement() );
+         }
+      }
+      consume( Operators.RIGHT_CURLY_BRACKET );
+      return result;
+   }
+
+   /**
+    * tok is catch
+    * 
+    * @throws TokenException
+    */
+   private Node parseCatch() throws TokenException
+   {
+      consume( KeyWords.CATCH );
+      consume( Operators.LEFT_PARENTHESIS );
+      final Node result = Node.create( NodeKind.CATCH,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       Node.create( NodeKind.NAME,
+                                                    tok.getLine(),
+                                                    tok.getColumn(),
+                                                    tok.getText() ) );
+      nextToken( true ); // name
+      if ( tokIs( Operators.COLUMN ) )
+      {
+         nextToken( true ); // :
+         result.addChild( Node.create( NodeKind.TYPE,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true ); // type
+      }
+      consume( Operators.RIGHT_PARENTHESIS );
+      result.addChild( parseBlock() );
+      return result;
+   }
+
+   /**
+    * tok is class
+    * 
+    * @param meta
+    * @param modifier
+    * @throws TokenException
+    */
+   private Node parseClass( final List< Node > meta,
+                            final List< Token > modifier ) throws TokenException
+   {
+      consume( KeyWords.CLASS );
+
+      final Node result = Node.create( NodeKind.CLASS,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+
+      if ( currentAsDoc != null )
+      {
+         result.addChild( currentAsDoc );
+         currentAsDoc = null;
+      }
+      if ( currentMultiLineComment != null )
+      {
+         result.addChild( currentMultiLineComment );
+         currentMultiLineComment = null;
+      }
+
+      result.addChild( NodeKind.NAME,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseQualifiedName( true ) );
+
+      result.addChild( convertMeta( meta ) );
+      result.addChild( convertModifiers( modifier ) );
+
+      // nextToken( true ); // name
+
+      do
+      {
+         if ( tokIs( KeyWords.EXTENDS ) )
+         {
+            nextToken( true ); // extends
+            result.addChild( NodeKind.EXTENDS,
+                             tok.getLine(),
+                             tok.getColumn(),
+                             parseQualifiedName( false ) );
+         }
+         else if ( tokIs( KeyWords.IMPLEMENTS ) )
+         {
+            result.addChild( parseImplementsList() );
+         }
+      }
+      while ( !tokIs( Operators.LEFT_CURLY_BRACKET ) );
+      consume( Operators.LEFT_CURLY_BRACKET );
+      result.addChild( parseClassContent() );
+      consume( Operators.RIGHT_CURLY_BRACKET );
+      return result;
+   }
+
+   private void parseClassConstant( final Node result,
+                                    final List< Token > modifiers,
+                                    final List< Node > meta ) throws TokenException
+   {
+      result.addChild( parseConstList( meta,
+                                       modifiers ) );
+      if ( tokIs( Operators.SEMI_COLUMN ) )
+      {
+         nextToken();
+      }
+      meta.clear();
+      modifiers.clear();
+   }
+
+   private void parseClassField( final Node result,
+                                 final List< Token > modifiers,
+                                 final List< Node > meta ) throws TokenException
+   {
+      final Node varList = parseVarList( meta,
+                                         modifiers );
+      result.addChild( varList );
+      if ( currentAsDoc != null )
+      {
+         varList.addChild( currentAsDoc );
+         currentAsDoc = null;
+      }
+      if ( currentMultiLineComment != null )
+      {
+         result.addChild( currentMultiLineComment );
+         currentMultiLineComment = null;
+      }
+      if ( tokIs( Operators.SEMI_COLUMN ) )
+      {
+         nextToken();
+      }
+      meta.clear();
+      modifiers.clear();
+   }
+
+   private void parseClassFunctions( final Node result,
+                                     final List< Token > modifiers,
+                                     final List< Node > meta ) throws TokenException
+   {
+      result.addChild( parseFunction( meta,
+                                      modifiers ) );
+      meta.clear();
+      modifiers.clear();
+   }
+
+   /**
+    * tok is (
+    * 
+    * @throws TokenException
+    */
+   private Node parseCondition() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+      final Node result = Node.create( NodeKind.CONDITION,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseExpression() );
+      consume( Operators.RIGHT_PARENTHESIS );
+      return result;
+   }
+
+   private IParserNode parseConditionalExpression() throws TokenException
+   {
+      final IParserNode result = parseOrExpression();
+      if ( tokIs( Operators.QUESTION_MARK ) )
+      {
+         final Node conditional = Node.create( NodeKind.CONDITIONAL,
+                                               tok.getLine(),
+                                               tok.getColumn(),
+                                               result );
+         nextToken( true ); // ?
+         conditional.addChild( parseExpression() );
+         nextToken( true ); // :
+         conditional.addChild( parseExpression() );
+
+         return conditional;
+      }
+      return result;
+   }
+
+   private Node parseConst() throws TokenException
+   {
+      Node result;
+      result = parseConstList( null,
+                               null );
+      skip( Operators.SEMI_COLUMN );
+      return result;
+   }
+
+   /**
+    * tok is const
+    * 
+    * @param modifiers
+    * @param meta
+    * @throws TokenException
+    */
+   private Node parseConstList( final List< Node > meta,
+                                final List< Token > modifiers ) throws TokenException
+   {
+      consume( KeyWords.CONST );
+      final Node result = Node.create( NodeKind.CONST_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( convertMeta( meta ) );
+      result.addChild( convertModifiers( modifiers ) );
+      collectVarListContent( result );
+      return result;
+   }
+
+   private Node parseDecrement( final Node node ) throws TokenException
+   {
+      nextToken( true );
+      final Node result = Node.create( NodeKind.POST_DEC,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( node );
+      return result;
+   }
+
+   /**
+    * tok is do
+    * 
+    * @throws TokenException
+    */
+   private Node parseDo() throws TokenException
+   {
+      consume( KeyWords.DO );
+      final Node result = Node.create( NodeKind.DO,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseStatement() );
+      consume( KeyWords.WHILE );
+      result.addChild( parseCondition() );
+      if ( tokIs( Operators.SEMI_COLUMN ) )
+      {
+         nextToken( true );
+      }
+      return result;
+   }
+
+   private Node parseDot( final Node node ) throws TokenException
+   {
+      nextToken();
+      if ( tokIs( Operators.LEFT_PARENTHESIS ) )
+      {
+         nextToken();
+         final Node result = Node.create( NodeKind.E4X_FILTER,
+                                          tok.getLine(),
+                                          tok.getColumn() );
+         result.addChild( node );
+         result.addChild( parseExpression() );
+         consume( Operators.RIGHT_PARENTHESIS );
+         return result;
+      }
+      else if ( tokIs( Operators.TIMES ) )
+      {
+         final Node result = Node.create( NodeKind.E4X_STAR,
+                                          tok.getLine(),
+                                          tok.getColumn() );
+         result.addChild( node );
+         return result;
+      }
+      final Node result = Node.create( NodeKind.DOT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( node );
+      result.addChild( parseExpression() );
+      return result;
+   }
+
+   private Node parseEmptyStatement() throws TokenException
+   {
+      Node result;
+      result = Node.create( NodeKind.STMT_EMPTY,
+                            tok.getLine(),
+                            tok.getColumn(),
+                            Operators.SEMI_COLUMN.toString() );
+      nextToken( true );
+      return result;
+   }
+
+   private Node parseEncapsulatedExpression() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+      final Node result = Node.create( NodeKind.ENCAPSULATED,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( parseExpressionList() );
+
+      consume( Operators.RIGHT_PARENTHESIS );
+
+      return result;
+   }
+
+   private IParserNode parseEqualityExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.EQUALITY,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseRelationalExpression() );
+      while ( tokIs( Operators.DOUBLE_EQUAL )
+            || tokIs( Operators.DOUBLE_EQUAL_AS2 ) || tokIs( Operators.STRICTLY_EQUAL )
+            || tokIs( Operators.NON_EQUAL ) || tokIs( Operators.NON_EQUAL_AS2_1 )
+            || tokIs( Operators.NON_EQUAL_AS2_2 ) || tokIs( Operators.NON_STRICTLY_EQUAL ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseRelationalExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private IParserNode parseExpressionList() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.EXPR_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseAssignmentExpression() );
+      while ( tokIs( Operators.COMMA ) )
+      {
+         nextToken( true );
+         result.addChild( parseAssignmentExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private Node parseFinally() throws TokenException
+   {
+      Node result;
+      nextToken( true );
+      result = Node.create( NodeKind.FINALLY,
+                            tok.getLine(),
+                            tok.getColumn(),
+                            parseBlock() );
+      return result;
+   }
+
+   /**
+    * tok is for
+    * 
+    * @throws TokenException
+    */
+   private Node parseFor() throws TokenException
+   {
+      consume( KeyWords.FOR );
+
+      if ( tokIs( KeyWords.EACH ) )
+      {
+         nextToken();
+         return parseForEach();
+      }
+      else
+      {
+         return parseTraditionalFor();
+      }
+   }
+
+   /**
+    * tok is ( for each( var obj : Type in List )
+    * 
+    * @throws TokenException
+    */
+   private Node parseForEach() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+
+      final Node result = Node.create( NodeKind.FOREACH,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      if ( tokIs( KeyWords.VAR ) )
+      {
+         final Node var = Node.create( NodeKind.VAR,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+         nextToken();
+         var.addChild( parseNameTypeInit() );
+         result.addChild( var );
+      }
+      else
+      {
+         result.addChild( NodeKind.NAME,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          tok.getText() );
+         // names allowed?
+         nextToken();
+      }
+      nextToken(); // in
+      result.addChild( NodeKind.IN,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseExpression() );
+      consume( Operators.RIGHT_PARENTHESIS );
+      result.addChild( parseStatement() );
+      return result;
+   }
+
+   private Node parseForIn( final Node result ) throws TokenException
+   {
+      nextToken();
+      result.addChild( NodeKind.IN,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseExpression() );
+      result.setId( NodeKind.FORIN );
+      return result;
+   }
+
+   /**
+    * tok is function
+    * 
+    * @param modifiers
+    * @param meta
+    * @throws TokenException
+    */
+   private Node parseFunction( final List< Node > meta,
+                               final List< Token > modifiers ) throws TokenException
+   {
+      final Node[] signature = doParseSignature();
+      final Node result = Node.create( findFunctionTypeFromSignature( signature ),
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       signature[ 0 ].getStringValue() );
+
+      if ( currentAsDoc != null )
+      {
+         result.addChild( currentAsDoc );
+         currentAsDoc = null;
+      }
+      if ( currentMultiLineComment != null )
+      {
+         result.addChild( currentMultiLineComment );
+         currentMultiLineComment = null;
+      }
+      result.addChild( convertMeta( meta ) );
+      result.addChild( convertModifiers( modifiers ) );
+      result.addChild( signature[ 1 ] );
+      result.addChild( signature[ 2 ] );
+      result.addChild( signature[ 3 ] );
+      if ( tokIs( Operators.SEMI_COLUMN ) )
+      {
+         consume( Operators.SEMI_COLUMN );
+      }
+      else
+      {
+         result.addChild( parseFunctionBlock() );
+      }
+      currentFunctionNode = null;
+      return result;
+   }
+
+   /**
+    * tok is { exit tok is the first tok after }
+    * 
+    * @throws TokenException
+    * @throws TokenException
+    */
+
+   private Node parseFunctionBlock() throws TokenException
+   {
+      final Node block = Node.create( NodeKind.BLOCK,
+                                      tok.getLine(),
+                                      tok.getColumn() );
+
+      currentFunctionNode = block;
+
+      parseBlock( block );
+
+      return block;
+   }
+
+   private Node parseFunctionCall( final Node node ) throws TokenException
+   {
+      final Node result = Node.create( NodeKind.CALL,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( node );
+      while ( tokIs( Operators.LEFT_PARENTHESIS ) )
+      {
+         result.addChild( parseArgumentList() );
+      }
+      while ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+      {
+         result.addChild( parseArrayLiteral() );
+      }
+
+      return result;
+   }
+
+   /**
+    * tok is function exit tok is the first token after the optional ;
+    * 
+    * @throws TokenException
+    */
+   private Node parseFunctionSignature() throws TokenException
+   {
+      final Node[] signature = doParseSignature();
+      skip( Operators.SEMI_COLUMN );
+      final Node result = Node.create( findFunctionTypeFromSignature( signature ),
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       signature[ 0 ].getStringValue() );
+      result.addChild( signature[ 1 ] );
+      result.addChild( signature[ 2 ] );
+      result.addChild( signature[ 3 ] );
+      return result;
+   }
+
+   /**
+    * tok is if
+    * 
+    * @throws TokenException
+    */
+   private Node parseIf() throws TokenException
+   {
+      consume( KeyWords.IF );
+      final Node result = Node.create( NodeKind.IF,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseCondition() );
+      result.addChild( parseStatement() );
+      if ( tokIs( KeyWords.ELSE ) )
+      {
+         nextToken( true );
+         result.addChild( parseStatement() );
+      }
+      return result;
+   }
+
+   /**
+    * tok is implements implements a,b,c exit tok is the first token after the
+    * list of qualfied names
+    * 
+    * @throws TokenException
+    */
+   private Node parseImplementsList() throws TokenException
+   {
+      consume( KeyWords.IMPLEMENTS );
+
+      final Node result = Node.create( NodeKind.IMPLEMENTS_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( NodeKind.IMPLEMENTS,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseQualifiedName( true ) );
+      while ( tokIs( Operators.COMMA ) )
+      {
+         nextToken( true );
+         result.addChild( NodeKind.IMPLEMENTS,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          parseQualifiedName( false ) );
+      }
+      return result;
+   }
+
+   /**
+    * tok is import
+    * 
+    * @throws TokenException
+    */
+   private Node parseImport() throws TokenException
+   {
+      consume( KeyWords.IMPORT );
+      final Node result = Node.create( NodeKind.IMPORT,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseImportName() );
+      skip( Operators.SEMI_COLUMN );
+      return result;
+   }
+
+   /**
+    * tok is the first part of a name the last part can be a star exit tok is
+    * the first token, which doesn't belong to the name
+    * 
+    * @throws TokenException
+    */
+   private String parseImportName() throws TokenException
+   {
+      final StringBuffer result = new StringBuffer();
+
+      result.append( tok.getText() );
+      nextToken();
+      while ( tokIs( Operators.DOT ) )
+      {
+         result.append( Operators.DOT );
+         nextToken(); // .
+         result.append( tok.getText() );
+         nextToken(); // part of name
+      }
+      return result.toString();
+   }
+
+   private IParserNode parseIncludeExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.INCLUDE,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      if ( tokIs( KeyWords.INCLUDE ) )
+      {
+         consume( KeyWords.INCLUDE );
+      }
+      else if ( tokIs( KeyWords.INCLUDE_AS2 ) )
+      {
+         consume( KeyWords.INCLUDE_AS2 );
+      }
+      result.addChild( parseExpression() );
+      return result;
+   }
+
+   private Node parseIncrement( final Node node ) throws TokenException
+   {
+      nextToken( true );
+      final Node result = Node.create( NodeKind.POST_INC,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( node );
+      return result;
+   }
+
+   /**
+    * tok is interface
+    * 
+    * @param meta
+    * @param modifier
+    * @throws TokenException
+    */
+   private Node parseInterface( final List< Node > meta,
+                                final List< Token > modifier ) throws TokenException
+   {
+      consume( KeyWords.INTERFACE );
+      final Node result = Node.create( NodeKind.INTERFACE,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+
+      if ( currentAsDoc != null )
+      {
+         result.addChild( currentAsDoc );
+         currentAsDoc = null;
+      }
+      if ( currentMultiLineComment != null )
+      {
+         result.addChild( currentMultiLineComment );
+         currentMultiLineComment = null;
+      }
+      result.addChild( NodeKind.NAME,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseQualifiedName( true ) );
+
+      result.addChild( convertMeta( meta ) );
+      result.addChild( convertModifiers( modifier ) );
+
+      if ( tokIs( KeyWords.EXTENDS ) )
+      {
+         nextToken(); // extends
+         result.addChild( NodeKind.EXTENDS,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          parseQualifiedName( false ) );
+      }
+      while ( tokIs( Operators.COMMA ) )
+      {
+         nextToken(); // comma
+         result.addChild( NodeKind.EXTENDS,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          parseQualifiedName( false ) );
+      }
+      consume( Operators.LEFT_CURLY_BRACKET );
+      result.addChild( parseInterfaceContent() );
+      consume( Operators.RIGHT_CURLY_BRACKET );
+      return result;
+   }
+
+   /**
+    * tok is function
+    * 
+    * @throws TokenException
+    */
+   private Node parseLambdaExpression() throws TokenException
+   {
+      consume( KeyWords.FUNCTION );
+      Node result;
+
+      if ( tok.getText().compareTo( "(" ) == 0 )
+      {
+         result = Node.create( NodeKind.LAMBDA,
+                               tok.getLine(),
+                               tok.getColumn() );
+      }
+      else
+      {
+         result = Node.create( NodeKind.FUNCTION,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               tok.getText() );
+         nextToken( true );
+      }
+      result.addChild( parseParameterList() );
+      result.addChild( parseOptionalType() );
+      result.addChild( parseBlock() );
+      return result;
+   }
+
+   private IParserNode parseLines( final String filePath,
+                                   final String[] lines ) throws TokenException
+   {
+      setFileName( filePath );
+      scn = new AS3Scanner();
+      scn.setLines( lines );
+      return parseCompilationUnit();
+   }
+
+   /**
+    * tok is [ [id] [id ("test")] [id (name="test",type="a.b.c.Event")] exit
+    * token is the first token after ]
+    * 
+    * @throws TokenException
+    */
+   private Node parseMetaData() throws TokenException
+   {
+      final StringBuffer buffer = new StringBuffer();
+
+      final int line = tok.getLine();
+      final int column = tok.getColumn();
+
+      consume( Operators.LEFT_SQUARE_BRACKET );
+      while ( !tokIs( Operators.RIGHT_SQUARE_BRACKET ) )
+      {
+         if ( buffer.length() > 0 )
+         {
+            buffer.append( ' ' );
+         }
+         buffer.append( tok.getText() );
+         nextToken();
+      }
+      skip( Operators.RIGHT_SQUARE_BRACKET );
+      final Node metaDataNode = Node.create( NodeKind.META,
+                                             line,
+                                             column,
+                                             buffer.toString() );
+
+      return metaDataNode;
+   }
+
+   private IParserNode parseMultiplicativeExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.MULTIPLICATION,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseUnaryExpression() );
+      while ( tokIs( Operators.TIMES )
+            || tokIs( Operators.SLASH ) || tokIs( Operators.MODULO ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseUnaryExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private String parseNamespaceName() throws TokenException
+   {
+      final String name = tok.getText();
+      nextToken(); // simple name for now
+      return name;
+   }
+
+   private Node parseNameTypeInit() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.NAME_TYPE_INIT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( NodeKind.NAME,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       tok.getText() );
+      nextToken( true ); // name
+      result.addChild( parseOptionalType() );
+      result.addChild( parseOptionalInit() );
+      return result;
+   }
+
+   private Node parseNewExpression() throws TokenException
+   {
+      consume( KeyWords.NEW );
+
+      final Node result = Node.create( NodeKind.NEW,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( parseExpression() ); // name
+      if ( tokIs( Operators.VECTOR_START ) )
+      {
+         result.addChild( Node.create( NodeKind.VECTOR,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseVector() ) );
+      }
+      if ( tokIs( Operators.LEFT_PARENTHESIS ) )
+      {
+         result.addChild( parseArgumentList() );
+      }
+      return result;
+   }
+
+   /**
+    * tok is {
+    */
+   private Node parseObjectLiteral() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.OBJECT,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      consume( Operators.LEFT_CURLY_BRACKET );
+      while ( !tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+      {
+         result.addChild( parseObjectLiteralPropertyDeclaration() );
+         skip( Operators.COMMA );
+      }
+      consume( Operators.RIGHT_CURLY_BRACKET );
+      return result;
+   }
+
+   /*
+    * tok is name
+    */
+   private Node parseObjectLiteralPropertyDeclaration() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.PROP,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      final Node name = Node.create( NodeKind.NAME,
+                                     tok.getLine(),
+                                     tok.getColumn(),
+                                     tok.getText() );
+      result.addChild( name );
+      nextToken(); // name
+      consume( Operators.COLUMN );
+      result.addChild( NodeKind.VALUE,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       parseExpression() );
+      return result;
+   }
+
+   /**
+    * if tok is "=" parse the expression otherwise do nothing
+    * 
+    * @return
+    */
+   private Node parseOptionalInit() throws TokenException
+   {
+      Node result = null;
+      if ( tokIs( Operators.EQUAL ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.INIT,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      return result;
+   }
+
+   /**
+    * if tok is ":" parse the type otherwise do nothing
+    * 
+    * @return
+    * @throws TokenException
+    */
+   private Node parseOptionalType() throws TokenException
+   {
+      Node result = Node.create( NodeKind.TYPE,
+                                 tok.getLine(),
+                                 tok.getColumn(),
+                                 "" );
+      if ( tokIs( Operators.COLUMN ) )
+      {
+         nextToken( true );
+         result = parseType();
+      }
+      return result;
+   }
+
+   private IParserNode parseOrExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.OR,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseAndExpression() );
+      while ( tokIs( Operators.LOGICAL_OR )
+            || tokIs( Operators.LOGICAL_OR_AS2 ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseAndExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   /**
+    * tok is package
+    * 
+    * @throws UnExpectedTokenException
+    */
+   private Node parsePackage() throws TokenException
+   {
+      consume( KeyWords.PACKAGE );
+
+      final Node result = Node.create( NodeKind.PACKAGE,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      final StringBuffer nameBuffer = new StringBuffer();
+
+      while ( !tokIs( Operators.LEFT_CURLY_BRACKET ) )
+      {
+         nameBuffer.append( tok.getText() );
+         nextToken();
+      }
+      result.addChild( NodeKind.NAME,
+                       tok.getLine(),
+                       tok.getColumn(),
+                       nameBuffer.toString() );
+      consume( Operators.LEFT_CURLY_BRACKET );
+      result.addChild( parsePackageContent() );
+      consume( Operators.RIGHT_CURLY_BRACKET );
+      return result;
+   }
+
+   /**
+    * tok is the name of a parameter or ...
+    */
+   private Node parseParameter() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.PARAMETER,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      if ( tokIs( Operators.REST_PARAMETERS ) )
+      {
+         nextToken( true ); // ...
+         final Node rest = Node.create( NodeKind.REST,
+                                        tok.getLine(),
+                                        tok.getColumn(),
+                                        tok.getText() );
+         nextToken( true ); // rest
+         result.addChild( rest );
+      }
+      else
+      {
+         result.addChild( parseNameTypeInit() );
+      }
+      return result;
+   }
+
+   /**
+    * tok is (
+    * 
+    * @throws TokenException
+    */
+   private Node parseParameterList() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+
+      final Node result = Node.create( NodeKind.PARAMETER_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      while ( !tokIs( Operators.RIGHT_PARENTHESIS ) )
+      {
+         result.addChild( parseParameter() );
+         if ( tokIs( Operators.COMMA ) )
+         {
+            nextToken( true );
+         }
+         else
+         {
+            break;
+         }
+      }
+      consume( Operators.RIGHT_PARENTHESIS );
+      return result;
+   }
+
+   /**
+    * tok is first part of the name exit tok is the first token after the name
+    * 
+    * @throws TokenException
+    */
+   private String parseQualifiedName( final boolean skipPackage ) throws TokenException
+   {
+      final StringBuffer buffer = new StringBuffer();
+
+      buffer.append( tok.getText() );
+      nextToken();
+      while ( tokIs( Operators.DOT )
+            || tokIs( Operators.DOUBLE_COLUMN ) )
+      {
+         buffer.append( tok.getText() );
+         nextToken();
+         buffer.append( tok.getText() );
+         nextToken(); // name
+      }
+
+      if ( skipPackage )
+      {
+         return buffer.substring( buffer.lastIndexOf( Operators.DOT.toString() ) + 1 );
+      }
+      return buffer.toString();
+   }
+
+   private IParserNode parseRelationalExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.RELATION,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseShiftExpression() );
+      while ( tokIs( Operators.INFERIOR )
+            || tokIs( Operators.INFERIOR_AS2 ) || tokIs( Operators.INFERIOR_OR_EQUAL )
+            || tokIs( Operators.INFERIOR_OR_EQUAL_AS2 ) || tokIs( Operators.SUPERIOR )
+            || tokIs( Operators.SUPERIOR_AS2 ) || tokIs( Operators.SUPERIOR_OR_EQUAL )
+            || tokIs( Operators.SUPERIOR_OR_EQUAL_AS2 ) || tokIs( KeyWords.IS ) || tokIs( KeyWords.IN )
+            && !isInFor || tokIs( KeyWords.AS ) || tokIs( KeyWords.INSTANCE_OF ) )
+      {
+         if ( !tokIs( KeyWords.AS ) )
+         {
+            result.addChild( Node.create( NodeKind.OP,
+                                          tok.getLine(),
+                                          tok.getColumn(),
+                                          tok.getText() ) );
+         }
+         else
+         {
+            result.addChild( Node.create( NodeKind.AS,
+                                          tok.getLine(),
+                                          tok.getColumn(),
+                                          tok.getText() ) );
+         }
+         nextToken( true );
+         result.addChild( parseShiftExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   private IParserNode parseReturnStatement() throws TokenException
+   {
+      Node result;
+
+      nextTokenAllowNewLine();
+      if ( tokIs( NEW_LINE )
+            || tokIs( Operators.SEMI_COLUMN ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.RETURN,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               "" );
+      }
+      else
+      {
+         result = Node.create( NodeKind.RETURN,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+         skip( Operators.SEMI_COLUMN );
+      }
+      return result;
+   }
+
+   private IParserNode parseShiftExpression() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.SHIFT,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseAdditiveExpression() );
+      while ( tokIs( Operators.DOUBLE_SHIFT_LEFT )
+            || tokIs( Operators.TRIPLE_SHIFT_LEFT ) || tokIs( Operators.DOUBLE_SHIFT_RIGHT )
+            || tokIs( Operators.TRIPLE_SHIFT_RIGHT ) )
+      {
+         result.addChild( Node.create( NodeKind.OP,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken( true );
+         result.addChild( parseAdditiveExpression() );
+      }
+      return result.numChildren() > 1 ? result
+                                     : result.getChild( 0 );
+   }
+
+   /**
+    * tok is switch
+    * 
+    * @throws TokenException
+    */
+   private Node parseSwitch() throws TokenException
+   {
+      consume( KeyWords.SWITCH );
+      final Node result = Node.create( NodeKind.SWITCH,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseCondition() );
+      if ( tokIs( Operators.LEFT_CURLY_BRACKET ) )
+      {
+         nextToken();
+         result.addChild( parseSwitchCases() );
+         consume( Operators.RIGHT_CURLY_BRACKET );
+      }
+      return result;
+   }
+
+   /**
+    * tok is case, default or the first token of the first statement
+    * 
+    * @throws TokenException
+    */
+   private Node parseSwitchBlock() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.SWITCH_BLOCK,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      while ( !tokIs( KeyWords.CASE )
+            && !tokIs( KeyWords.DEFAULT ) && !tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+      {
+         result.addChild( parseStatement() );
+      }
+      return result;
+   }
+
+   /**
+    * tok is { exit tok is }
+    * 
+    * @throws TokenException
+    */
+   private Node parseSwitchCases() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.CASES,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      for ( ;; )
+      {
+         if ( tokIs( Operators.RIGHT_CURLY_BRACKET ) )
+         {
+            break;
+         }
+         else if ( tokIs( KeyWords.CASE ) )
+         {
+            nextToken( true ); // case
+            final Node caseNode = Node.create( NodeKind.CASE,
+                                               tok.getLine(),
+                                               tok.getColumn(),
+                                               parseExpression() );
+            consume( Operators.COLUMN );
+            caseNode.addChild( parseSwitchBlock() );
+            result.addChild( caseNode );
+         }
+         else if ( tokIs( KeyWords.DEFAULT ) )
+         {
+            nextToken( true ); // default
+            consume( Operators.COLUMN );
+            final Node caseNode = Node.create( NodeKind.CASE,
+                                               tok.getLine(),
+                                               tok.getColumn(),
+                                               Node.create( NodeKind.DEFAULT,
+                                                            tok.getLine(),
+                                                            tok.getColumn(),
+                                                            KeyWords.DEFAULT.toString() ) );
+            caseNode.addChild( parseSwitchBlock() );
+            result.addChild( caseNode );
+         }
+      }
+      return result;
+   }
+
+   /**
+    * tok is ( for( var x : int = 0; i < length; i++ ) for( var s : String in
+    * Object )
+    * 
+    * @throws TokenException
+    */
+   private Node parseTraditionalFor() throws TokenException
+   {
+      consume( Operators.LEFT_PARENTHESIS );
+
+      final Node result = Node.create( NodeKind.FOR,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      if ( !tokIs( Operators.SEMI_COLUMN ) )
+      {
+         if ( tokIs( KeyWords.VAR ) )
+         {
+            result.addChild( NodeKind.INIT,
+                             tok.getLine(),
+                             tok.getColumn(),
+                             parseVarList( null,
+                                           null ) );
+         }
+         else
+         {
+            isInFor = true;
+            result.addChild( NodeKind.INIT,
+                             tok.getLine(),
+                             tok.getColumn(),
+                             parseExpression() );
+            isInFor = false;
+         }
+         if ( tokIs( NodeKind.IN.toString() ) )
+         {
+            return parseForIn( result );
+         }
+      }
+      consume( Operators.SEMI_COLUMN );
+      if ( !tokIs( Operators.SEMI_COLUMN ) )
+      {
+         result.addChild( NodeKind.COND,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          parseExpression() );
+      }
+      consume( Operators.SEMI_COLUMN );
+      if ( !tokIs( Operators.RIGHT_PARENTHESIS ) )
+      {
+         result.addChild( NodeKind.ITER,
+                          tok.getLine(),
+                          tok.getColumn(),
+                          parseExpressionList() );
+      }
+      consume( Operators.RIGHT_PARENTHESIS );
+      result.addChild( parseStatement() );
+      return result;
+   }
+
+   private Node parseTry() throws TokenException
+   {
+      Node result;
+      nextToken( true );
+      result = Node.create( NodeKind.TRY,
+                            tok.getLine(),
+                            tok.getColumn(),
+                            parseBlock() );
+      return result;
+   }
+
+   private Node parseType() throws TokenException
+   {
+      Node result;
+      if ( tok.getText().equals( VECTOR ) )
+      {
+         result = parseVector();
+      }
+      else
+      {
+         result = Node.create( NodeKind.TYPE,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseQualifiedName( true ) );
+         // nextToken( true );
+      }
+      return result;
+   }
+
+   private Node parseUnaryExpressionNotPlusMinus() throws TokenException
+   {
+      Node result;
+      if ( tokIs( KeyWords.DELETE ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.DELETE,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      else if ( tokIs( KeyWords.VOID ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.VOID,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      else if ( tokIs( KeyWords.TYPEOF ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.TYPEOF,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      else if ( tokIs( "!" )
+            || tokIs( "not" ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.NOT,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      else if ( tokIs( "~" ) )
+      {
+         nextToken( true );
+         result = Node.create( NodeKind.B_NOT,
+                               tok.getLine(),
+                               tok.getColumn(),
+                               parseExpression() );
+      }
+      else
+      {
+         result = parseUnaryPostfixExpression();
+      }
+      return result;
+   }
+
+   private Node parseUnaryPostfixExpression() throws TokenException
+   {
+      Node node = parsePrimaryExpression();
+
+      if ( tokIs( Operators.LEFT_SQUARE_BRACKET ) )
+      {
+         node = parseArrayAccessor( node );
+      }
+      else if ( tokIs( Operators.LEFT_PARENTHESIS ) )
+      {
+         node = parseFunctionCall( node );
+      }
+      if ( tokIs( Operators.INCREMENT ) )
+      {
+         node = parseIncrement( node );
+      }
+      else if ( tokIs( Operators.DECREMENT ) )
+      {
+         node = parseDecrement( node );
+      }
+      else if ( tokIs( Operators.DOT )
+            || tokIs( Operators.DOUBLE_COLUMN ) )
+      {
+         node = parseDot( node );
+      }
+      return node;
+   }
+
+   private Node parseUse() throws TokenException
+   {
+      consume( KeyWords.USE );
+      consume( KeyWords.NAMESPACE );
+      final Node result = Node.create( NodeKind.USE,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       parseNamespaceName() );
+      skip( Operators.SEMI_COLUMN );
+      return result;
+   }
+
+   private Node parseVar() throws TokenException
+   {
+      Node result;
+      result = parseVarList( null,
+                             null );
+      skip( Operators.SEMI_COLUMN );
+      return result;
+   }
+
+   /**
+    * tok is var var x, y : String, z : int = 0;
+    * 
+    * @param modifiers
+    * @param meta
+    * @throws TokenException
+    */
+   private Node parseVarList( final List< Node > meta,
+                              final List< Token > modifiers ) throws TokenException
+   {
+      consume( KeyWords.VAR );
+      final Node result = Node.create( NodeKind.VAR_LIST,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( convertMeta( meta ) );
+      result.addChild( convertModifiers( modifiers ) );
+      collectVarListContent( result );
+      return result;
+   }
+
+   private Node parseVector() throws TokenException
+   {
+      final Node result = Node.create( NodeKind.VECTOR,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       "" );
+      if ( tok.getText().compareTo( "Vector" ) == 0 )
+      {
+         nextToken();
+      }
+      consume( Operators.VECTOR_START );
+
+      result.addChild( parseType() );
+
+      consume( Operators.SUPERIOR );
+
+      return result;
+   }
+
+   /**
+    * tok is while
+    * 
+    * @throws TokenException
+    */
+   private Node parseWhile() throws TokenException
+   {
+      consume( KeyWords.WHILE );
+      final Node result = Node.create( NodeKind.WHILE,
+                                       tok.getLine(),
+                                       tok.getColumn() );
+      result.addChild( parseCondition() );
+      result.addChild( parseStatement() );
+      return result;
+   }
+
+   private void setFileName( final String fileNameToParse )
+   {
+      fileName = fileNameToParse;
+   }
+
+   private void skip( final Operators operator ) throws TokenException
+   {
+      skip( operator.toString() );
+   }
+
+   /**
+    * Skip the current token, if it equals to the parameter
+    * 
+    * @param text
+    * @throws UnExpectedTokenException
+    */
+   private void skip( final String text ) throws TokenException
+   {
+      if ( tokIs( text ) )
+      {
+         nextToken();
+      }
+   }
+
+   private boolean tokIs( final KeyWords keyword )
+   {
+      return tok.getText().compareTo( keyword.toString() ) == 0;
+   }
+
+   private boolean tokIs( final Operators operator )
+   {
+      return tok.getText().compareTo( operator.toString() ) == 0;
+   }
+
+   /**
+    * Compare the current token to the parameter
+    * 
+    * @param text
+    * @return true, if tok's text property equals the parameter
+    */
+   private boolean tokIs( final String text )
+   {
+      return tok.getText().equals( text );
+   }
+
+   private void tryToParseCommentNode( final Node result,
+                                       final List< Token > modifiers ) throws TokenException
+   {
+      if ( tok.getText().startsWith( ASDOC_COMMENT ) )
+      {
+         currentAsDoc = Node.create( NodeKind.AS_DOC,
+                                     tok.getLine(),
+                                     tok.getColumn(),
+                                     tok.getText() );
+         nextToken();
+      }
+      else if ( tok.getText().startsWith( MULTIPLE_LINES_COMMENT ) )
+      {
+         result.addChild( Node.create( NodeKind.MULTI_LINE_COMMENT,
+                                       tok.getLine(),
+                                       tok.getColumn(),
+                                       tok.getText() ) );
+         nextToken();
+      }
+      else
+      {
+         if ( modifiers != null )
+         {
+            modifiers.add( tok );
+         }
+         nextTokenIgnoringDocumentation();
+      }
+   }
+}


Mime
View raw message