Added:
/grammar/src/main/antlr3/noop/grammar/antlr/Doc.g
/grammar/src/main/antlr3/noop/grammar/antlr/Noop.g
/grammar/src/main/antlr3/noop/grammar/antlr/NoopAST.g
/grammar/src/main/scala/noop/grammar/ParseException.scala
/grammar/src/main/scala/noop/grammar/Parser.scala
/grammar/src/test/scala/noop/grammar/BindingSpec.scala
/grammar/src/test/scala/noop/grammar/BlockSpec.scala
/grammar/src/test/scala/noop/grammar/ClassSpec.scala
/grammar/src/test/scala/noop/grammar/CommentsSpec.scala
/grammar/src/test/scala/noop/grammar/DocumentationSpec.scala
/grammar/src/test/scala/noop/grammar/ExpressionsSpec.scala
/grammar/src/test/scala/noop/grammar/FileSpec.scala
/grammar/src/test/scala/noop/grammar/IfSpec.scala
/grammar/src/test/scala/noop/grammar/InterfaceSpec.scala
/grammar/src/test/scala/noop/grammar/InterpretableSpec.scala
/grammar/src/test/scala/noop/grammar/LiteralsSpec.scala
/grammar/src/test/scala/noop/grammar/LoopSpec.scala
/grammar/src/test/scala/noop/grammar/MethodsSpec.scala
/grammar/src/test/scala/noop/grammar/ParseExamplesTest.scala
/grammar/src/test/scala/noop/grammar/ParserSpec.scala
/grammar/src/test/scala/noop/grammar/PropertiesSpec.scala
/grammar/src/test/scala/noop/grammar/TestSpec.scala
/grammar/src/test/scala/noop/grammar/TryCatchSpec.scala
Deleted:
/core/src/main/antlr3/noop/grammar/antlr/Doc.g
/core/src/main/antlr3/noop/grammar/antlr/Noop.g
/core/src/main/antlr3/noop/grammar/antlr/NoopAST.g
/core/src/main/scala/noop/grammar/ParseException.scala
/core/src/main/scala/noop/grammar/Parser.scala
/core/src/test/scala/noop/grammar/BindingSpec.scala
/core/src/test/scala/noop/grammar/BlockSpec.scala
/core/src/test/scala/noop/grammar/ClassSpec.scala
/core/src/test/scala/noop/grammar/CommentsSpec.scala
/core/src/test/scala/noop/grammar/DocumentationSpec.scala
/core/src/test/scala/noop/grammar/ExpressionsSpec.scala
/core/src/test/scala/noop/grammar/FileSpec.scala
/core/src/test/scala/noop/grammar/IfSpec.scala
/core/src/test/scala/noop/grammar/InterfaceSpec.scala
/core/src/test/scala/noop/grammar/InterpretableSpec.scala
/core/src/test/scala/noop/grammar/LiteralsSpec.scala
/core/src/test/scala/noop/grammar/LoopSpec.scala
/core/src/test/scala/noop/grammar/MethodsSpec.scala
/core/src/test/scala/noop/grammar/ParseExamplesTest.scala
/core/src/test/scala/noop/grammar/ParserSpec.scala
/core/src/test/scala/noop/grammar/PropertiesSpec.scala
/core/src/test/scala/noop/grammar/TestSpec.scala
/core/src/test/scala/noop/grammar/TryCatchSpec.scala
Modified:
/buildfile
/core/src/main/scala/noop/model/ExpressionWrapper.scala
=======================================
--- /dev/null
+++ /grammar/src/main/antlr3/noop/grammar/antlr/Doc.g Mon Feb 1 12:11:10
2010
@@ -0,0 +1,73 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed 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.
+
+grammar Doc;
+
+options {
+ backtrack = true;
+ output = AST;
+ ASTLabelType = CommonTree;
+}
+
+@header {
+ package noop.grammar.antlr;
+}
+
+@lexer::header {
+ package noop.grammar.antlr;
+}
+
+@lexer::rulecatch {
+ catch (RecognitionException e) {
+ reportError(e);
+ throw new RuntimeException(e);
+ }
+}
+
+@rulecatch {
+ catch (RecognitionException e) {
+ reportError(e);
+ throw e;
+ }
+}
+
+doc
+ : DocLine* docCommandDeclaration*
+ ;
+
+docCommandDeclaration
+ : docCommand DocLine*
+ ;
+
+docCommand
+ : '@param'
+// TODO(gabe) : '@param' VariableIdentifier
+ | CustomCommand
+ ;
+
+CustomCommand
+ : '@' 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
+ ;
+
+VariableIdentifier
+ : 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
+ ;
+
+DocLine
+ : ~'@' ~('\n'|'\r')* '\r'? '\n'
+ ;
+
+WS : (' '|'\t'|'\n')+
+ ;
+
=======================================
--- /dev/null
+++ /grammar/src/main/antlr3/noop/grammar/antlr/Noop.g Mon Feb 1 12:11:10
2010
@@ -0,0 +1,349 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed 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.
+
+grammar Noop;
+
+options {
+ backtrack = true;
+ output = AST;
+ ASTLabelType = CommonTree;
+}
+
+tokens {
+ DOC;
+ CLASS;
+ INTERFACE;
+ PARAMS;
+ PARAM;
+ METHOD;
+ MOD;
+ ARGS;
+ VAR;
+ IMPL;
+ IF;
+ WHILE;
+ FOREACH;
+ FOR;
+ TEST;
+ UNITTEST;
+ BINDING;
+ BIND;
+ RETURN_TYPE;
+ TRY;
+ CATCH;
+ FINALLY;
+}
+
+@header {
+ package noop.grammar.antlr;
+}
+
+@lexer::header {
+ package noop.grammar.antlr;
+}
+
+@members {
+ public boolean hadErrors = false;
+
+ @Override
+ public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
+ hadErrors = true;
+ return super.getErrorMessage(e, tokenNames);
+ }
+}
+
+@lexer::members {
+ public boolean hadErrors = false;
+
+ @Override
+ public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
+ hadErrors = true;
+ return super.getErrorMessage(e, tokenNames);
+ }
+}
+
+// A line of user input in the interactive interpreter
+interpretable
+ : (importDeclaration
+ | classDefinition
+ | statement)+
+ ;
+
+file
+ : namespaceDeclaration? importDeclaration* (classDefinition |
interfaceDefinition | bindingDefinition | test)
+ ;
+
+namespaceDeclaration
+ : 'namespace'^ namespace ';'!
+ ;
+
+importDeclaration
+ : 'import'^ qualifiedType ';'!
+ ;
+
+ifExpression
+ : 'if' '(' expression ')' block* ('else' block*)?
+ -> ^(IF expression* block*)
+ ;
+
+methodDefinition
+ : methodSignature block
+ -> ^(METHOD methodSignature block?)
+ ;
+
+namespace
+ : VariableIdentifier ('.'! VariableIdentifier)*
+ ;
+
+qualifiedType
+ : (namespace '.'!)? TypeIdentifier
+ ;
+
+classDefinition
+ : doc? modifiers? 'class' TypeIdentifier parameterList typeSpecifiers?
classBlock
+ -> ^(CLASS modifiers? TypeIdentifier parameterList? typeSpecifiers?
classBlock? doc?)
+ ;
+
+doc
+ : StringLiteral -> ^(DOC StringLiteral)
+ ;
+
+typeSpecifiers
+ : 'implements' qualifiedType (',' qualifiedType)*
+ -> ^(IMPL qualifiedType)*
+ ;
+
+interfaceDefinition
+ : doc? 'interface' TypeIdentifier interfaceBlock
+ -> ^(INTERFACE TypeIdentifier interfaceBlock? doc?)
+ ;
+
+modifiers
+ : modifier+
+ -> ^(MOD modifier+)
+ ;
+
+modifier
+ : 'mutable' | 'delegate' | 'native'
+ ;
+
+classBlock
+ : '{'! (identifierDeclaration ';'!)* methodDefinition* unittest* '}'!
+ ;
+
+interfaceBlock
+ : '{'! methodDeclaration* '}'!
+ ;
+
+test
+ : 'test' StringLiteral '{' (statement* | test | unittest) '}'
+ -> ^(TEST StringLiteral statement* test? unittest?)
+ ;
+
+unittest
+ : 'unittest' StringLiteral bindingDeclaration? block
+ -> ^(UNITTEST StringLiteral bindingDeclaration? block?)
+ ;
+
+methodSignature
+ : doc? modifiers? returnType VariableIdentifier parameterList
throwsDeclaration?
+ ;
+
+throwsDeclaration
+ : 'throws' qualifiedType
+ -> ^('throws' qualifiedType)
+ ;
+
+returnType
+ : TypeIdentifier -> ^(RETURN_TYPE TypeIdentifier)
+ | '(' typeList ')' -> ^(RETURN_TYPE typeList)
+ ;
+
+typeList
+ : TypeIdentifier (','! TypeIdentifier)*
+ ;
+
+methodDeclaration
+ : methodSignature ';'
+ -> ^(METHOD methodSignature)
+ ;
+
+
+identifierDeclaration
+ : TypeIdentifier identifierDeclarator
+ -> ^(VAR TypeIdentifier identifierDeclarator)
+ ;
+
+identifierDeclarator
+ : VariableIdentifier ('='^ expression)?
+ ;
+
+block
+ : '{'! statement* '}'!
+ ;
+
+statement
+ : identifierDeclaration ';'!
+ | whileLoop
+ | forLoop
+ | 'return'^ expression ';'!
+ | expression ';'!
+ | ifExpression
+ | shouldStatement ';'!
+ | bindingsBlock
+ | tryCatchBlock
+ ;
+
+tryCatchBlock
+ : 'try' block 'catch' block ('finally' block)?
+ -> ^(TRY block CATCH block (FINALLY block)?)
+ | 'try' block 'finally' block
+ -> ^(TRY block FINALLY block)
+ ;
+
+//TODO(alex): The binding syntax seems a little scattered. Sometimes
semicolon, sometimes comma?
+bindingDefinition
+ : doc? 'binding' qualifiedType '{' ((binding | typealias) ';')* '}'
+ -> ^(BINDING qualifiedType doc? binding* typealias*)
+ ;
+
+bindingDeclaration
+ : 'binding' (bindings | qualifiedType)
+ -> ^(BINDING bindings? qualifiedType?)
+ ;
+
+bindingsBlock
+ : 'binding' (bindings | qualifiedType) block
+ -> ^(BINDING bindings? qualifiedType? block?)
+ ;
+
+bindings
+ : '('! binding? (','! binding)* ')'!
+ ;
+
+binding
+ : qualifiedType '->' expression
+ -> ^(BIND qualifiedType expression)
+ ;
+
+typealias
+ : 'alias'^ qualifiedType TypeIdentifier
+ ;
+
+shouldStatement
+ : expression 'should'^ expression
+ ;
+
+forLoop
+ : 'for' '(' (identifierDeclaration|VariableIdentifier) 'in'
expression ')' block
+ -> ^(FOREACH identifierDeclaration? VariableIdentifier? expression block?)
+ | 'for' '(' identifierDeclaration ';' conditionalExpression ';'
expression ')' block
+ -> ^(FOR identifierDeclaration conditionalExpression expression block?)
+ ;
+
+whileLoop
+ : 'while' '(' expression ')' block
+ -> ^(WHILE expression block?)
+ ;
+
+expression
+ : additiveExpression ('='^ expression)?
+ ;
+
+additiveExpression
+ : multiplicativeExpression ( ('+' | '-')^ multiplicativeExpression )*
+ ;
+
+multiplicativeExpression
+ : conditionalExpression ( ( '*' | '/' | '%' )^ conditionalExpression )*
+ ;
+
+conditionalExpression
+ : (conditionalOrExpression | conditionalAndExpression)+
+ ;
+
+conditionalOrExpression
+ : conditionalAndExpression ('||'^ conditionalAndExpression)*
+ ;
+
+conditionalAndExpression
+ : finalConditionalExpression ('&&'^ finalConditionalExpression)*
+ ;
+
+finalConditionalExpression
+ : primary (('==' | '!=' | '>' | '<' | '>=' | '<=')^ primary)*
+ ;
+
+primary
+ : '('! expression ')'!
+ | (VariableIdentifier|TypeIdentifier|literal) (arguments | ('.'^
(VariableIdentifier|TypeIdentifier) arguments?)*)
+ ;
+
+arguments
+ : '(' expressionList? ')'
+ -> ^(ARGS expressionList?)
+ ;
+
+expressionList
+ : expression (','! expression)*
+ ;
+
+parameterList
+ : '('! parameters? ')'!
+ ;
+
+parameters
+ : parameter (',' parameter)*
+ -> ^(PARAMS parameter*)
+ ;
+
+parameter
+ : modifiers? qualifiedType VariableIdentifier
+ -> ^(PARAM modifiers? qualifiedType VariableIdentifier)
+ ;
+
+literal
+ : INT | StringLiteral | 'true' | 'false'
+ ;
+
+/* Lexer rules */
+
+TypeIdentifier
+ : 'A' .. 'Z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
+ ;
+
+VariableIdentifier
+ : 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
+ ;
+
+StringLiteral
+ : '"' ~('"'|'\\'|'\n'|'\r')* '"'
+ | '"""' (options {greedy=false;}:.)* '"""'
+ ;
+
+WS
+ : (' '|'\r'|'\n'|'\t')+ {$channel = HIDDEN;}
+ ;
+
+COMMENT
+ : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
+ ;
+
+LINE_COMMENT
+ : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
+ ;
+
+INT
+ : '-'? '0'..'9'+
+ ;
=======================================
--- /dev/null
+++ /grammar/src/main/antlr3/noop/grammar/antlr/NoopAST.g Mon Feb 1
12:11:10 2010
@@ -0,0 +1,395 @@
+// Copyright 2009 Google Inc.
+//
+// Licensed 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.
+
+tree grammar NoopAST;
+
+options {
+ tokenVocab = Noop;
+ ASTLabelType = CommonTree;
+}
+
+scope SourceFile {
+ SourceFile file;
+}
+
+scope Block {
+ Block block;
+}
+
+@header {
+ package noop.grammar.antlr;
+
+ import noop.model.*;
+ import noop.model.proto.NoopAst;
+ import noop.model.proto.NoopAst.*;
+ import scala.Enumeration;
+ import scala.collection.mutable.Buffer;
+ import scala.collection.mutable.ArrayBuffer;
+}
+
+@members {
+ Stack paraphrases = new Stack();
+ public boolean hadErrors = false;
+
+ @Override
+ public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
+ hadErrors = true;
+ String msg = super.getErrorMessage(e, tokenNames);
+ if ( paraphrases.size()>0 ) {
+ String paraphrase = (String)paraphrases.peek();
+ msg = msg+" "+paraphrase;
+ }
+ return msg;
+ }
+
+ public String join(String delim, List strings) {
+ if (strings.isEmpty()) {
+ return "";
+ }
+ String first = ((CommonTree) strings.get(0)).getText();
+ if (strings.size() == 1) {
+ return first;
+ }
+ StringBuilder builder = new StringBuilder(first);
+ for (int i=1; i<strings.size(); i++) {
+ builder.append(delim);
+ builder.append(((CommonTree)strings.get(i)).getText());
+ }
+ return builder.toString();
+ }
+
+ //TODO(alexeagle): when we have escape sequences, we need to do more
work here
+ // Probably anything acceping raw strings should take a RawString type
which
+ // knows how to propertly un-escape things.
+ String stripQuotes(String withQuotes) {
+ return (withQuotes.startsWith("\"\"\"") ?
+ withQuotes.substring(3, withQuotes.length() - 3) :
+ withQuotes.substring(1, withQuotes.length() - 1));
+ }
+}
+
+file returns [SourceFile file = new SourceFile()]
+ scope SourceFile;
+ @init { $SourceFile::file = $file;
+ paraphrases.push("at top-level in file"); }
+ @after { paraphrases.pop(); }
+ : namespaceDeclaration? importDeclaration* (classDefinition |
interfaceDefinition | bindingsDefinition | test)
+ ;
+
+namespaceDeclaration
+ : ^('namespace' name=namespace)
+ { $SourceFile::file.namespace_\$eq($name.text); }
+ ;
+
+importDeclaration
+ : ^('import' name=qualifiedType)
+ { $SourceFile::file.imports().\$plus\$eq($name.text); }
+ ;
+
+namespace returns [String text]
+ : v+=VariableIdentifier+
+ { $text = join(".", $v); }
+ ;
+
+qualifiedType returns [String text]
+ : n=namespace? t=TypeIdentifier
+ { $text = ($n.text == null) ? $t.text : $n.text + "." + $t.text; }
+ ;
+
+classDefinition
+@init {
+ paraphrases.push("in class definition");
+ Buffer<Method> methodCollector = new ArrayBuffer<Method>();
+ Buffer<Method> unittestCollector = new ArrayBuffer<Method>();
+ Buffer<String> interfaceCollector = new ArrayBuffer<String>();
+}
+@after {
+ paraphrases.pop();
+}
+ : ^(CLASS m=modifiers? t=TypeIdentifier p=parameters?
+ typeSpecifier[interfaceCollector]*
+ classBlock[methodCollector, unittestCollector]?
+ d=doc?)
+ {
+ ConcreteClassDefinition classDef = new ConcreteClassDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
+ classDef.imports().\$plus\$plus\$eq($SourceFile::file.imports());
+ classDef.methods().\$plus\$plus\$eq(methodCollector);
+ classDef.unittests().\$plus\$plus\$eq(unittestCollector);
+ classDef.interfaces().\$plus\$plus\$eq(interfaceCollector);
+ if ($p.parameters != null) {
+ classDef.parameters().\$plus\$plus\$eq($p.parameters);
+ }
+ if ($m.modifiers != null) {
+ classDef.modifiers().\$plus\$plus\$eq($m.modifiers);
+ }
+ $SourceFile::file.classDef_\$eq(classDef);
+ }
+ ;
+
+interfaceDefinition
+ : ^(INTERFACE m=modifiers? t=TypeIdentifier d=doc?)
+ {
+ InterfaceDefinition classDef = new InterfaceDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
+ if ($m.modifiers != null) {
+ classDef.modifiers().\$plus\$plus\$eq($m.modifiers);
+ }
+ $SourceFile::file.classDef_\$eq(classDef);
+ }
+ ;
+
+parameters returns [Buffer<Parameter> parameters = new
ArrayBuffer<Parameter>() ]
+ : ^(PARAMS parameter[$parameters]*)
+ ;
+
+parameter [Buffer<Parameter> parameters]
+ : ^(PARAM modifiers? t=qualifiedType v=VariableIdentifier)
+
+ { Parameter param = new Parameter($v.text, $t.text);
+ $parameters.\$plus\$eq(param);
+ }
+ ;
+
+typeSpecifier [Buffer<String> interfaces]
+ : ^(IMPL i=qualifiedType)
+ {
+ $interfaces.\$plus\$eq($i.text);
+ }
+ ;
+
+modifiers returns [Buffer<Enumeration.Value> modifiers ]
+@init { modifiers = new ArrayBuffer<Enumeration.Value>(); }
+ : ^(MOD modifier[modifiers]+)
+ ;
+
+modifier [Buffer<Enumeration.Value> mods]
+ : m=('mutable' | 'delegate' | 'native')
+ { mods.\$plus\$eq(Modifier.valueOf($m.text).get()); }
+ ;
+
+test
+@init {
+ Buffer<Method> unittestCollector = new ArrayBuffer<Method>();
+}
+ : ^(TEST StringLiteral statement* test? unittest[unittestCollector]?)
+ {}
+ ;
+
+unittest [Buffer<Method> unittests]
+ : ^(UNITTEST name=StringLiteral b=block)
+ { Method method = new Method(stripQuotes($name.text), $b.block,
stripQuotes($name.text));
+ $unittests.\$plus\$eq(method);
+ method.returnTypes().\$plus\$eq("Void");
+ }
+ ;
+
+classBlock [Buffer<Method> methods, Buffer<Method> unittests]
+ : (identifierDeclaration | methodDefinition[methods] |
unittest[unittests])+
+ ;
+
+methodDefinition [Buffer<Method> methods]
+@init { paraphrases.push("in method definition"); }
+@after { paraphrases.pop(); }
+ : ^(METHOD d=doc? m=modifiers? r=returnType name=VariableIdentifier
p=parameters? b=block)
+ { Method method = new Method($name.text, $b.block, $d.doc);
+ method.returnTypes().\$plus\$plus\$eq($r.types);
+ if ($p.parameters != null) {
+ method.parameters().\$plus\$plus\$eq($p.parameters);
+ }
+ if ($m.modifiers != null) {
+ method.modifiers().\$plus\$plus\$eq($m.modifiers);
+ }
+ $methods.\$plus\$eq(method);
+ }
+ ;
+
+returnType returns [Buffer<String> types = new ArrayBuffer<String>() ]
+ : ^(RETURN_TYPE type[$types]+)
+ ;
+
+type [Buffer<String> types]
+ : t=TypeIdentifier {
+ $types.\$plus\$eq($t.text);
+ }
+ ;
+
+bindingsDefinition
+ : ^(BINDING t=TypeIdentifier d=doc? b=bindings)
+ {
+ BindingDefinition classDef = new BindingDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
+ classDef.bindings().\$plus\$plus\$eq($b.bindings);
+ classDef.imports().\$plus\$plus\$eq($SourceFile::file.imports());
+ $SourceFile::file.classDef_\$eq(classDef);
+ }
+ ;
+
+bindingsDeclaration returns [Buffer<BindingDeclaration> bindings]
+ : ^(BINDING b=bindings)
+ { $bindings = $b.bindings; }
+ ;
+
+bindingsReference returns [String text]
+ : ^(BINDING t=qualifiedType)
+ { $text = $t.text; }
+ ;
+
+bindings returns [Buffer<BindingDeclaration> bindings]
+ @init{ $bindings = new ArrayBuffer<BindingDeclaration>(); }
+ : binding[bindings]*
+ ;
+
+binding[Buffer<BindingDeclaration> bindings]
+ : ^(BIND t=qualifiedType exp=expression)
+ { $bindings.\$plus\$eq(new BindingDeclaration($t.text, $exp.exp)); }
+ ;
+
+block returns [Block block]
+ scope Block;
+ @init { $block = new Block();
+ $Block::block = $block; }
+ : (anonBind=bindingsDeclaration | namedBind=bindingsReference)?
statement*
+ {
+ if ($namedBind.text != null) {
+ $block.namedBinding_\$eq(new scala.Some($namedBind.text));
+ }
+ if ($anonBind.bindings != null) {
+ $block.anonymousBindings().\$plus\$plus\$eq($anonBind.bindings);
+ }
+ }
+ ;
+
+statement
+@init { paraphrases.push("in statement"); }
+@after { paraphrases.pop(); }
+ : returnStatement
+ | w=whileStatement
+ { $Block::block.statements().\$plus\$eq($w.exp); }
+ | identifierDeclaration
+ | should=shouldStatement
+ { $Block::block.statements().\$plus\$eq($should.exp); }
+ | exp=expression
+ { $Block::block.statements().\$plus\$eq($exp.exp); }
+ ;
+
+shouldStatement returns [Expression exp]
+ : ^('should' left=expression right=expression)
+ { $exp = new ShouldExpression($left.exp, $right.exp); }
+ ;
+
+whileStatement returns [Expression exp]
+ : ^(WHILE term=expression b=block)
+ { $exp = new WhileLoop($term.exp, $b.block); }
+ ;
+
+returnStatement
+ : ^('return' ex=expression)
+ { $Block::block.statements().\$plus\$eq(new ReturnExpression($ex.exp)); }
+ ;
+
+identifierDeclaration
+ : ^(VAR t=TypeIdentifier (^('=' v=VariableIdentifier exp=expression) |
v=VariableIdentifier))
+ { IdentifierDeclarationExpression identifierDeclaration = new
IdentifierDeclarationExpression($t.text, $v.text);
+ $Block::block.statements().\$plus\$eq(identifierDeclaration);
+ if ($exp.exp != null) {
+ identifierDeclaration.initialValue_\$eq(new scala.Some($exp.exp));
+ }
+ }
+ ;
+
+assignment returns [Expression exp]
+ : ^('=' lhs=expression rhs=expression)
+ { $exp = new AssignmentExpression($lhs.exp, $rhs.exp); }
+ ;
+
+expression returns [Expression exp]
+ : l=literal
+ { $exp = new ExpressionWrapper($l.exp); }
+ | d=dereference
+ { $exp = $d.exp; }
+ | o=operatorExpression
+ { $exp = $o.exp; }
+ | ass=assignment
+ { $exp = $ass.exp; }
+ | c=conditionalExpression
+ { $exp = $c.exp; }
+ | right=(VariableIdentifier|TypeIdentifier) a=arguments?
+ { if ($a.args != null) {
+ Expression left = new IdentifierExpression("this");
+ $exp = new MethodInvocationExpression(left, $right.text, $a.args);
+ } else {
+ $exp = new IdentifierExpression($right.text);
+ }
+ }
+ ;
+
+conditionalExpression returns [Expression exp]
+ : ^(cond=('||' | '&&') left=expression right=expression)
+ {
+ if ($cond.text.equals("||")) {
+ $exp = new ConditionalOrExpression($left.exp, $right.exp);
+ } else if ($cond.text.equals("&&")) {
+ $exp = new ConditionalAndExpression($left.exp, $right.exp);
+ }
+ }
+ ;
+
+operatorExpression returns [Expression exp]
+ : ^(op=('+' | '-' | '*' | '/' | '%' | '==' | '!=' | '>' | '<' | '>='
| '<=') left=expression right=expression)
+ { $exp = new OperatorExpression($left.exp, $op.text, $right.exp); }
+ ;
+
+dereference returns [Expression exp]
+ : ^('.' left=expression right=VariableIdentifier a=arguments?)
+ {
+ if ($a.args != null) {
+ $exp = new MethodInvocationExpression($left.exp, $right.text,
$a.args);
+ } else {
+ $exp = new DereferenceExpression($left.exp, new
IdentifierExpression($right.text));
+ }
+ }
+ ;
+
+arguments returns [Buffer<Expression> args]
+@init { $args = new ArrayBuffer<Expression>(); }
+ : ^(ARGS argument[args]*)
+ ;
+
+argument[Buffer<Expression> args]
+ : exp=expression
+ {
+ $args.\$plus\$eq($exp.exp);
+ }
+ ;
+
+literal returns [Expr exp]
+ : i=INT
+ { $exp = Expr.newBuilder()
+ .setType(Expr.Type.INT_LITERAL)
+ .setIntLiteral(IntLiteral.newBuilder().setValue(Integer.valueOf($i.text)))
+ .build(); }
+ | s=StringLiteral
+ { $exp = Expr.newBuilder()
+ .setType(Expr.Type.STRING_LITERAL)
+ .setStringLiteral(NoopAst.StringLiteral.newBuilder().setValue(stripQuotes($s.text)))
+ .build(); }
+ | b=('true' | 'false')
+ { $exp = Expr.newBuilder()
+ .setType(Expr.Type.BOOLEAN_LITERAL)
+ .setBooleanLiteral(NoopAst.BooleanLiteral.newBuilder().setValue(Boolean.valueOf($b.text)))
+ .build(); }
+ ;
+
+doc returns [String doc]
+ : ^(DOC s=StringLiteral)
+ { $doc = stripQuotes($s.text); }
+ ;
=======================================
--- /dev/null
+++ /grammar/src/main/scala/noop/grammar/ParseException.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,24 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+/**
+ * Thrown by our parser when ANTLR reports some errors while lexing or
parsing.
+ *
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class ParseException(val message: String) extends RuntimeException(message)
=======================================
--- /dev/null
+++ /grammar/src/main/scala/noop/grammar/Parser.scala Mon Feb 1 12:11:10
2010
@@ -0,0 +1,108 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import java.io.InputStream;
+
+import org.antlr.runtime.{ANTLRInputStream, ANTLRStringStream,
CommonTokenStream};
+import org.antlr.runtime.tree.{CommonTree, CommonTreeNodeStream};
+
+import model.SourceFile;
+import grammar.antlr.{DocLexer, DocParser, NoopAST, NoopParser, NoopLexer};
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class Parser() {
+
+ def buildParser(input: ANTLRStringStream): (NoopLexer, NoopParser) = {
+ val lexer = new NoopLexer(input);
+
+ return (lexer, new NoopParser(new CommonTokenStream(lexer)));
+ }
+
+ def buildDocParser(input: ANTLRStringStream): (DocLexer, DocParser) = {
+ val lexer = new DocLexer(input);
+
+ return (lexer, new DocParser(new CommonTokenStream(lexer)));
+ }
+
+ def parseFile(source: InputStream): CommonTree = {
+ val (lexer, parser) = buildParser(new ANTLRInputStream(source));
+
+ return parseFile(lexer, parser);
+ }
+
+ def parseFile(source: String): CommonTree = {
+ val (lexer, parser) = buildParser(new ANTLRStringStream(source));
+
+ return parseFile(lexer, parser);
+ }
+
+ def parseFile(lexer: NoopLexer, parser: NoopParser): CommonTree = {
+ val file = parser.file();
+
+ if (parser.hadErrors || lexer.hadErrors) {
+ throw new ParseException("Source failed to parse");
+ }
+ return file.getTree().asInstanceOf[CommonTree];
+ }
+
+ def parseInterpretable(source: String): CommonTree = {
+ val (lexer, parser) = buildParser(new ANTLRStringStream(source));
+ val interpretable = parser.interpretable();
+
+ if (parser.hadErrors || lexer.hadErrors) {
+ throw new ParseException("Source failed to parse");
+ }
+ return interpretable.getTree().asInstanceOf[CommonTree];
+ }
+
+ def parseBlock(source: String): CommonTree = {
+ val (lexer, parser) = buildParser(new ANTLRStringStream(source));
+ val block = parser.block();
+
+ if (parser.hadErrors || lexer.hadErrors) {
+ throw new ParseException("Source failed to parse");
+ }
+ return block.getTree().asInstanceOf[CommonTree];
+ }
+
+ def parseDoc(source: String): CommonTree = {
+ val (lexer, parser) = buildDocParser(new ANTLRStringStream(source));
+ val doc = parser.doc();
+
+ return doc.getTree().asInstanceOf[CommonTree];
+ }
+
+ def buildTreeParser(ast: CommonTree): NoopAST = {
+ return new NoopAST(new CommonTreeNodeStream(ast));
+ }
+
+ def file(ast: CommonTree): SourceFile = {
+ val treeParser = buildTreeParser(ast);
+ val file = treeParser.file();
+
+ if (treeParser.hadErrors) {
+ throw new ParseException("Syntax errors");
+ }
+ return file;
+ }
+
+ def file(source: String): SourceFile = file(parseFile(source));
+
+ def file(source: InputStream): SourceFile = file(parseFile(source));
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/BindingSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar
+
+
+import org.scalatest.matchers.ShouldMatchers
+import noop.model.{ExpressionWrapper, BindingDefinition,
StringLiteralExpression, IdentifierExpression}
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class BindingSpec extends Spec with ShouldMatchers {
+ val parser = new Parser();
+
+ describe("the binding keyword") {
+
+ it("allows the binding operator in a binding") {
+ val source = "binding Something { " +
+ "BankService -> BankServiceImpl; " +
+ "Port -> 9876; " +
+ "Max -> firstThing;" +
+ "}";
+ parser.parseFile(source).toStringTree() should be(
+ "(BINDING Something (BIND BankService BankServiceImpl) (BIND Port
9876) (BIND Max firstThing))");
+ val file = parser.buildTreeParser(parser.parseFile(source)).file;
+ val bindingDef = file.classDef.asInstanceOf[BindingDefinition];
+ bindingDef.bindings should have length(3);
+ bindingDef.bindings.first.noopType should be("BankService");
+ bindingDef.bindings.first.boundTo.getClass() should
be(classOf[IdentifierExpression]);
+
bindingDef.bindings.first.boundTo.asInstanceOf[IdentifierExpression].identifier
should be ("BankServiceImpl");
+ }
+
+ it("can appear as an anonymous binding block") {
+ val source = "class Foo() { Int thing() { binding(A -> B) {} } }";
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING (BIND A
B))))");
+ val file = parser.buildTreeParser(parser.parseFile(source)).file;
+ val method = file.classDef.methods.first;
+ method.block.anonymousBindings should have length(1);
+ method.block.namedBinding should be(None);
+ val firstBinding = method.block.anonymousBindings.first;
+ firstBinding.noopType should be("A");
+ firstBinding.boundTo.getClass() should
be(classOf[IdentifierExpression]);
+ firstBinding.boundTo.asInstanceOf[IdentifierExpression].identifier
should be ("B");
+
+ }
+
+ it("can appear as a named binding block") {
+ val source = "class Foo() { Int thing() { binding MyBinding {} } }";
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING
MyBinding)))");
+ val file = parser.buildTreeParser(parser.parseFile(source)).file;
+ val method = file.classDef.methods.first;
+ method.block.anonymousBindings should be('empty);
+ method.block.namedBinding should be(Some("MyBinding"));
+ }
+
+ it("can not appear in a method declaration with a name") {
+ val source = "class Foo() { Int thing() binding MyBinding {} }";
+ intercept[ParseException] {
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING
MyBinding)))");
+ }
+ }
+
+ it("can not appear anonymously in a method declaration") {
+ val source = "class Foo() { Int thing() binding(This -> that) {} }";
+ intercept[ParseException] {
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING (BIND This
that))))");
+ }
+ }
+
+ it("can appear in a unittest declaration with a name") {
+ val source = "class Foo() { unittest \"test this\" binding MyBinding
{} }";
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (UNITTEST \"test this\" (BINDING MyBinding)))");
+ val file = parser.buildTreeParser(parser.parseFile(source)).file;
+ val method = file.classDef.unittests.first;
+ method.block.anonymousBindings should be('empty);
+ method.block.namedBinding should be(Some("MyBinding"));
+ }
+
+ it("can appear anonymously in a unittest declaration") {
+ val source = "class Foo() { unittest \"test this\" binding(String ->
\"foo\") {} }";
+ parser.parseFile(source).toStringTree() should be(
+ "(CLASS Foo (UNITTEST \"test this\" (BINDING (BIND String
\"foo\"))))");
+ val file = parser.buildTreeParser(parser.parseFile(source)).file;
+ val method = file.classDef.unittests.first;
+ method.block.anonymousBindings should have length(1);
+ val firstBinding = method.block.anonymousBindings.first;
+ firstBinding.noopType should be("String");
+ val typedExpression =
firstBinding.boundTo.asInstanceOf[ExpressionWrapper].getTypedExpression;
+ typedExpression.asInstanceOf[StringLiteralExpression].value should
be ("foo");
+ }
+ }
+
+ describe("the type alias") {
+ it("should parse") {
+ val source = "binding App { alias Int Port; }";
+ parser.parseFile(source).toStringTree() should be(
+ "(BINDING App (alias Int Port))");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/BlockSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,166 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import collection.mutable.ArrayBuffer;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+import noop.model._;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class BlockSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("a block") {
+
+ it("should allow a return statement") {
+ val blockAst = parser.parseBlock("{ return 0; }");
+
+ blockAst.toStringTree() should be("(return 0)");
+ val block = parser.buildTreeParser(blockAst).block();
+
+ block.statements.size should be(1);
+ block.statements(0).getClass() should be(classOf[ReturnExpression]);
+ val returnExpression =
block.statements(0).asInstanceOf[ReturnExpression];
+
+ val typedExpression =
returnExpression.expr.asInstanceOf[ExpressionWrapper].getTypedExpression
+ typedExpression.getClass should be(classOf[IntLiteralExpression]);
+ typedExpression.asInstanceOf[IntLiteralExpression].value should
be(0);
+ }
+
+ it("should allow chained property access on properties") {
+ val source = "{ b.c.d; }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be("(. (. b c) d)");
+ val block = parser.buildTreeParser(blockAst).block();
+
+ block.statements.size should be(1);
+ block.statements(0).getClass() should
be(classOf[DereferenceExpression]);
+ val deref1 = block.statements(0).asInstanceOf[DereferenceExpression];
+ deref1.left.getClass() should be(classOf[DereferenceExpression]);
+ deref1.right.getClass() should be(classOf[IdentifierExpression]);
+ deref1.right.asInstanceOf[IdentifierExpression].identifier should
be("d");
+
+ val deref2 = deref1.left.asInstanceOf[DereferenceExpression];
+ deref2.left.getClass() should be(classOf[IdentifierExpression]);
+ deref2.right.getClass() should be(classOf[IdentifierExpression]);
+ deref2.left.asInstanceOf[IdentifierExpression].identifier should
be("b");
+ deref2.right.asInstanceOf[IdentifierExpression].identifier should
be("c");
+ }
+
+ it("should allow a method call on implicit 'this'") {
+ val source = "{ a(); }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be ("a ARGS");
+ val block = parser.buildTreeParser(blockAst).block();
+ block.statements.size should be(1);
+ block.statements(0).getClass() should
be(classOf[MethodInvocationExpression]);
+ val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
+ methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
+ methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("this");
+ methodInvocation.name should be("a");
+ methodInvocation.arguments should be ('empty);
+ }
+
+ it("should allow calling a method on an identifier") {
+ val source = "{ a.b(); }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be("(. a b ARGS)");
+ val block = parser.buildTreeParser(blockAst).block();
+ block.statements.size should be(1);
+
+ block.statements(0).getClass() should
be(classOf[MethodInvocationExpression]);
+ val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
+ methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
+ methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("a");
+ methodInvocation.name should be("b");
+ methodInvocation.arguments should be(new ArrayBuffer[Expression]);
+ methodInvocation.arguments.isEmpty should be (true);
+ }
+
+ it("should allow method chaining") {
+ val source = "{ a.b().c(); }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be("(. (. a b ARGS) c ARGS)");
+ val block = parser.buildTreeParser(blockAst).block();
+ block.statements should have length (1);
+
+ val method1 =
block.statements(0).asInstanceOf[MethodInvocationExpression];
+ method1.left.getClass() should
be(classOf[MethodInvocationExpression]);
+ val method2 = method1.left.asInstanceOf[MethodInvocationExpression];
+
+ method2.left.getClass() should be(classOf[IdentifierExpression]);
+ method2.left.asInstanceOf[IdentifierExpression].identifier should
be("a");
+ method2.name should be("b");
+ method2.arguments should be ('empty);
+
+ method1.name should be("c");
+ method1.arguments should be('empty);
+ }
+
+ it("should allow a method call on a property") {
+ val source = "{ a.b.c(); }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be("(. (. a b) c ARGS)");
+ val block = parser.buildTreeParser(blockAst).block();
+ block.statements should have length (1);
+
+ val method =
block.statements(0).asInstanceOf[MethodInvocationExpression];
+ method.left.getClass() should be(classOf[DereferenceExpression]);
+ val deref = method.left.asInstanceOf[DereferenceExpression];
+
+ deref.left.getClass() should be(classOf[IdentifierExpression]);
+ deref.left.asInstanceOf[IdentifierExpression].identifier should
be("a");
+ deref.right.getClass() should be(classOf[IdentifierExpression]);
+ deref.right.asInstanceOf[IdentifierExpression].identifier should
be("b");
+
+ method.name should be("c");
+ method.arguments should be('empty);
+ }
+
+ it("should allow a method call with arguments") {
+ val source = "{ a.b(c, \"d\"); }";
+ val blockAst = parser.parseBlock(source);
+
+ blockAst.toStringTree() should be ("(. a b (ARGS c \"d\"))");
+
+ val block = parser.buildTreeParser(blockAst).block();
+ block.statements.size should be(1);
+
+ val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
+ methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
+ methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("a");
+ methodInvocation.name should be("b");
+ methodInvocation.arguments should have length(2);
+ methodInvocation.arguments(0).getClass() should
be(classOf[IdentifierExpression]);
+
methodInvocation.arguments(0).asInstanceOf[IdentifierExpression].identifier
should be("c");
+ val typedExpression =
methodInvocation.arguments(1).asInstanceOf[ExpressionWrapper].getTypedExpression
+ typedExpression.getClass() should
be(classOf[StringLiteralExpression]);
+ typedExpression.asInstanceOf[StringLiteralExpression].value should
be ("d");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/ClassSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,114 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers
+import noop.model.{ConcreteClassDefinition, Modifier};
+import org.scalatest.Spec;
+
+
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class ClassSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("parser") {
+
+ it("should fail to parse a class with no parenthesis") {
+ val source = "class Bar {}";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+
+ it("should parse a class with no parameters") {
+ val source = "class Bar() {}";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar)");
+ }
+
+ it("should parse a class with one parameter") {
+ val source = "class Bar(String a) {}";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar (PARAMS (PARAM
String a)))");
+
+ val file = parser.file(source);
+ file.classDef.name should be ("Bar");
+ val concreteClass =
file.classDef.asInstanceOf[ConcreteClassDefinition];
+ concreteClass.parameters(0).name should be ("a");
+ concreteClass.parameters(0).noopType should be ("String");
+ }
+
+ it("should parse a class with a fully-qualified type in a parameter") {
+ val source = "class Bar(noop.String a) {}";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar (PARAMS (PARAM
noop String a)))");
+
+ val file = parser.file(source);
+ val concreteClass =
file.classDef.asInstanceOf[ConcreteClassDefinition];
+ concreteClass.parameters(0).noopType should be ("noop.String");
+ }
+
+ it("should parse a class with multiple parameters") {
+ val source = "class Bar(A a, B b, C c) {}";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal (
+ "(CLASS Bar (PARAMS (PARAM A a) (PARAM B b) (PARAM C c)))");
+ }
+
+ it("should allow modifiers on the parameters") {
+ val source = "class Bar(mutable A a, delegate B b, mutable delegate
C c) {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Bar (PARAMS (PARAM (MOD mutable) A a) (PARAM (MOD
delegate) B b) " +
+ "(PARAM (MOD mutable delegate) C c)))");
+ }
+
+ it("should allow an implements clause with one interface") {
+ val source = "class Foo() implements Bar {}";
+
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Foo (IMPL Bar))");
+ }
+
+ it("should allow an implements clause with several interfaces") {
+ val source = "class Foo() implements A, a.b.C, d.E {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Foo (IMPL A) (IMPL a b C) (IMPL d E))");
+ val file = parser.file(source);
+ file.classDef.name should be ("Foo");
+ val concreteDef =
file.classDef.asInstanceOf[ConcreteClassDefinition];
+ concreteDef.interfaces(0) should be("A");
+ concreteDef.interfaces(1) should be ("a.b.C");
+ concreteDef.interfaces(2) should be ("d.E");
+ }
+
+ it("should allow the native modifier on a class") {
+ val source = "native class Foo() {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS (MOD native) Foo)");
+ val file = parser.file(source);
+ file.classDef.modifiers should contain(Modifier.native);
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/CommentsSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,67 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class CommentsSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("parser") {
+
+ it("should be able to parse a single line comment") {
+ val source = "// a comment\n class Foo() {}\n";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Foo)");
+ }
+
+ it("should be able to parse a multi-line comment") {
+ val source = """
+ /** hello
+ bonjour
+ */class Foo() {}
+ """;
+ var commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Foo)");
+ }
+
+ it("should be able to parse nested comments") {
+ val source = """
+ /** hello
+ // bonjour
+ *
+ class Foo() {} */class Foo() {}
+ """;
+ var commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Foo)");
+ }
+
+ // Note: this makes Alex sad.
+ it("should allow tab characters to appear in the source") {
+ val source = "\tclass\tFoo() {\t}";
+ parser.parseFile(source).toStringTree() should equal ("(CLASS Foo)");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/DocumentationSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class DocumentationSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("documentation") {
+
+ it("should appear before a class definition, in a string literal") {
+ val source = "\"This class is awesome\" class Awesome() {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Awesome (DOC \"This class is awesome\"))");
+ val file = parser.file(source);
+ file.classDef.documentation should equal("This class is awesome");
+ }
+
+ it("should appear before a method declaration") {
+ val source = "class Foo() { \"Here is my great method\" Int doIt()
{}}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Foo (METHOD (DOC \"Here is my great method\")
(RETURN_TYPE Int) doIt))");
+ val file = parser.file(source);
+ file.classDef.methods(0).documentation should equal ("Here is my
great method");
+ }
+
+ it("can use the triple-quoted string literal and appear on an
interface") {
+ val source = "\"\"\"\nMulti-line\ndocumentation\n\"\"\" interface
Bar {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(INTERFACE Bar (DOC
\"\"\"\nMulti-line\ndocumentation\n\"\"\"))");
+ val file = parser.file(source);
+ file.classDef.documentation should equal
("\nMulti-line\ndocumentation\n");
+ }
+
+ it("should appear before a bindings definition") {
+ val source = "\"Stuff you need bound\" binding Stuff {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(BINDING Stuff (DOC \"Stuff you need bound\"))");
+ val file = parser.file(source);
+ file.classDef.documentation should equal("Stuff you need bound");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/ExpressionsSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers
+import noop.model.{ExpressionWrapper, OperatorExpression,
IntLiteralExpression, IdentifierDeclarationExpression};
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class ExpressionsSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("the parser") {
+
+ it("should parse a variable assignment") {
+ val source = "{ Int a = 3; }";
+ parser.parseBlock(source).toStringTree() should equal ("(VAR Int (=
a 3))");
+ }
+
+ it("should parse arithmetic") {
+ val source = "{ Float a = 3 + 4 / (5 * (6 + 7)) % 8; }";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(VAR Float (= a (+ 3 (% (/ 4 (* 5 (+ 6 7))) 8))))");
+ val block =
parser.buildTreeParser(parser.parseBlock(source)).block();
+ block.statements should have length(1);
+ block.statements(0).getClass should
be(classOf[IdentifierDeclarationExpression]);
+ val declaration =
block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
+ declaration.initialValue should be ('defined);
+ val expression1 =
declaration.initialValue.get().asInstanceOf[OperatorExpression];
+ expression1.operator should be ("+");
+ val typedExpression =
expression1.left.asInstanceOf[ExpressionWrapper].getTypedExpression
+ typedExpression.asInstanceOf[IntLiteralExpression].value should be
(3);
+ val expression2 = expression1.asInstanceOf[OperatorExpression].right;
+ expression2.asInstanceOf[OperatorExpression].operator should be
("%");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/FileSpec.scala Mon Feb 1 12:11:10
2010
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class FileSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("parser") {
+
+ it("should allow the word 'test' as a package name") {
+ // TODO(alexeagle)
+ }
+
+ it("should parse namespace declaration") {
+ val source = "namespace noop.demo; class Foo() {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(namespace noop demo) (CLASS Foo)");
+ }
+
+ it("should allow import in default namespace") {
+ val source = "import Foo; class B(){}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(import Foo) (CLASS B)");
+ }
+
+ it("should parse import statements") {
+ val source = "import noop.demo.Test; class Foo() {}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(import noop demo Test) (CLASS Foo)");
+ }
+
+ it("should not allow import without a type on the end") {
+ val source = "import noop.demo;";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+
+ it("should parse a realistic looking file header") {
+ val source = """
+ namespace noop.grammar;
+ // TODO: it should fail when a semicolon is missing, but the test
still passes
+ import org.antlr.runtime.RecognitionException;
+ import org.scalatest.Spec;
+ import org.scalatest.matchers.ShouldMatchers;
+
+ class FileSpec() {
+ }
+ """;
+ parser.parseFile(source).toStringTree() should equal (
+ "(namespace noop grammar) (import org antlr runtime
RecognitionException) " +
+ "(import org scalatest Spec) (import org scalatest matchers
ShouldMatchers) " +
+ "(CLASS FileSpec)");
+ val file = parser.file(source);
+ file.namespace should be ("noop.grammar");
+ file.imports(0) should be ("org.antlr.runtime.RecognitionException");
+ file.imports(1) should be ("org.scalatest.Spec");
+ file.imports(2) should be ("org.scalatest.matchers.ShouldMatchers");
+ }
+
+ it ("should not allow extra stuff after the class definition") {
+ val source = "class Foo() {} extra stuff";
+ //intercept[ParseException] {
+ // parser.parseFile(source);
+ //}
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/IfSpec.scala Mon Feb 1 12:11:10
2010
@@ -0,0 +1,101 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class IfSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("an if expression") {
+
+ it("should parse correctly equality expression on two literals") {
+ val source = "{ if (1 == 1) { } }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (== 1 1))");
+ }
+
+ it("should parse correctly an inequality expression on two literals") {
+ val source = "{ if (1 != 2) { } }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (!= 1 2))");
+ }
+
+ it("should parse correctly an inequality expression followed by an
or'ed equality expression on literals") {
+ val source = "{ if (1 != 2 || 1 == 1) { } }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (|| (!= 1 2) (== 1 1)))");
+ }
+
+ it("should parse correctly an inequality expression followed by an
and'ed equality expression on literals") {
+ val source = "{ if (1 != 2 && 1 == 1) { } }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (&& (!= 1 2) (== 1 1)))");
+ }
+
+ it("should parse correctly complex conditional with or and and
primaries") {
+ val source = "{ if (1 != a.getValue() && \"hello\" != \"wolrd\" ||
50 == myVar) { } }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (|| (&& (!= 1 (. a getValue
ARGS)) (!= \"hello\" \"wolrd\")) (== 50 myVar)))");
+ }
+
+ it("should parse correctly greater than conditional") {
+ val source = "{ if (1 > 3) {} }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (> 1 3))");
+ }
+
+ it("should parse correctly lesser than conditional") {
+ val source = "{ if (1 < 3) {} }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (< 1 3))");
+ }
+
+ it("should parse correctly greater than or equal conditional") {
+ val source = "{ if (1 >= 3) {} }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (>= 1 3))");
+ }
+
+ it("should parse correctly lesser than or equal conditional") {
+ val source = "{ if (1 <= 3) {} }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(IF (<= 1 3))");
+ }
+
+ it("should parse regular expression") {
+ val source = "{ boolean b = false; if (b = true) {} }";
+ val ifBlock = parser.parseBlock(source);
+
+ ifBlock.toStringTree() should be("(= boolean b false) (IF (= b
true))");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/InterfaceSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class InterfaceSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("interface") {
+
+ it("should parse an interface with no methods") {
+ val source = "interface MyInterface {}";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(INTERFACE MyInterface)");
+ }
+
+ it("should parse an interface with one method") {
+ val source = "interface MyInterface { Int helloWorld(); }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(INTERFACE MyInterface
(METHOD (RETURN_TYPE Int) helloWorld))");
+ }
+
+ it("should not parse an interface with a method having a body") {
+ val source = "interface MyInterface { Int helloWorld() { Int i = 0;
} }";
+
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/InterpretableSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,55 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class InterpretableSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("the parser") {
+
+ it("should parse an import as interpretable") {
+ val source = "import noop.Foo;";
+ parser.parseInterpretable(source).toStringTree() should equal (
+ "(import noop Foo)");
+ }
+
+ it("should parse a class definition as interpretable") {
+ val source = "class F() {}";
+ parser.parseInterpretable(source).toStringTree() should equal (
+ "(CLASS F)");
+ }
+
+ it("should parse a variable declaratian as interpretable") {
+ val source = "Int a = 3;";
+ parser.parseInterpretable(source).toStringTree() should equal (
+ "(VAR Int (= a 3))");
+ }
+
+ it("should parse several statements at once") {
+ val source = """Int a = 3; import foo.Foo; String b = "poop"; class
F() {}""";
+ parser.parseInterpretable(source).toStringTree() should equal (
+ """(VAR Int (= a 3)) (import foo Foo) (VAR String (= b "poop"))
(CLASS F)""");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/LiteralsSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers
+import noop.model.{ExpressionWrapper, BooleanLiteralExpression,
IdentifierDeclarationExpression};
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class LiteralsSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("the parser") {
+
+ it("should parse integer literals") {
+ val source = "{ Int a = 123; Int b = -123; } ";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(VAR Int (= a 123)) (VAR Int (= b -123))");
+ }
+
+ it("should parse a string literal") {
+ val source = " { a = \"hello, world!\"; } ";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(= a \"hello, world!\")");
+ }
+
+ it("should parse a multi-line string literal") {
+ val source = "{ String a = \"\"\"Line1\n\"Line2\"\n\"\"\"; }";
+ parser.parseBlock(source).toStringTree() should equal(
+ "(VAR String (= a \"\"\"Line1\n\"Line2\"\n\"\"\"))");
+ }
+
+ it("should not allow a single-double-quoted string to span lines") {
+ val source = """{ a = "Line 1
+ "; }""";
+ intercept[ParseException] (parser.parseBlock(source));
+ }
+
+ it("should parse boolean literals") {
+ val source = "{ Boolean a = true; }";
+ parser.parseBlock(source).toStringTree() should equal ("(VAR Boolean
(= a true))");
+ val statement =
parser.buildTreeParser(parser.parseBlock(source)).block().statements(0)
+ .asInstanceOf[IdentifierDeclarationExpression];
+ statement.initialValue match {
+ case Some(b) => {
+
b.asInstanceOf[ExpressionWrapper].getTypedExpression.asInstanceOf[BooleanLiteralExpression].value
should be (true);
+ }
+ case None => fail();
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/LoopSpec.scala Mon Feb 1 12:11:10
2010
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers
+import noop.model.{ExpressionWrapper, BooleanLiteralExpression, WhileLoop};
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class LoopSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("a while loop") {
+
+ it("should be formed with a while statement") {
+ val source = "{ while(true) {} }";
+ parser.parseBlock(source).toStringTree() should be ("(WHILE true)");
+ val block =
parser.buildTreeParser(parser.parseBlock(source)).block();
+ block.statements(0).getClass() should be (classOf[WhileLoop]);
+ val whileLoop = block.statements(0).asInstanceOf[WhileLoop];
+ val typedExpression =
whileLoop.continueCondition.asInstanceOf[ExpressionWrapper].getTypedExpression
+ typedExpression.asInstanceOf[BooleanLiteralExpression].value should
be(true);
+ }
+ }
+
+ describe("a for loop") {
+
+ it("should be formed with a for-in statement") {
+ val source = "{ for (Int i in 1.to(10)) {} }";
+ parser.parseBlock(source).toStringTree() should be("(FOREACH (VAR
Int i) (. 1 to (ARGS 10)))");
+ }
+
+ it("should allow an existing identifier to be the loop variable") {
+ val source = "{ Int i; for (i in 1.to(10)) {} }";
+ parser.parseBlock(source).toStringTree() should be("(VAR Int i)
(FOREACH i (. 1 to (ARGS 10)))");
+ }
+
+ it("should allow a c-style loop with explicit initialization,
termination, and iteration expressions") {
+ val source = "{ for (Int i = 1; i < 3; i = i + 1) {} }";
+ parser.parseBlock(source).toStringTree() should be("(FOR (VAR Int (=
i 1)) (< i 3) (= i (+ i 1)))");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/MethodsSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,184 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+import model.{IdentifierDeclarationExpression, Modifier};
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class MethodsSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("the parser") {
+
+ it("should parse a method with no parameters") {
+ val source = "class Bar() { String helloWorld() { Int i = 1; } }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
+ "(VAR Int (= i 1))))");
+ }
+
+ it("should parse a method with parameters") {
+ val source = "class Bar() { String helloWorld(String s, Int n) { Int
i = 1; } }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
+ "(PARAMS (PARAM String s) (PARAM Int n)) (VAR Int (= i 1))))");
+
+ val file = parser.file(source);
+ file.classDef.methods.size should be (1);
+ val firstMethod = file.classDef.methods(0)
+ firstMethod.name should be ("helloWorld");
+ firstMethod.returnTypes.size should be (1);
+ firstMethod.returnTypes(0) should be ("String");
+ firstMethod.parameters.size should be (2);
+ firstMethod.parameters(0).name should be ("s");
+ firstMethod.parameters(0).noopType should be ("String");
+ firstMethod.parameters(1).name should be ("n");
+ firstMethod.parameters(1).noopType should be ("Int");
+ firstMethod.block.statements.size should be (1);
+ firstMethod.block.statements(0).getClass() should be
(classOf[IdentifierDeclarationExpression]);
+ val firstStatement =
firstMethod.block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
+ firstStatement.noopType should be ("Int");
+ firstStatement.name should be ("i");
+ // firstStatement.initialValue should be (Some(new
IntLiteralExpression(1)));
+ }
+
+ it("should allow variable declaration without an initial value") {
+ val source = "class Bar() { String helloWorld() { Int i; } }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
+ "(VAR Int i)))");
+
+ val file = parser.file(source);
+ file.classDef.methods.size should be (1);
+ val firstMethod = file.classDef.methods(0)
+ val firstStatement =
firstMethod.block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
+
+ firstStatement.noopType should be ("Int");
+ firstStatement.name should be ("i");
+ firstStatement.initialValue should be (None);
+ }
+
+ it("should parse a method invocation on a parameter reference") {
+ val source = """class HelloWorld() { Int hello() {
console.println("Hello, World!"); }}""";
+ parser.parseFile(source).toStringTree() should equal(
+ """(CLASS HelloWorld (METHOD (RETURN_TYPE Int) hello (. console
println (ARGS "Hello, World!"))))""");
+ }
+
+ it("should parse a method with a return statement") {
+ val source = "class Foo() { Void do() { return 4; } }";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Foo (METHOD (RETURN_TYPE Void) do (return 4)))");
+ }
+
+ it("should allow the native modifier on a method") {
+ val source = "class Foo() { native Void do() { Int i; }}";
+ parser.parseFile(source).toStringTree() should equal (
+ "(CLASS Foo (METHOD (MOD native) (RETURN_TYPE Void) do (VAR Int
i)))");
+ val file = parser.file(source);
+ file.classDef.methods(0).modifiers should contain(Modifier.native);
+ }
+
+ it("should parse a method with one return type (no parentheses)") {
+ val source = "class Math() { Int calculate() {} }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal (
+ "(CLASS Math (METHOD (RETURN_TYPE Int) calculate))");
+
+ val file = parser.file(source);
+ file.classDef.methods.size should be (1);
+ val firstMethod = file.classDef.methods(0);
+ firstMethod.name should be ("calculate");
+ firstMethod.returnTypes.size should be (1);
+ firstMethod.returnTypes(0) should be ("Int");
+ firstMethod.parameters.size should be (0);
+ firstMethod.block.statements.size should be (0);
+ }
+
+ it("should parse a method with one return type (parentheses)") {
+ val source = "class Math() { (Int) calculate() {} }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal (
+ "(CLASS Math (METHOD (RETURN_TYPE Int) calculate))");
+
+ val file = parser.file(source);
+ file.classDef.methods.size should be (1);
+ val firstMethod = file.classDef.methods(0);
+ firstMethod.name should be ("calculate");
+ firstMethod.returnTypes.size should be (1);
+ firstMethod.returnTypes(0) should be ("Int");
+ firstMethod.parameters.size should be (0);
+ firstMethod.block.statements.size should be (0);
+ }
+
+ it("should parse a method with multiple return types") {
+ val source = "class Math() { (Int, Int) calculate() {} }";
+ val commonTree = parser.parseFile(source);
+
+ commonTree.toStringTree() should equal (
+ "(CLASS Math (METHOD (RETURN_TYPE Int Int) calculate))");
+
+ val file = parser.file(source);
+ file.classDef.methods.size should be (1);
+ val firstMethod = file.classDef.methods(0);
+ firstMethod.name should be ("calculate");
+ firstMethod.returnTypes.size should be (2);
+ firstMethod.returnTypes(0) should be ("Int");
+ firstMethod.returnTypes(1) should be ("Int");
+ firstMethod.parameters.size should be (0);
+ firstMethod.block.statements.size should be (0);
+ }
+
+ it ("should NOT parse a method with one named return parameter (no
parentheses)") {
+ val source = "class Math() { Int a calculate() {} }";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+
+ it ("should NOT parse a method with one named return parameter
(parentheses)") {
+ val source = "class Math() { (Int a) calculate() {} }";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+
+ it ("should NOT parse a method with a mixture of named and unnamed
return parameters") {
+ val source = "class Math() { (Int, Int b, Int) calculate() {} }";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+
+ it ("should NOT parse a method with multiple named return parameters")
{
+ val source = "class Math() { (Int a, Int b) calcualte() {} }";
+ intercept[ParseException] {
+ parser.parseFile(source);
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/ParseExamplesTest.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar
+
+import org.scalatest.Spec
+import org.scalatest.matchers.ShouldMatchers
+import java.io.{FileInputStream, File}
+
+class ParseExamplesTest extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("the parser") {
+ it("should parse all the .noop files found under the /examples
directory") {
+ val examplesDir = new File(new
File(System.getProperty("user.dir")), "examples");
+ parseAllFilesInDirectory(examplesDir);
+ }
+ }
+
+ def parseAllFilesInDirectory(dir: File): Unit = {
+ for (file: File <- dir.listFiles) {
+ if (file.isDirectory) {
+ parseAllFilesInDirectory(file);
+ } else {
+ if (file.getName.endsWith(".noop")) {
+ try {
+ parser.parseFile(new FileInputStream(file));
+ } catch {
+ case e: ParseException => fail("failed to parse " +
file.getAbsolutePath());
+ }
+ }
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/ParserSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class ParserSpec extends Spec with ShouldMatchers {
+
+ describe("our parser") {
+
+ it("should throw an exception if there's an error parsing the AST") {
+ val source = "class MyClass() { Int foo() { Int result =
List.List(List()); } }";
+ val parser = new Parser();
+ parser.parseFile(source).toStringTree() should be (
+ "(CLASS MyClass (METHOD (RETURN_TYPE Int) foo (VAR Int (= result
(. List List (ARGS List ARGS))))))");
+ intercept[ParseException] {
+ val classDef = parser.file(source);
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/PropertiesSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
+ */
+class PropertiesSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("parser") {
+
+ it("should parse a single property declaration") {
+ val source = """
+ class Foo() {
+ Int a = 4;
+ Int i;
+ }
+ """;
+
+ parser.parseFile(source).toStringTree() should equal ("(CLASS Foo
(VAR Int (= a 4)) (VAR Int i))");
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/TestSpec.scala Mon Feb 1 12:11:10
2010
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar;
+
+import org.scalatest.matchers.ShouldMatchers;
+import org.scalatest.Spec;
+
+import model.ShouldExpression;
+
+/**
+ * @author alex...@google.com (Alex Eagle)
+ */
+class TestSpec extends Spec with ShouldMatchers {
+
+ val parser = new Parser();
+
+ describe("test block declarations") {
+
+ it("should allow a unittest block in a class") {
+ val source = "class Foo() { unittest \"testing 123\" {} }";
+ parser.parseFile(source).toStringTree() should equal(
+ "(CLASS Foo (UNITTEST \"testing 123\"))");
+ val classDef = parser.file(source).classDef;
+ classDef.methods should have length(0);
+ classDef.unittests should have length(1);
+ classDef.unittests(0).name should be("testing 123");
+ }
+
+ it("should not allow a unittest block in a method") {
+ val source = "class Foo() { Int do() { unittest \"testing 123\" {} }
}";
+ intercept[ParseException] (
+ parser.parseFile(source)
+ );
+ }
+
+ it("should not allow a test block in a class") {
+ val source = "class Foo() { test \"testing 123\" {} }";
+ intercept[ParseException] (
+ parser.parseFile(source)
+ );
+ }
+
+ it("should allow a test block in a file") {
+ val source = "test \"testing 123\" {}";
+ parser.parseFile(source).toStringTree() should equal("(TEST
\"testing 123\")");
+ }
+
+ it("should allow a unittest block in a test block") {
+ val source = "test \"testing 123\" { unittest \"it should work\" {}
}";
+ parser.parseFile(source).toStringTree() should equal(
+ "(TEST \"testing 123\" (UNITTEST \"it should work\"))");
+ }
+
+ it("should allow a test block in a test block") {
+ val source = "test \"testing 123\" { test \"it should work\" {} }";
+ parser.parseFile(source).toStringTree() should equal(
+ "(TEST \"testing 123\" (TEST \"it should work\"))");
+ }
+
+ it("should not allow a unittest block in a unittest block") {
+ val source = "unittest \"testing 123\" { unittest \"it should work\"
{} }";
+ intercept[ParseException] (
+ parser.parseFile(source)
+ );
+ }
+ }
+
+ describe("the testing DSL") {
+
+ it("should have a 'should' operator") {
+ val source = "{ 1 should equal(1); }";
+ parser.parseBlock(source).toStringTree() should be("(should 1 equal
(ARGS 1))");
+ val statement =
parser.buildTreeParser(parser.parseBlock(source)).block().statements(0);
+ statement.getClass() should be(classOf[ShouldExpression]);
+ }
+ }
+}
=======================================
--- /dev/null
+++ /grammar/src/test/scala/noop/grammar/TryCatchSpec.scala Mon Feb 1
12:11:10 2010
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed 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 noop.grammar
+
+import org.scalatest.matchers.ShouldMatchers
+import org.scalatest.Spec
+
+class TryCatchSpec extends Spec with ShouldMatchers {
+ val parser = new Parser();
+
+ describe("the parser") {
+ it("should parse a try-catch block") {
+ val source = "{ try { parseInt(\"1\"); } catch { println(\"oops\");
} }";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(TRY parseInt (ARGS \"1\") CATCH println (ARGS \"oops\"))");
+ }
+
+ it("should parse a try-finally block") {
+ val source = "{ try { parseInt(\"1\"); } finally { cleanup(); } }";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(TRY parseInt (ARGS \"1\") FINALLY cleanup ARGS)");
+ }
+
+ it("should parse a try-catch-finally block") {
+ val source = "{ try { parseInt(\"1\"); } catch { println(\"oops\");
} finally { cleanup(); } }";
+ parser.parseBlock(source).toStringTree() should equal (
+ "(TRY parseInt (ARGS \"1\") CATCH println (ARGS \"oops\")
FINALLY cleanup ARGS)");
+ }
+ }
+
+}
=======================================
--- /core/src/main/antlr3/noop/grammar/antlr/Doc.g Mon Oct 19 04:42:14 2009
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// Licensed 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.
-
-grammar Doc;
-
-options {
- backtrack = true;
- output = AST;
- ASTLabelType = CommonTree;
-}
-
-@header {
- package noop.grammar.antlr;
-}
-
-@lexer::header {
- package noop.grammar.antlr;
-}
-
-@lexer::rulecatch {
- catch (RecognitionException e) {
- reportError(e);
- throw new RuntimeException(e);
- }
-}
-
-@rulecatch {
- catch (RecognitionException e) {
- reportError(e);
- throw e;
- }
-}
-
-doc
- : DocLine* docCommandDeclaration*
- ;
-
-docCommandDeclaration
- : docCommand DocLine*
- ;
-
-docCommand
- : '@param'
-// TODO(gabe) : '@param' VariableIdentifier
- | CustomCommand
- ;
-
-CustomCommand
- : '@' 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
- ;
-
-VariableIdentifier
- : 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
- ;
-
-DocLine
- : ~'@' ~('\n'|'\r')* '\r'? '\n'
- ;
-
-WS : (' '|'\t'|'\n')+
- ;
-
=======================================
--- /core/src/main/antlr3/noop/grammar/antlr/Noop.g Thu Dec 3 18:36:36 2009
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// Licensed 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.
-
-grammar Noop;
-
-options {
- backtrack = true;
- output = AST;
- ASTLabelType = CommonTree;
-}
-
-tokens {
- DOC;
- CLASS;
- INTERFACE;
- PARAMS;
- PARAM;
- METHOD;
- MOD;
- ARGS;
- VAR;
- IMPL;
- IF;
- WHILE;
- FOREACH;
- FOR;
- TEST;
- UNITTEST;
- BINDING;
- BIND;
- RETURN_TYPE;
- TRY;
- CATCH;
- FINALLY;
-}
-
-@header {
- package noop.grammar.antlr;
-}
-
-@lexer::header {
- package noop.grammar.antlr;
-}
-
-@members {
- public boolean hadErrors = false;
-
- @Override
- public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
- hadErrors = true;
- return super.getErrorMessage(e, tokenNames);
- }
-}
-
-@lexer::members {
- public boolean hadErrors = false;
-
- @Override
- public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
- hadErrors = true;
- return super.getErrorMessage(e, tokenNames);
- }
-}
-
-// A line of user input in the interactive interpreter
-interpretable
- : (importDeclaration
- | classDefinition
- | statement)+
- ;
-
-file
- : namespaceDeclaration? importDeclaration* (classDefinition |
interfaceDefinition | bindingDefinition | test)
- ;
-
-namespaceDeclaration
- : 'namespace'^ namespace ';'!
- ;
-
-importDeclaration
- : 'import'^ qualifiedType ';'!
- ;
-
-ifExpression
- : 'if' '(' expression ')' block* ('else' block*)?
- -> ^(IF expression* block*)
- ;
-
-methodDefinition
- : methodSignature block
- -> ^(METHOD methodSignature block?)
- ;
-
-namespace
- : VariableIdentifier ('.'! VariableIdentifier)*
- ;
-
-qualifiedType
- : (namespace '.'!)? TypeIdentifier
- ;
-
-classDefinition
- : doc? modifiers? 'class' TypeIdentifier parameterList typeSpecifiers?
classBlock
- -> ^(CLASS modifiers? TypeIdentifier parameterList? typeSpecifiers?
classBlock? doc?)
- ;
-
-doc
- : StringLiteral -> ^(DOC StringLiteral)
- ;
-
-typeSpecifiers
- : 'implements' qualifiedType (',' qualifiedType)*
- -> ^(IMPL qualifiedType)*
- ;
-
-interfaceDefinition
- : doc? 'interface' TypeIdentifier interfaceBlock
- -> ^(INTERFACE TypeIdentifier interfaceBlock? doc?)
- ;
-
-modifiers
- : modifier+
- -> ^(MOD modifier+)
- ;
-
-modifier
- : 'mutable' | 'delegate' | 'native'
- ;
-
-classBlock
- : '{'! (identifierDeclaration ';'!)* methodDefinition* unittest* '}'!
- ;
-
-interfaceBlock
- : '{'! methodDeclaration* '}'!
- ;
-
-test
- : 'test' StringLiteral '{' (statement* | test | unittest) '}'
- -> ^(TEST StringLiteral statement* test? unittest?)
- ;
-
-unittest
- : 'unittest' StringLiteral bindingDeclaration? block
- -> ^(UNITTEST StringLiteral bindingDeclaration? block?)
- ;
-
-methodSignature
- : doc? modifiers? returnType VariableIdentifier parameterList
throwsDeclaration?
- ;
-
-throwsDeclaration
- : 'throws' qualifiedType
- -> ^('throws' qualifiedType)
- ;
-
-returnType
- : TypeIdentifier -> ^(RETURN_TYPE TypeIdentifier)
- | '(' typeList ')' -> ^(RETURN_TYPE typeList)
- ;
-
-typeList
- : TypeIdentifier (','! TypeIdentifier)*
- ;
-
-methodDeclaration
- : methodSignature ';'
- -> ^(METHOD methodSignature)
- ;
-
-
-identifierDeclaration
- : TypeIdentifier identifierDeclarator
- -> ^(VAR TypeIdentifier identifierDeclarator)
- ;
-
-identifierDeclarator
- : VariableIdentifier ('='^ expression)?
- ;
-
-block
- : '{'! statement* '}'!
- ;
-
-statement
- : identifierDeclaration ';'!
- | whileLoop
- | forLoop
- | 'return'^ expression ';'!
- | expression ';'!
- | ifExpression
- | shouldStatement ';'!
- | bindingsBlock
- | tryCatchBlock
- ;
-
-tryCatchBlock
- : 'try' block 'catch' block ('finally' block)?
- -> ^(TRY block CATCH block (FINALLY block)?)
- | 'try' block 'finally' block
- -> ^(TRY block FINALLY block)
- ;
-
-//TODO(alex): The binding syntax seems a little scattered. Sometimes
semicolon, sometimes comma?
-bindingDefinition
- : doc? 'binding' qualifiedType '{' ((binding | typealias) ';')* '}'
- -> ^(BINDING qualifiedType doc? binding* typealias*)
- ;
-
-bindingDeclaration
- : 'binding' (bindings | qualifiedType)
- -> ^(BINDING bindings? qualifiedType?)
- ;
-
-bindingsBlock
- : 'binding' (bindings | qualifiedType) block
- -> ^(BINDING bindings? qualifiedType? block?)
- ;
-
-bindings
- : '('! binding? (','! binding)* ')'!
- ;
-
-binding
- : qualifiedType '->' expression
- -> ^(BIND qualifiedType expression)
- ;
-
-typealias
- : 'alias'^ qualifiedType TypeIdentifier
- ;
-
-shouldStatement
- : expression 'should'^ expression
- ;
-
-forLoop
- : 'for' '(' (identifierDeclaration|VariableIdentifier) 'in'
expression ')' block
- -> ^(FOREACH identifierDeclaration? VariableIdentifier? expression block?)
- | 'for' '(' identifierDeclaration ';' conditionalExpression ';'
expression ')' block
- -> ^(FOR identifierDeclaration conditionalExpression expression block?)
- ;
-
-whileLoop
- : 'while' '(' expression ')' block
- -> ^(WHILE expression block?)
- ;
-
-expression
- : additiveExpression ('='^ expression)?
- ;
-
-additiveExpression
- : multiplicativeExpression ( ('+' | '-')^ multiplicativeExpression )*
- ;
-
-multiplicativeExpression
- : conditionalExpression ( ( '*' | '/' | '%' )^ conditionalExpression )*
- ;
-
-conditionalExpression
- : (conditionalOrExpression | conditionalAndExpression)+
- ;
-
-conditionalOrExpression
- : conditionalAndExpression ('||'^ conditionalAndExpression)*
- ;
-
-conditionalAndExpression
- : finalConditionalExpression ('&&'^ finalConditionalExpression)*
- ;
-
-finalConditionalExpression
- : primary (('==' | '!=' | '>' | '<' | '>=' | '<=')^ primary)*
- ;
-
-primary
- : '('! expression ')'!
- | (VariableIdentifier|TypeIdentifier|literal) (arguments | ('.'^
(VariableIdentifier|TypeIdentifier) arguments?)*)
- ;
-
-arguments
- : '(' expressionList? ')'
- -> ^(ARGS expressionList?)
- ;
-
-expressionList
- : expression (','! expression)*
- ;
-
-parameterList
- : '('! parameters? ')'!
- ;
-
-parameters
- : parameter (',' parameter)*
- -> ^(PARAMS parameter*)
- ;
-
-parameter
- : modifiers? qualifiedType VariableIdentifier
- -> ^(PARAM modifiers? qualifiedType VariableIdentifier)
- ;
-
-literal
- : INT | StringLiteral | 'true' | 'false'
- ;
-
-/* Lexer rules */
-
-TypeIdentifier
- : 'A' .. 'Z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
- ;
-
-VariableIdentifier
- : 'a' .. 'z' ('a' .. 'z' | 'A' .. 'Z' | '0' .. '9')*
- ;
-
-StringLiteral
- : '"' ~('"'|'\\'|'\n'|'\r')* '"'
- | '"""' (options {greedy=false;}:.)* '"""'
- ;
-
-WS
- : (' '|'\r'|'\n'|'\t')+ {$channel = HIDDEN;}
- ;
-
-COMMENT
- : '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
- ;
-
-LINE_COMMENT
- : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
- ;
-
-INT
- : '-'? '0'..'9'+
- ;
=======================================
--- /core/src/main/antlr3/noop/grammar/antlr/NoopAST.g Fri Dec 18 09:39:36
2009
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2009 Google Inc.
-//
-// Licensed 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.
-
-tree grammar NoopAST;
-
-options {
- tokenVocab = Noop;
- ASTLabelType = CommonTree;
-}
-
-scope SourceFile {
- SourceFile file;
-}
-
-scope Block {
- Block block;
-}
-
-@header {
- package noop.grammar.antlr;
-
- import noop.model.*;
- import noop.model.proto.NoopAst;
- import noop.model.proto.NoopAst.*;
- import scala.Enumeration;
- import scala.collection.mutable.Buffer;
- import scala.collection.mutable.ArrayBuffer;
-}
-
-@members {
- Stack paraphrases = new Stack();
- public boolean hadErrors = false;
-
- @Override
- public String getErrorMessage(RecognitionException e, String[]
tokenNames) {
- hadErrors = true;
- String msg = super.getErrorMessage(e, tokenNames);
- if ( paraphrases.size()>0 ) {
- String paraphrase = (String)paraphrases.peek();
- msg = msg+" "+paraphrase;
- }
- return msg;
- }
-
- public String join(String delim, List strings) {
- if (strings.isEmpty()) {
- return "";
- }
- String first = ((CommonTree) strings.get(0)).getText();
- if (strings.size() == 1) {
- return first;
- }
- StringBuilder builder = new StringBuilder(first);
- for (int i=1; i<strings.size(); i++) {
- builder.append(delim);
- builder.append(((CommonTree)strings.get(i)).getText());
- }
- return builder.toString();
- }
-
- //TODO(alexeagle): when we have escape sequences, we need to do more
work here
- // Probably anything acceping raw strings should take a RawString type
which
- // knows how to propertly un-escape things.
- String stripQuotes(String withQuotes) {
- return (withQuotes.startsWith("\"\"\"") ?
- withQuotes.substring(3, withQuotes.length() - 3) :
- withQuotes.substring(1, withQuotes.length() - 1));
- }
-}
-
-file returns [SourceFile file = new SourceFile()]
- scope SourceFile;
- @init { $SourceFile::file = $file;
- paraphrases.push("at top-level in file"); }
- @after { paraphrases.pop(); }
- : namespaceDeclaration? importDeclaration* (classDefinition |
interfaceDefinition | bindingsDefinition | test)
- ;
-
-namespaceDeclaration
- : ^('namespace' name=namespace)
- { $SourceFile::file.namespace_\$eq($name.text); }
- ;
-
-importDeclaration
- : ^('import' name=qualifiedType)
- { $SourceFile::file.imports().\$plus\$eq($name.text); }
- ;
-
-namespace returns [String text]
- : v+=VariableIdentifier+
- { $text = join(".", $v); }
- ;
-
-qualifiedType returns [String text]
- : n=namespace? t=TypeIdentifier
- { $text = ($n.text == null) ? $t.text : $n.text + "." + $t.text; }
- ;
-
-classDefinition
-@init {
- paraphrases.push("in class definition");
- Buffer<Method> methodCollector = new ArrayBuffer<Method>();
- Buffer<Method> unittestCollector = new ArrayBuffer<Method>();
- Buffer<String> interfaceCollector = new ArrayBuffer<String>();
-}
-@after {
- paraphrases.pop();
-}
- : ^(CLASS m=modifiers? t=TypeIdentifier p=parameters?
- typeSpecifier[interfaceCollector]*
- classBlock[methodCollector, unittestCollector]?
- d=doc?)
- {
- ConcreteClassDefinition classDef = new ConcreteClassDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
- classDef.imports().\$plus\$plus\$eq($SourceFile::file.imports());
- classDef.methods().\$plus\$plus\$eq(methodCollector);
- classDef.unittests().\$plus\$plus\$eq(unittestCollector);
- classDef.interfaces().\$plus\$plus\$eq(interfaceCollector);
- if ($p.parameters != null) {
- classDef.parameters().\$plus\$plus\$eq($p.parameters);
- }
- if ($m.modifiers != null) {
- classDef.modifiers().\$plus\$plus\$eq($m.modifiers);
- }
- $SourceFile::file.classDef_\$eq(classDef);
- }
- ;
-
-interfaceDefinition
- : ^(INTERFACE m=modifiers? t=TypeIdentifier d=doc?)
- {
- InterfaceDefinition classDef = new InterfaceDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
- if ($m.modifiers != null) {
- classDef.modifiers().\$plus\$plus\$eq($m.modifiers);
- }
- $SourceFile::file.classDef_\$eq(classDef);
- }
- ;
-
-parameters returns [Buffer<Parameter> parameters = new
ArrayBuffer<Parameter>() ]
- : ^(PARAMS parameter[$parameters]*)
- ;
-
-parameter [Buffer<Parameter> parameters]
- : ^(PARAM modifiers? t=qualifiedType v=VariableIdentifier)
-
- { Parameter param = new Parameter($v.text, $t.text);
- $parameters.\$plus\$eq(param);
- }
- ;
-
-typeSpecifier [Buffer<String> interfaces]
- : ^(IMPL i=qualifiedType)
- {
- $interfaces.\$plus\$eq($i.text);
- }
- ;
-
-modifiers returns [Buffer<Enumeration.Value> modifiers ]
-@init { modifiers = new ArrayBuffer<Enumeration.Value>(); }
- : ^(MOD modifier[modifiers]+)
- ;
-
-modifier [Buffer<Enumeration.Value> mods]
- : m=('mutable' | 'delegate' | 'native')
- { mods.\$plus\$eq(Modifier.valueOf($m.text).get()); }
- ;
-
-test
-@init {
- Buffer<Method> unittestCollector = new ArrayBuffer<Method>();
-}
- : ^(TEST StringLiteral statement* test? unittest[unittestCollector]?)
- {}
- ;
-
-unittest [Buffer<Method> unittests]
- : ^(UNITTEST name=StringLiteral b=block)
- { Method method = new Method(stripQuotes($name.text), $b.block,
stripQuotes($name.text));
- $unittests.\$plus\$eq(method);
- method.returnTypes().\$plus\$eq("Void");
- }
- ;
-
-classBlock [Buffer<Method> methods, Buffer<Method> unittests]
- : (identifierDeclaration | methodDefinition[methods] |
unittest[unittests])+
- ;
-
-methodDefinition [Buffer<Method> methods]
-@init { paraphrases.push("in method definition"); }
-@after { paraphrases.pop(); }
- : ^(METHOD d=doc? m=modifiers? r=returnType name=VariableIdentifier
p=parameters? b=block)
- { Method method = new Method($name.text, $b.block, $d.doc);
- method.returnTypes().\$plus\$plus\$eq($r.types);
- if ($p.parameters != null) {
- method.parameters().\$plus\$plus\$eq($p.parameters);
- }
- if ($m.modifiers != null) {
- method.modifiers().\$plus\$plus\$eq($m.modifiers);
- }
- $methods.\$plus\$eq(method);
- }
- ;
-
-returnType returns [Buffer<String> types = new ArrayBuffer<String>() ]
- : ^(RETURN_TYPE type[$types]+)
- ;
-
-type [Buffer<String> types]
- : t=TypeIdentifier {
- $types.\$plus\$eq($t.text);
- }
- ;
-
-bindingsDefinition
- : ^(BINDING t=TypeIdentifier d=doc? b=bindings)
- {
- BindingDefinition classDef = new BindingDefinition($t.text,
$SourceFile::file.namespace(), $d.doc);
- classDef.bindings().\$plus\$plus\$eq($b.bindings);
- classDef.imports().\$plus\$plus\$eq($SourceFile::file.imports());
- $SourceFile::file.classDef_\$eq(classDef);
- }
- ;
-
-bindingsDeclaration returns [Buffer<BindingDeclaration> bindings]
- : ^(BINDING b=bindings)
- { $bindings = $b.bindings; }
- ;
-
-bindingsReference returns [String text]
- : ^(BINDING t=qualifiedType)
- { $text = $t.text; }
- ;
-
-bindings returns [Buffer<BindingDeclaration> bindings]
- @init{ $bindings = new ArrayBuffer<BindingDeclaration>(); }
- : binding[bindings]*
- ;
-
-binding[Buffer<BindingDeclaration> bindings]
- : ^(BIND t=qualifiedType exp=expression)
- { $bindings.\$plus\$eq(new BindingDeclaration($t.text, $exp.exp)); }
- ;
-
-block returns [Block block]
- scope Block;
- @init { $block = new Block();
- $Block::block = $block; }
- : (anonBind=bindingsDeclaration | namedBind=bindingsReference)?
statement*
- {
- if ($namedBind.text != null) {
- $block.namedBinding_\$eq(new scala.Some($namedBind.text));
- }
- if ($anonBind.bindings != null) {
- $block.anonymousBindings().\$plus\$plus\$eq($anonBind.bindings);
- }
- }
- ;
-
-statement
-@init { paraphrases.push("in statement"); }
-@after { paraphrases.pop(); }
- : returnStatement
- | w=whileStatement
- { $Block::block.statements().\$plus\$eq($w.exp); }
- | identifierDeclaration
- | should=shouldStatement
- { $Block::block.statements().\$plus\$eq($should.exp); }
- | exp=expression
- { $Block::block.statements().\$plus\$eq($exp.exp); }
- ;
-
-shouldStatement returns [Expression exp]
- : ^('should' left=expression right=expression)
- { $exp = new ShouldExpression($left.exp, $right.exp); }
- ;
-
-whileStatement returns [Expression exp]
- : ^(WHILE term=expression b=block)
- { $exp = new WhileLoop($term.exp, $b.block); }
- ;
-
-returnStatement
- : ^('return' ex=expression)
- { $Block::block.statements().\$plus\$eq(new ReturnExpression($ex.exp)); }
- ;
-
-identifierDeclaration
- : ^(VAR t=TypeIdentifier (^('=' v=VariableIdentifier exp=expression) |
v=VariableIdentifier))
- { IdentifierDeclarationExpression identifierDeclaration = new
IdentifierDeclarationExpression($t.text, $v.text);
- $Block::block.statements().\$plus\$eq(identifierDeclaration);
- if ($exp.exp != null) {
- identifierDeclaration.initialValue_\$eq(new scala.Some($exp.exp));
- }
- }
- ;
-
-assignment returns [Expression exp]
- : ^('=' lhs=expression rhs=expression)
- { $exp = new AssignmentExpression($lhs.exp, $rhs.exp); }
- ;
-
-expression returns [Expression exp]
- : l=literal
- { $exp = new ExpressionWrapper($l.exp); }
- | d=dereference
- { $exp = $d.exp; }
- | o=operatorExpression
- { $exp = $o.exp; }
- | ass=assignment
- { $exp = $ass.exp; }
- | c=conditionalExpression
- { $exp = $c.exp; }
- | right=(VariableIdentifier|TypeIdentifier) a=arguments?
- { if ($a.args != null) {
- Expression left = new IdentifierExpression("this");
- $exp = new MethodInvocationExpression(left, $right.text, $a.args);
- } else {
- $exp = new IdentifierExpression($right.text);
- }
- }
- ;
-
-conditionalExpression returns [Expression exp]
- : ^(cond=('||' | '&&') left=expression right=expression)
- {
- if ($cond.text.equals("||")) {
- $exp = new ConditionalOrExpression($left.exp, $right.exp);
- } else if ($cond.text.equals("&&")) {
- $exp = new ConditionalAndExpression($left.exp, $right.exp);
- }
- }
- ;
-
-operatorExpression returns [Expression exp]
- : ^(op=('+' | '-' | '*' | '/' | '%' | '==' | '!=' | '>' | '<' | '>='
| '<=') left=expression right=expression)
- { $exp = new OperatorExpression($left.exp, $op.text, $right.exp); }
- ;
-
-dereference returns [Expression exp]
- : ^('.' left=expression right=VariableIdentifier a=arguments?)
- {
- if ($a.args != null) {
- $exp = new MethodInvocationExpression($left.exp, $right.text,
$a.args);
- } else {
- $exp = new DereferenceExpression($left.exp, new
IdentifierExpression($right.text));
- }
- }
- ;
-
-arguments returns [Buffer<Expression> args]
-@init { $args = new ArrayBuffer<Expression>(); }
- : ^(ARGS argument[args]*)
- ;
-
-argument[Buffer<Expression> args]
- : exp=expression
- {
- $args.\$plus\$eq($exp.exp);
- }
- ;
-
-literal returns [Expr exp]
- : i=INT
- { $exp = Expr.newBuilder()
- .setType(Expr.Type.INT_LITERAL)
- .setIntLiteral(IntLiteral.newBuilder().setValue(Integer.valueOf($i.text)))
- .build(); }
- | s=StringLiteral
- { $exp = Expr.newBuilder()
- .setType(Expr.Type.STRING_LITERAL)
- .setStringLiteral(NoopAst.StringLiteral.newBuilder().setValue(stripQuotes($s.text)))
- .build(); }
- | b=('true' | 'false')
- { $exp = Expr.newBuilder()
- .setType(Expr.Type.BOOLEAN_LITERAL)
- .setBooleanLiteral(NoopAst.BooleanLiteral.newBuilder().setValue(Boolean.valueOf($b.text)))
- .build(); }
- ;
-
-doc returns [String doc]
- : ^(DOC s=StringLiteral)
- { $doc = stripQuotes($s.text); }
- ;
=======================================
--- /core/src/main/scala/noop/grammar/ParseException.scala Thu Oct 8
10:25:57 2009
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-/**
- * Thrown by our parser when ANTLR reports some errors while lexing or
parsing.
- *
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class ParseException(val message: String) extends RuntimeException(message)
=======================================
--- /core/src/main/scala/noop/grammar/Parser.scala Fri Nov 13 17:38:34 2009
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import java.io.InputStream;
-
-import org.antlr.runtime.{ANTLRInputStream, ANTLRStringStream,
CommonTokenStream};
-import org.antlr.runtime.tree.{CommonTree, CommonTreeNodeStream};
-
-import model.SourceFile;
-import grammar.antlr.{DocLexer, DocParser, NoopAST, NoopParser, NoopLexer};
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class Parser() {
-
- def buildParser(input: ANTLRStringStream): (NoopLexer, NoopParser) = {
- val lexer = new NoopLexer(input);
-
- return (lexer, new NoopParser(new CommonTokenStream(lexer)));
- }
-
- def buildDocParser(input: ANTLRStringStream): (DocLexer, DocParser) = {
- val lexer = new DocLexer(input);
-
- return (lexer, new DocParser(new CommonTokenStream(lexer)));
- }
-
- def parseFile(source: InputStream): CommonTree = {
- val (lexer, parser) = buildParser(new ANTLRInputStream(source));
-
- return parseFile(lexer, parser);
- }
-
- def parseFile(source: String): CommonTree = {
- val (lexer, parser) = buildParser(new ANTLRStringStream(source));
-
- return parseFile(lexer, parser);
- }
-
- def parseFile(lexer: NoopLexer, parser: NoopParser): CommonTree = {
- val file = parser.file();
-
- if (parser.hadErrors || lexer.hadErrors) {
- throw new ParseException("Source failed to parse");
- }
- return file.getTree().asInstanceOf[CommonTree];
- }
-
- def parseInterpretable(source: String): CommonTree = {
- val (lexer, parser) = buildParser(new ANTLRStringStream(source));
- val interpretable = parser.interpretable();
-
- if (parser.hadErrors || lexer.hadErrors) {
- throw new ParseException("Source failed to parse");
- }
- return interpretable.getTree().asInstanceOf[CommonTree];
- }
-
- def parseBlock(source: String): CommonTree = {
- val (lexer, parser) = buildParser(new ANTLRStringStream(source));
- val block = parser.block();
-
- if (parser.hadErrors || lexer.hadErrors) {
- throw new ParseException("Source failed to parse");
- }
- return block.getTree().asInstanceOf[CommonTree];
- }
-
- def parseDoc(source: String): CommonTree = {
- val (lexer, parser) = buildDocParser(new ANTLRStringStream(source));
- val doc = parser.doc();
-
- return doc.getTree().asInstanceOf[CommonTree];
- }
-
- def buildTreeParser(ast: CommonTree): NoopAST = {
- return new NoopAST(new CommonTreeNodeStream(ast));
- }
-
- def file(ast: CommonTree): SourceFile = {
- val treeParser = buildTreeParser(ast);
- val file = treeParser.file();
-
- if (treeParser.hadErrors) {
- throw new ParseException("Syntax errors");
- }
- return file;
- }
-
- def file(source: String): SourceFile = file(parseFile(source));
-
- def file(source: InputStream): SourceFile = file(parseFile(source));
-}
=======================================
--- /core/src/test/scala/noop/grammar/BindingSpec.scala Fri Dec 18 09:39:36
2009
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar
-
-
-import org.scalatest.matchers.ShouldMatchers
-import noop.model.{ExpressionWrapper, BindingDefinition,
StringLiteralExpression, IdentifierExpression}
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class BindingSpec extends Spec with ShouldMatchers {
- val parser = new Parser();
-
- describe("the binding keyword") {
-
- it("allows the binding operator in a binding") {
- val source = "binding Something { " +
- "BankService -> BankServiceImpl; " +
- "Port -> 9876; " +
- "Max -> firstThing;" +
- "}";
- parser.parseFile(source).toStringTree() should be(
- "(BINDING Something (BIND BankService BankServiceImpl) (BIND Port
9876) (BIND Max firstThing))");
- val file = parser.buildTreeParser(parser.parseFile(source)).file;
- val bindingDef = file.classDef.asInstanceOf[BindingDefinition];
- bindingDef.bindings should have length(3);
- bindingDef.bindings.first.noopType should be("BankService");
- bindingDef.bindings.first.boundTo.getClass() should
be(classOf[IdentifierExpression]);
-
bindingDef.bindings.first.boundTo.asInstanceOf[IdentifierExpression].identifier
should be ("BankServiceImpl");
- }
-
- it("can appear as an anonymous binding block") {
- val source = "class Foo() { Int thing() { binding(A -> B) {} } }";
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING (BIND A
B))))");
- val file = parser.buildTreeParser(parser.parseFile(source)).file;
- val method = file.classDef.methods.first;
- method.block.anonymousBindings should have length(1);
- method.block.namedBinding should be(None);
- val firstBinding = method.block.anonymousBindings.first;
- firstBinding.noopType should be("A");
- firstBinding.boundTo.getClass() should
be(classOf[IdentifierExpression]);
- firstBinding.boundTo.asInstanceOf[IdentifierExpression].identifier
should be ("B");
-
- }
-
- it("can appear as a named binding block") {
- val source = "class Foo() { Int thing() { binding MyBinding {} } }";
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING
MyBinding)))");
- val file = parser.buildTreeParser(parser.parseFile(source)).file;
- val method = file.classDef.methods.first;
- method.block.anonymousBindings should be('empty);
- method.block.namedBinding should be(Some("MyBinding"));
- }
-
- it("can not appear in a method declaration with a name") {
- val source = "class Foo() { Int thing() binding MyBinding {} }";
- intercept[ParseException] {
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING
MyBinding)))");
- }
- }
-
- it("can not appear anonymously in a method declaration") {
- val source = "class Foo() { Int thing() binding(This -> that) {} }";
- intercept[ParseException] {
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (METHOD (RETURN_TYPE Int) thing (BINDING (BIND This
that))))");
- }
- }
-
- it("can appear in a unittest declaration with a name") {
- val source = "class Foo() { unittest \"test this\" binding MyBinding
{} }";
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (UNITTEST \"test this\" (BINDING MyBinding)))");
- val file = parser.buildTreeParser(parser.parseFile(source)).file;
- val method = file.classDef.unittests.first;
- method.block.anonymousBindings should be('empty);
- method.block.namedBinding should be(Some("MyBinding"));
- }
-
- it("can appear anonymously in a unittest declaration") {
- val source = "class Foo() { unittest \"test this\" binding(String ->
\"foo\") {} }";
- parser.parseFile(source).toStringTree() should be(
- "(CLASS Foo (UNITTEST \"test this\" (BINDING (BIND String
\"foo\"))))");
- val file = parser.buildTreeParser(parser.parseFile(source)).file;
- val method = file.classDef.unittests.first;
- method.block.anonymousBindings should have length(1);
- val firstBinding = method.block.anonymousBindings.first;
- firstBinding.noopType should be("String");
- val typedExpression =
firstBinding.boundTo.asInstanceOf[ExpressionWrapper].getTypedExpression;
- typedExpression.asInstanceOf[StringLiteralExpression].value should
be ("foo");
- }
- }
-
- describe("the type alias") {
- it("should parse") {
- val source = "binding App { alias Int Port; }";
- parser.parseFile(source).toStringTree() should be(
- "(BINDING App (alias Int Port))");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/BlockSpec.scala Fri Dec 18 09:39:36
2009
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import collection.mutable.ArrayBuffer;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-import noop.model._;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class BlockSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("a block") {
-
- it("should allow a return statement") {
- val blockAst = parser.parseBlock("{ return 0; }");
-
- blockAst.toStringTree() should be("(return 0)");
- val block = parser.buildTreeParser(blockAst).block();
-
- block.statements.size should be(1);
- block.statements(0).getClass() should be(classOf[ReturnExpression]);
- val returnExpression =
block.statements(0).asInstanceOf[ReturnExpression];
-
- val typedExpression =
returnExpression.expr.asInstanceOf[ExpressionWrapper].getTypedExpression
- typedExpression.getClass should be(classOf[IntLiteralExpression]);
- typedExpression.asInstanceOf[IntLiteralExpression].value should
be(0);
- }
-
- it("should allow chained property access on properties") {
- val source = "{ b.c.d; }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be("(. (. b c) d)");
- val block = parser.buildTreeParser(blockAst).block();
-
- block.statements.size should be(1);
- block.statements(0).getClass() should
be(classOf[DereferenceExpression]);
- val deref1 = block.statements(0).asInstanceOf[DereferenceExpression];
- deref1.left.getClass() should be(classOf[DereferenceExpression]);
- deref1.right.getClass() should be(classOf[IdentifierExpression]);
- deref1.right.asInstanceOf[IdentifierExpression].identifier should
be("d");
-
- val deref2 = deref1.left.asInstanceOf[DereferenceExpression];
- deref2.left.getClass() should be(classOf[IdentifierExpression]);
- deref2.right.getClass() should be(classOf[IdentifierExpression]);
- deref2.left.asInstanceOf[IdentifierExpression].identifier should
be("b");
- deref2.right.asInstanceOf[IdentifierExpression].identifier should
be("c");
- }
-
- it("should allow a method call on implicit 'this'") {
- val source = "{ a(); }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be ("a ARGS");
- val block = parser.buildTreeParser(blockAst).block();
- block.statements.size should be(1);
- block.statements(0).getClass() should
be(classOf[MethodInvocationExpression]);
- val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
- methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
- methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("this");
- methodInvocation.name should be("a");
- methodInvocation.arguments should be ('empty);
- }
-
- it("should allow calling a method on an identifier") {
- val source = "{ a.b(); }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be("(. a b ARGS)");
- val block = parser.buildTreeParser(blockAst).block();
- block.statements.size should be(1);
-
- block.statements(0).getClass() should
be(classOf[MethodInvocationExpression]);
- val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
- methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
- methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("a");
- methodInvocation.name should be("b");
- methodInvocation.arguments should be(new ArrayBuffer[Expression]);
- methodInvocation.arguments.isEmpty should be (true);
- }
-
- it("should allow method chaining") {
- val source = "{ a.b().c(); }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be("(. (. a b ARGS) c ARGS)");
- val block = parser.buildTreeParser(blockAst).block();
- block.statements should have length (1);
-
- val method1 =
block.statements(0).asInstanceOf[MethodInvocationExpression];
- method1.left.getClass() should
be(classOf[MethodInvocationExpression]);
- val method2 = method1.left.asInstanceOf[MethodInvocationExpression];
-
- method2.left.getClass() should be(classOf[IdentifierExpression]);
- method2.left.asInstanceOf[IdentifierExpression].identifier should
be("a");
- method2.name should be("b");
- method2.arguments should be ('empty);
-
- method1.name should be("c");
- method1.arguments should be('empty);
- }
-
- it("should allow a method call on a property") {
- val source = "{ a.b.c(); }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be("(. (. a b) c ARGS)");
- val block = parser.buildTreeParser(blockAst).block();
- block.statements should have length (1);
-
- val method =
block.statements(0).asInstanceOf[MethodInvocationExpression];
- method.left.getClass() should be(classOf[DereferenceExpression]);
- val deref = method.left.asInstanceOf[DereferenceExpression];
-
- deref.left.getClass() should be(classOf[IdentifierExpression]);
- deref.left.asInstanceOf[IdentifierExpression].identifier should
be("a");
- deref.right.getClass() should be(classOf[IdentifierExpression]);
- deref.right.asInstanceOf[IdentifierExpression].identifier should
be("b");
-
- method.name should be("c");
- method.arguments should be('empty);
- }
-
- it("should allow a method call with arguments") {
- val source = "{ a.b(c, \"d\"); }";
- val blockAst = parser.parseBlock(source);
-
- blockAst.toStringTree() should be ("(. a b (ARGS c \"d\"))");
-
- val block = parser.buildTreeParser(blockAst).block();
- block.statements.size should be(1);
-
- val methodInvocation =
block.statements(0).asInstanceOf[MethodInvocationExpression];
- methodInvocation.left.getClass() should
be(classOf[IdentifierExpression]);
- methodInvocation.left.asInstanceOf[IdentifierExpression].identifier
should be("a");
- methodInvocation.name should be("b");
- methodInvocation.arguments should have length(2);
- methodInvocation.arguments(0).getClass() should
be(classOf[IdentifierExpression]);
-
methodInvocation.arguments(0).asInstanceOf[IdentifierExpression].identifier
should be("c");
- val typedExpression =
methodInvocation.arguments(1).asInstanceOf[ExpressionWrapper].getTypedExpression
- typedExpression.getClass() should
be(classOf[StringLiteralExpression]);
- typedExpression.asInstanceOf[StringLiteralExpression].value should
be ("d");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/ClassSpec.scala Thu Dec 3 21:44:41
2009
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers
-import noop.model.{ConcreteClassDefinition, Modifier};
-import org.scalatest.Spec;
-
-
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class ClassSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("parser") {
-
- it("should fail to parse a class with no parenthesis") {
- val source = "class Bar {}";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
-
- it("should parse a class with no parameters") {
- val source = "class Bar() {}";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar)");
- }
-
- it("should parse a class with one parameter") {
- val source = "class Bar(String a) {}";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar (PARAMS (PARAM
String a)))");
-
- val file = parser.file(source);
- file.classDef.name should be ("Bar");
- val concreteClass =
file.classDef.asInstanceOf[ConcreteClassDefinition];
- concreteClass.parameters(0).name should be ("a");
- concreteClass.parameters(0).noopType should be ("String");
- }
-
- it("should parse a class with a fully-qualified type in a parameter") {
- val source = "class Bar(noop.String a) {}";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar (PARAMS (PARAM
noop String a)))");
-
- val file = parser.file(source);
- val concreteClass =
file.classDef.asInstanceOf[ConcreteClassDefinition];
- concreteClass.parameters(0).noopType should be ("noop.String");
- }
-
- it("should parse a class with multiple parameters") {
- val source = "class Bar(A a, B b, C c) {}";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal (
- "(CLASS Bar (PARAMS (PARAM A a) (PARAM B b) (PARAM C c)))");
- }
-
- it("should allow modifiers on the parameters") {
- val source = "class Bar(mutable A a, delegate B b, mutable delegate
C c) {}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Bar (PARAMS (PARAM (MOD mutable) A a) (PARAM (MOD
delegate) B b) " +
- "(PARAM (MOD mutable delegate) C c)))");
- }
-
- it("should allow an implements clause with one interface") {
- val source = "class Foo() implements Bar {}";
-
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Foo (IMPL Bar))");
- }
-
- it("should allow an implements clause with several interfaces") {
- val source = "class Foo() implements A, a.b.C, d.E {}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Foo (IMPL A) (IMPL a b C) (IMPL d E))");
- val file = parser.file(source);
- file.classDef.name should be ("Foo");
- val concreteDef =
file.classDef.asInstanceOf[ConcreteClassDefinition];
- concreteDef.interfaces(0) should be("A");
- concreteDef.interfaces(1) should be ("a.b.C");
- concreteDef.interfaces(2) should be ("d.E");
- }
-
- it("should allow the native modifier on a class") {
- val source = "native class Foo() {}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS (MOD native) Foo)");
- val file = parser.file(source);
- file.classDef.modifiers should contain(Modifier.native);
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/CommentsSpec.scala Thu Oct 8
10:25:57 2009
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class CommentsSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("parser") {
-
- it("should be able to parse a single line comment") {
- val source = "// a comment\n class Foo() {}\n";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Foo)");
- }
-
- it("should be able to parse a multi-line comment") {
- val source = """
- /** hello
- bonjour
- */class Foo() {}
- """;
- var commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Foo)");
- }
-
- it("should be able to parse nested comments") {
- val source = """
- /** hello
- // bonjour
- *
- class Foo() {} */class Foo() {}
- """;
- var commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Foo)");
- }
-
- // Note: this makes Alex sad.
- it("should allow tab characters to appear in the source") {
- val source = "\tclass\tFoo() {\t}";
- parser.parseFile(source).toStringTree() should equal ("(CLASS Foo)");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/DocumentationSpec.scala Wed Nov 25
15:40:07 2009
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class DocumentationSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("documentation") {
-
- it("should appear before a class definition, in a string literal") {
- val source = "\"This class is awesome\" class Awesome() {}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Awesome (DOC \"This class is awesome\"))");
- val file = parser.file(source);
- file.classDef.documentation should equal("This class is awesome");
- }
-
- it("should appear before a method declaration") {
- val source = "class Foo() { \"Here is my great method\" Int doIt()
{}}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Foo (METHOD (DOC \"Here is my great method\")
(RETURN_TYPE Int) doIt))");
- val file = parser.file(source);
- file.classDef.methods(0).documentation should equal ("Here is my
great method");
- }
-
- it("can use the triple-quoted string literal and appear on an
interface") {
- val source = "\"\"\"\nMulti-line\ndocumentation\n\"\"\" interface
Bar {}";
- parser.parseFile(source).toStringTree() should equal (
- "(INTERFACE Bar (DOC
\"\"\"\nMulti-line\ndocumentation\n\"\"\"))");
- val file = parser.file(source);
- file.classDef.documentation should equal
("\nMulti-line\ndocumentation\n");
- }
-
- it("should appear before a bindings definition") {
- val source = "\"Stuff you need bound\" binding Stuff {}";
- parser.parseFile(source).toStringTree() should equal (
- "(BINDING Stuff (DOC \"Stuff you need bound\"))");
- val file = parser.file(source);
- file.classDef.documentation should equal("Stuff you need bound");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/ExpressionsSpec.scala Fri Dec 18
09:39:36 2009
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers
-import noop.model.{ExpressionWrapper, OperatorExpression,
IntLiteralExpression, IdentifierDeclarationExpression};
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class ExpressionsSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("the parser") {
-
- it("should parse a variable assignment") {
- val source = "{ Int a = 3; }";
- parser.parseBlock(source).toStringTree() should equal ("(VAR Int (=
a 3))");
- }
-
- it("should parse arithmetic") {
- val source = "{ Float a = 3 + 4 / (5 * (6 + 7)) % 8; }";
- parser.parseBlock(source).toStringTree() should equal (
- "(VAR Float (= a (+ 3 (% (/ 4 (* 5 (+ 6 7))) 8))))");
- val block =
parser.buildTreeParser(parser.parseBlock(source)).block();
- block.statements should have length(1);
- block.statements(0).getClass should
be(classOf[IdentifierDeclarationExpression]);
- val declaration =
block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
- declaration.initialValue should be ('defined);
- val expression1 =
declaration.initialValue.get().asInstanceOf[OperatorExpression];
- expression1.operator should be ("+");
- val typedExpression =
expression1.left.asInstanceOf[ExpressionWrapper].getTypedExpression
- typedExpression.asInstanceOf[IntLiteralExpression].value should be
(3);
- val expression2 = expression1.asInstanceOf[OperatorExpression].right;
- expression2.asInstanceOf[OperatorExpression].operator should be
("%");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/FileSpec.scala Thu Oct 8 10:25:57
2009
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class FileSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("parser") {
-
- it("should allow the word 'test' as a package name") {
- // TODO(alexeagle)
- }
-
- it("should parse namespace declaration") {
- val source = "namespace noop.demo; class Foo() {}";
- parser.parseFile(source).toStringTree() should equal (
- "(namespace noop demo) (CLASS Foo)");
- }
-
- it("should allow import in default namespace") {
- val source = "import Foo; class B(){}";
- parser.parseFile(source).toStringTree() should equal (
- "(import Foo) (CLASS B)");
- }
-
- it("should parse import statements") {
- val source = "import noop.demo.Test; class Foo() {}";
- parser.parseFile(source).toStringTree() should equal (
- "(import noop demo Test) (CLASS Foo)");
- }
-
- it("should not allow import without a type on the end") {
- val source = "import noop.demo;";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
-
- it("should parse a realistic looking file header") {
- val source = """
- namespace noop.grammar;
- // TODO: it should fail when a semicolon is missing, but the test
still passes
- import org.antlr.runtime.RecognitionException;
- import org.scalatest.Spec;
- import org.scalatest.matchers.ShouldMatchers;
-
- class FileSpec() {
- }
- """;
- parser.parseFile(source).toStringTree() should equal (
- "(namespace noop grammar) (import org antlr runtime
RecognitionException) " +
- "(import org scalatest Spec) (import org scalatest matchers
ShouldMatchers) " +
- "(CLASS FileSpec)");
- val file = parser.file(source);
- file.namespace should be ("noop.grammar");
- file.imports(0) should be ("org.antlr.runtime.RecognitionException");
- file.imports(1) should be ("org.scalatest.Spec");
- file.imports(2) should be ("org.scalatest.matchers.ShouldMatchers");
- }
-
- it ("should not allow extra stuff after the class definition") {
- val source = "class Foo() {} extra stuff";
- //intercept[ParseException] {
- // parser.parseFile(source);
- //}
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/IfSpec.scala Thu Oct 8 10:25:57 2009
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class IfSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("an if expression") {
-
- it("should parse correctly equality expression on two literals") {
- val source = "{ if (1 == 1) { } }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (== 1 1))");
- }
-
- it("should parse correctly an inequality expression on two literals") {
- val source = "{ if (1 != 2) { } }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (!= 1 2))");
- }
-
- it("should parse correctly an inequality expression followed by an
or'ed equality expression on literals") {
- val source = "{ if (1 != 2 || 1 == 1) { } }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (|| (!= 1 2) (== 1 1)))");
- }
-
- it("should parse correctly an inequality expression followed by an
and'ed equality expression on literals") {
- val source = "{ if (1 != 2 && 1 == 1) { } }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (&& (!= 1 2) (== 1 1)))");
- }
-
- it("should parse correctly complex conditional with or and and
primaries") {
- val source = "{ if (1 != a.getValue() && \"hello\" != \"wolrd\" ||
50 == myVar) { } }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (|| (&& (!= 1 (. a getValue
ARGS)) (!= \"hello\" \"wolrd\")) (== 50 myVar)))");
- }
-
- it("should parse correctly greater than conditional") {
- val source = "{ if (1 > 3) {} }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (> 1 3))");
- }
-
- it("should parse correctly lesser than conditional") {
- val source = "{ if (1 < 3) {} }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (< 1 3))");
- }
-
- it("should parse correctly greater than or equal conditional") {
- val source = "{ if (1 >= 3) {} }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (>= 1 3))");
- }
-
- it("should parse correctly lesser than or equal conditional") {
- val source = "{ if (1 <= 3) {} }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(IF (<= 1 3))");
- }
-
- it("should parse regular expression") {
- val source = "{ boolean b = false; if (b = true) {} }";
- val ifBlock = parser.parseBlock(source);
-
- ifBlock.toStringTree() should be("(= boolean b false) (IF (= b
true))");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/InterfaceSpec.scala Mon Oct 19
22:50:22 2009
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class InterfaceSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("interface") {
-
- it("should parse an interface with no methods") {
- val source = "interface MyInterface {}";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(INTERFACE MyInterface)");
- }
-
- it("should parse an interface with one method") {
- val source = "interface MyInterface { Int helloWorld(); }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(INTERFACE MyInterface
(METHOD (RETURN_TYPE Int) helloWorld))");
- }
-
- it("should not parse an interface with a method having a body") {
- val source = "interface MyInterface { Int helloWorld() { Int i = 0;
} }";
-
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/InterpretableSpec.scala Thu Oct 8
10:25:57 2009
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class InterpretableSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("the parser") {
-
- it("should parse an import as interpretable") {
- val source = "import noop.Foo;";
- parser.parseInterpretable(source).toStringTree() should equal (
- "(import noop Foo)");
- }
-
- it("should parse a class definition as interpretable") {
- val source = "class F() {}";
- parser.parseInterpretable(source).toStringTree() should equal (
- "(CLASS F)");
- }
-
- it("should parse a variable declaratian as interpretable") {
- val source = "Int a = 3;";
- parser.parseInterpretable(source).toStringTree() should equal (
- "(VAR Int (= a 3))");
- }
-
- it("should parse several statements at once") {
- val source = """Int a = 3; import foo.Foo; String b = "poop"; class
F() {}""";
- parser.parseInterpretable(source).toStringTree() should equal (
- """(VAR Int (= a 3)) (import foo Foo) (VAR String (= b "poop"))
(CLASS F)""");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/LiteralsSpec.scala Fri Dec 18
09:39:36 2009
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers
-import noop.model.{ExpressionWrapper, BooleanLiteralExpression,
IdentifierDeclarationExpression};
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class LiteralsSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("the parser") {
-
- it("should parse integer literals") {
- val source = "{ Int a = 123; Int b = -123; } ";
- parser.parseBlock(source).toStringTree() should equal (
- "(VAR Int (= a 123)) (VAR Int (= b -123))");
- }
-
- it("should parse a string literal") {
- val source = " { a = \"hello, world!\"; } ";
- parser.parseBlock(source).toStringTree() should equal (
- "(= a \"hello, world!\")");
- }
-
- it("should parse a multi-line string literal") {
- val source = "{ String a = \"\"\"Line1\n\"Line2\"\n\"\"\"; }";
- parser.parseBlock(source).toStringTree() should equal(
- "(VAR String (= a \"\"\"Line1\n\"Line2\"\n\"\"\"))");
- }
-
- it("should not allow a single-double-quoted string to span lines") {
- val source = """{ a = "Line 1
- "; }""";
- intercept[ParseException] (parser.parseBlock(source));
- }
-
- it("should parse boolean literals") {
- val source = "{ Boolean a = true; }";
- parser.parseBlock(source).toStringTree() should equal ("(VAR Boolean
(= a true))");
- val statement =
parser.buildTreeParser(parser.parseBlock(source)).block().statements(0)
- .asInstanceOf[IdentifierDeclarationExpression];
- statement.initialValue match {
- case Some(b) => {
-
b.asInstanceOf[ExpressionWrapper].getTypedExpression.asInstanceOf[BooleanLiteralExpression].value
should be (true);
- }
- case None => fail();
- }
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/LoopSpec.scala Fri Dec 18 09:39:36
2009
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers
-import noop.model.{ExpressionWrapper, BooleanLiteralExpression, WhileLoop};
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class LoopSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("a while loop") {
-
- it("should be formed with a while statement") {
- val source = "{ while(true) {} }";
- parser.parseBlock(source).toStringTree() should be ("(WHILE true)");
- val block =
parser.buildTreeParser(parser.parseBlock(source)).block();
- block.statements(0).getClass() should be (classOf[WhileLoop]);
- val whileLoop = block.statements(0).asInstanceOf[WhileLoop];
- val typedExpression =
whileLoop.continueCondition.asInstanceOf[ExpressionWrapper].getTypedExpression
- typedExpression.asInstanceOf[BooleanLiteralExpression].value should
be(true);
- }
- }
-
- describe("a for loop") {
-
- it("should be formed with a for-in statement") {
- val source = "{ for (Int i in 1.to(10)) {} }";
- parser.parseBlock(source).toStringTree() should be("(FOREACH (VAR
Int i) (. 1 to (ARGS 10)))");
- }
-
- it("should allow an existing identifier to be the loop variable") {
- val source = "{ Int i; for (i in 1.to(10)) {} }";
- parser.parseBlock(source).toStringTree() should be("(VAR Int i)
(FOREACH i (. 1 to (ARGS 10)))");
- }
-
- it("should allow a c-style loop with explicit initialization,
termination, and iteration expressions") {
- val source = "{ for (Int i = 1; i < 3; i = i + 1) {} }";
- parser.parseBlock(source).toStringTree() should be("(FOR (VAR Int (=
i 1)) (< i 3) (= i (+ i 1)))");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/MethodsSpec.scala Sat Oct 24 14:47:55
2009
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-import model.{IdentifierDeclarationExpression, Modifier};
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class MethodsSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("the parser") {
-
- it("should parse a method with no parameters") {
- val source = "class Bar() { String helloWorld() { Int i = 1; } }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
- "(VAR Int (= i 1))))");
- }
-
- it("should parse a method with parameters") {
- val source = "class Bar() { String helloWorld(String s, Int n) { Int
i = 1; } }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
- "(PARAMS (PARAM String s) (PARAM Int n)) (VAR Int (= i 1))))");
-
- val file = parser.file(source);
- file.classDef.methods.size should be (1);
- val firstMethod = file.classDef.methods(0)
- firstMethod.name should be ("helloWorld");
- firstMethod.returnTypes.size should be (1);
- firstMethod.returnTypes(0) should be ("String");
- firstMethod.parameters.size should be (2);
- firstMethod.parameters(0).name should be ("s");
- firstMethod.parameters(0).noopType should be ("String");
- firstMethod.parameters(1).name should be ("n");
- firstMethod.parameters(1).noopType should be ("Int");
- firstMethod.block.statements.size should be (1);
- firstMethod.block.statements(0).getClass() should be
(classOf[IdentifierDeclarationExpression]);
- val firstStatement =
firstMethod.block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
- firstStatement.noopType should be ("Int");
- firstStatement.name should be ("i");
- // firstStatement.initialValue should be (Some(new
IntLiteralExpression(1)));
- }
-
- it("should allow variable declaration without an initial value") {
- val source = "class Bar() { String helloWorld() { Int i; } }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal ("(CLASS Bar (METHOD
(RETURN_TYPE String) helloWorld " +
- "(VAR Int i)))");
-
- val file = parser.file(source);
- file.classDef.methods.size should be (1);
- val firstMethod = file.classDef.methods(0)
- val firstStatement =
firstMethod.block.statements(0).asInstanceOf[IdentifierDeclarationExpression];
-
- firstStatement.noopType should be ("Int");
- firstStatement.name should be ("i");
- firstStatement.initialValue should be (None);
- }
-
- it("should parse a method invocation on a parameter reference") {
- val source = """class HelloWorld() { Int hello() {
console.println("Hello, World!"); }}""";
- parser.parseFile(source).toStringTree() should equal(
- """(CLASS HelloWorld (METHOD (RETURN_TYPE Int) hello (. console
println (ARGS "Hello, World!"))))""");
- }
-
- it("should parse a method with a return statement") {
- val source = "class Foo() { Void do() { return 4; } }";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Foo (METHOD (RETURN_TYPE Void) do (return 4)))");
- }
-
- it("should allow the native modifier on a method") {
- val source = "class Foo() { native Void do() { Int i; }}";
- parser.parseFile(source).toStringTree() should equal (
- "(CLASS Foo (METHOD (MOD native) (RETURN_TYPE Void) do (VAR Int
i)))");
- val file = parser.file(source);
- file.classDef.methods(0).modifiers should contain(Modifier.native);
- }
-
- it("should parse a method with one return type (no parentheses)") {
- val source = "class Math() { Int calculate() {} }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal (
- "(CLASS Math (METHOD (RETURN_TYPE Int) calculate))");
-
- val file = parser.file(source);
- file.classDef.methods.size should be (1);
- val firstMethod = file.classDef.methods(0);
- firstMethod.name should be ("calculate");
- firstMethod.returnTypes.size should be (1);
- firstMethod.returnTypes(0) should be ("Int");
- firstMethod.parameters.size should be (0);
- firstMethod.block.statements.size should be (0);
- }
-
- it("should parse a method with one return type (parentheses)") {
- val source = "class Math() { (Int) calculate() {} }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal (
- "(CLASS Math (METHOD (RETURN_TYPE Int) calculate))");
-
- val file = parser.file(source);
- file.classDef.methods.size should be (1);
- val firstMethod = file.classDef.methods(0);
- firstMethod.name should be ("calculate");
- firstMethod.returnTypes.size should be (1);
- firstMethod.returnTypes(0) should be ("Int");
- firstMethod.parameters.size should be (0);
- firstMethod.block.statements.size should be (0);
- }
-
- it("should parse a method with multiple return types") {
- val source = "class Math() { (Int, Int) calculate() {} }";
- val commonTree = parser.parseFile(source);
-
- commonTree.toStringTree() should equal (
- "(CLASS Math (METHOD (RETURN_TYPE Int Int) calculate))");
-
- val file = parser.file(source);
- file.classDef.methods.size should be (1);
- val firstMethod = file.classDef.methods(0);
- firstMethod.name should be ("calculate");
- firstMethod.returnTypes.size should be (2);
- firstMethod.returnTypes(0) should be ("Int");
- firstMethod.returnTypes(1) should be ("Int");
- firstMethod.parameters.size should be (0);
- firstMethod.block.statements.size should be (0);
- }
-
- it ("should NOT parse a method with one named return parameter (no
parentheses)") {
- val source = "class Math() { Int a calculate() {} }";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
-
- it ("should NOT parse a method with one named return parameter
(parentheses)") {
- val source = "class Math() { (Int a) calculate() {} }";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
-
- it ("should NOT parse a method with a mixture of named and unnamed
return parameters") {
- val source = "class Math() { (Int, Int b, Int) calculate() {} }";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
-
- it ("should NOT parse a method with multiple named return parameters")
{
- val source = "class Math() { (Int a, Int b) calcualte() {} }";
- intercept[ParseException] {
- parser.parseFile(source);
- }
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/ParseExamplesTest.scala Tue Nov 17
20:37:51 2009
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar
-
-import org.scalatest.Spec
-import org.scalatest.matchers.ShouldMatchers
-import java.io.{FileInputStream, File}
-
-class ParseExamplesTest extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("the parser") {
- it("should parse all the .noop files found under the /examples
directory") {
- val examplesDir = new File(new
File(System.getProperty("user.dir")), "examples");
- parseAllFilesInDirectory(examplesDir);
- }
- }
-
- def parseAllFilesInDirectory(dir: File): Unit = {
- for (file: File <- dir.listFiles) {
- if (file.isDirectory) {
- parseAllFilesInDirectory(file);
- } else {
- if (file.getName.endsWith(".noop")) {
- try {
- parser.parseFile(new FileInputStream(file));
- } catch {
- case e: ParseException => fail("failed to parse " +
file.getAbsolutePath());
- }
- }
- }
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/ParserSpec.scala Mon Oct 19 22:50:22
2009
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class ParserSpec extends Spec with ShouldMatchers {
-
- describe("our parser") {
-
- it("should throw an exception if there's an error parsing the AST") {
- val source = "class MyClass() { Int foo() { Int result =
List.List(List()); } }";
- val parser = new Parser();
- parser.parseFile(source).toStringTree() should be (
- "(CLASS MyClass (METHOD (RETURN_TYPE Int) foo (VAR Int (= result
(. List List (ARGS List ARGS))))))");
- intercept[ParseException] {
- val classDef = parser.file(source);
- }
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/PropertiesSpec.scala Thu Oct 8
10:25:57 2009
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- * @author toc...@gmail.com (Jeremie Lenfant-Engelmann)
- */
-class PropertiesSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("parser") {
-
- it("should parse a single property declaration") {
- val source = """
- class Foo() {
- Int a = 4;
- Int i;
- }
- """;
-
- parser.parseFile(source).toStringTree() should equal ("(CLASS Foo
(VAR Int (= a 4)) (VAR Int i))");
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/TestSpec.scala Thu Oct 8 10:25:57
2009
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar;
-
-import org.scalatest.matchers.ShouldMatchers;
-import org.scalatest.Spec;
-
-import model.ShouldExpression;
-
-/**
- * @author alex...@google.com (Alex Eagle)
- */
-class TestSpec extends Spec with ShouldMatchers {
-
- val parser = new Parser();
-
- describe("test block declarations") {
-
- it("should allow a unittest block in a class") {
- val source = "class Foo() { unittest \"testing 123\" {} }";
- parser.parseFile(source).toStringTree() should equal(
- "(CLASS Foo (UNITTEST \"testing 123\"))");
- val classDef = parser.file(source).classDef;
- classDef.methods should have length(0);
- classDef.unittests should have length(1);
- classDef.unittests(0).name should be("testing 123");
- }
-
- it("should not allow a unittest block in a method") {
- val source = "class Foo() { Int do() { unittest \"testing 123\" {} }
}";
- intercept[ParseException] (
- parser.parseFile(source)
- );
- }
-
- it("should not allow a test block in a class") {
- val source = "class Foo() { test \"testing 123\" {} }";
- intercept[ParseException] (
- parser.parseFile(source)
- );
- }
-
- it("should allow a test block in a file") {
- val source = "test \"testing 123\" {}";
- parser.parseFile(source).toStringTree() should equal("(TEST
\"testing 123\")");
- }
-
- it("should allow a unittest block in a test block") {
- val source = "test \"testing 123\" { unittest \"it should work\" {}
}";
- parser.parseFile(source).toStringTree() should equal(
- "(TEST \"testing 123\" (UNITTEST \"it should work\"))");
- }
-
- it("should allow a test block in a test block") {
- val source = "test \"testing 123\" { test \"it should work\" {} }";
- parser.parseFile(source).toStringTree() should equal(
- "(TEST \"testing 123\" (TEST \"it should work\"))");
- }
-
- it("should not allow a unittest block in a unittest block") {
- val source = "unittest \"testing 123\" { unittest \"it should work\"
{} }";
- intercept[ParseException] (
- parser.parseFile(source)
- );
- }
- }
-
- describe("the testing DSL") {
-
- it("should have a 'should' operator") {
- val source = "{ 1 should equal(1); }";
- parser.parseBlock(source).toStringTree() should be("(should 1 equal
(ARGS 1))");
- val statement =
parser.buildTreeParser(parser.parseBlock(source)).block().statements(0);
- statement.getClass() should be(classOf[ShouldExpression]);
- }
- }
-}
=======================================
--- /core/src/test/scala/noop/grammar/TryCatchSpec.scala Tue Nov 17
20:37:51 2009
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright 2009 Google Inc.
- *
- * Licensed 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 noop.grammar
-
-import org.scalatest.matchers.ShouldMatchers
-import org.scalatest.Spec
-
-class TryCatchSpec extends Spec with ShouldMatchers {
- val parser = new Parser();
-
- describe("the parser") {
- it("should parse a try-catch block") {
- val source = "{ try { parseInt(\"1\"); } catch { println(\"oops\");
} }";
- parser.parseBlock(source).toStringTree() should equal (
- "(TRY parseInt (ARGS \"1\") CATCH println (ARGS \"oops\"))");
- }
-
- it("should parse a try-finally block") {
- val source = "{ try { parseInt(\"1\"); } finally { cleanup(); } }";
- parser.parseBlock(source).toStringTree() should equal (
- "(TRY parseInt (ARGS \"1\") FINALLY cleanup ARGS)");
- }
-
- it("should parse a try-catch-finally block") {
- val source = "{ try { parseInt(\"1\"); } catch { println(\"oops\");
} finally { cleanup(); } }";
- parser.parseBlock(source).toStringTree() should equal (
- "(TRY parseInt (ARGS \"1\") CATCH println (ARGS \"oops\")
FINALLY cleanup ARGS)");
- }
- }
-
-}
=======================================
--- /buildfile Fri Dec 18 09:39:36 2009
+++ /buildfile Mon Feb 1 12:11:10 2010
@@ -41,12 +41,17 @@
manifest["Implementation-Vendor"] = COPYRIGHT
define "core" do
+ compile.with [SLF4J, PROTO]
+ package :jar
+ end
+
+ define "grammar" do
antlr = antlr([_('src/main/antlr3/noop/grammar/antlr/Doc.g'), \
_('src/main/antlr3/noop/grammar/antlr/Noop.g'), \
_('src/main/antlr3/noop/grammar/antlr/NoopAST.g')],
:in_package=>'noop.grammar.antlr')
compile.from(antlr).
- with [ANTLR, SLF4J, PROTO]
+ with [project("core"), ANTLR, SLF4J, PROTO]
package :jar
end
@@ -64,7 +69,7 @@
# TODO - only want examples as a test resource
resources.from [_('src/main/noop'), project("examples")._('noop')]
package(:jar).with(:manifest=>{'Main-Class'
=> 'noop.interpreter.InterpreterMain'})
- compile.with [project("core"), ANTLR_RUNTIME, SLF4J, GUICE, PROTO]
+ compile.with [project("core"), project("grammar"), ANTLR_RUNTIME,
SLF4J, GUICE, PROTO]
package(:zip).
include(compile.dependencies, :path=>'lib').
include(_("target/#{id}-#{version}.jar"), :path=>'lib').
=======================================
--- /core/src/main/scala/noop/model/ExpressionWrapper.scala Fri Dec 18
09:39:36 2009
+++ /core/src/main/scala/noop/model/ExpressionWrapper.scala Mon Feb 1
12:11:10 2010
@@ -1,6 +1,5 @@
package noop.model
-import noop.model.proto.NoopAst
import proto.NoopAst.Expr;
import noop.model.proto.NoopAst.Expr.Type;