1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-19 13:54:23 +01:00

Moving to ant-based build system from Processing. Mac OS X seems to work (for the moment).

This commit is contained in:
David A. Mellis 2010-05-08 21:47:19 +00:00
parent 5d54fbf70b
commit c4760d8ae7
17 changed files with 2038 additions and 3958 deletions

52
app/build.xml Normal file
View File

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<project name="Arduino PDE" default="build">
<target name="clean" description="Clean the build directories">
<delete dir="bin" />
<delete file="pde.jar" />
</target>
<target name="compile" description="Compile sources">
<condition property="core-built">
<available file="../core/core.jar" />
</condition>
<fail unless="core-built" message="Please build the core library first and make sure it sits in ../core/core.jar" />
<mkdir dir="bin" />
<!-- ant seems to nuke ${java.home} for some reason, pointing at the JRE
subfolder instead of the actual JDK found at JAVA_HOME.
To avoid this, we grab the actual JAVA_HOME environment variable
and use that to specify the location of tools.jar. -->
<!-- if someone is better with ant please help clean this up -->
<property environment="env" />
<property name="java_home" value="${env.JAVA_HOME}" />
<condition property="linux"><os family="unix" /></condition>
<fail if="linux" unless="java_home"
message="The JAVA_HOME variable must be set to the location of a full JDK. For instance, on Ubuntu Linux, this might be /usr/lib/jvm/java-6-sun." />
<condition property="windows"><os family="windows" /></condition>
<fail if="windows" unless="java_home"
message="The JAVA_HOME variable must be set to the location of a full JDK. For instance, on Windows, this might be c:\jdk1.6.0_18." />
<!--
<dirname property="blah" file="${java.home}" />
<echo message="here! ${java.home}/lib/tools.jar or there: ${blah}" />
<echo message="override ${env.JAVA_HOME}/lib/tools.jar" />
<fail />
-->
<javac target="1.5"
srcdir="src"
destdir="bin"
excludes="**/tools/format/**"
encoding="UTF-8"
includeAntRuntime="false"
classpath="../core/core.jar; ${env.JAVA_HOME}/lib/tools.jar; lib/ant.jar; lib/ant-launcher.jar; lib/apple.jar; lib/ecj.jar; lib/jna.jar; lib/oro.jar; lib/RXTXcomm.jar" />
</target>
<target name="build" depends="compile" description="Build PDE">
<jar basedir="bin" destfile="pde.jar" />
</target>
</project>

View File

@ -1,132 +0,0 @@
package antlr;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.jGuru.com
* Software rights: http://www.antlr.org/RIGHTS.html
*
* $Id: ExtendedCommonASTWithHiddenTokens.java 3419 2007-07-16 14:02:05Z fry $
*/
import java.io.*;
//import antlr.*;
import antlr.collections.*;
//import antlr.collections.impl.*;
/** A CommonAST whose initialization copies hidden token
* information from the Token used to create a node.
*/
public class ExtendedCommonASTWithHiddenTokens
extends CommonASTWithHiddenTokens {
public ExtendedCommonASTWithHiddenTokens() {
super();
}
public ExtendedCommonASTWithHiddenTokens(Token tok) {
super(tok);
}
public void initialize(AST ast) {
ExtendedCommonASTWithHiddenTokens a =
(ExtendedCommonASTWithHiddenTokens)ast;
super.initialize(a);
hiddenBefore = a.getHiddenBefore();
hiddenAfter = a.getHiddenAfter();
}
public String getHiddenAfterString() {
CommonHiddenStreamToken t;
StringBuffer hiddenAfterString = new StringBuffer(100);
for ( t = hiddenAfter ; t != null ; t = t.getHiddenAfter() ) {
hiddenAfterString.append(t.getText());
}
return hiddenAfterString.toString();
}
public String getHiddenBeforeString() {
antlr.CommonHiddenStreamToken
child = null,
parent = hiddenBefore;
// if there aren't any hidden tokens here, quietly return
//
if (parent == null) {
return "";
}
// traverse back to the head of the list of tokens before this node
do {
child = parent;
parent = child.getHiddenBefore();
} while (parent != null);
// dump that list
StringBuffer hiddenBeforeString = new StringBuffer(100);
for ( CommonHiddenStreamToken t = child; t != null ;
t = t.getHiddenAfter() ) {
hiddenBeforeString.append(t.getText());
}
return hiddenBeforeString.toString();
}
public void xmlSerializeNode(Writer out)
throws IOException {
StringBuffer buf = new StringBuffer(100);
buf.append("<");
buf.append(getClass().getName() + " ");
buf.append("hiddenBeforeString=\"" +
encode(getHiddenBeforeString()) +
"\" text=\"" + encode(getText()) + "\" type=\"" +
getType() + "\" hiddenAfterString=\"" +
encode(getHiddenAfterString()) + "\"/>");
out.write(buf.toString());
}
public void xmlSerializeRootOpen(Writer out)
throws IOException {
StringBuffer buf = new StringBuffer(100);
buf.append("<");
buf.append(getClass().getName() + " ");
buf.append("hiddenBeforeString=\"" +
encode(getHiddenBeforeString()) +
"\" text=\"" + encode(getText()) + "\" type=\"" +
getType() + "\" hiddenAfterString=\"" +
encode(getHiddenAfterString()) + "\">\n");
out.write(buf.toString());
}
public void xmlSerializeRootClose(Writer out)
throws IOException {
out.write("</" + getClass().getName() + ">\n");
}
public void xmlSerialize(Writer out) throws IOException {
// print out this node and all siblings
for (AST node = this;
node != null;
node = node.getNextSibling()) {
if (node.getFirstChild() == null) {
// print guts (class name, attributes)
((BaseAST)node).xmlSerializeNode(out);
}
else {
((BaseAST)node).xmlSerializeRootOpen(out);
// print children
((BaseAST)node.getFirstChild()).xmlSerialize(out);
// print end tag
((BaseAST)node).xmlSerializeRootClose(out);
}
}
}
}

View File

@ -1,221 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
package antlr;
//package processing.app.preproc;
//import antlr.*;
import antlr.collections.impl.BitSet;
/**
* This class provides TokenStreamHiddenTokenFilters with the concept of
* tokens which can be copied so that they are seen by both the hidden token
* stream as well as the parser itself. This is useful when one wants to use
* an existing parser (like the Java parser included with ANTLR) that throws
* away some tokens to create a parse tree which can be used to spit out
* a copy of the code with only minor modifications.
*
* This code is partially derived from the public domain ANLTR TokenStream
*/
public class TokenStreamCopyingHiddenTokenFilter
extends TokenStreamHiddenTokenFilter
implements TokenStream {
protected BitSet copyMask;
CommonHiddenStreamToken hiddenCopy = null;
public TokenStreamCopyingHiddenTokenFilter(TokenStream input) {
super(input);
copyMask = new BitSet();
}
/**
* Indicate that all tokens of type tokenType should be copied. The copy
* is put in the stream of hidden tokens, and the original is returned in the
* stream of normal tokens.
*
* @param tokenType integer representing the token type to copied
*/
public void copy(int tokenType) {
copyMask.add(tokenType);
}
/**
* Create a clone of the important parts of the given token. Note that this
* does NOT copy the hiddenBefore and hiddenAfter fields.
*
* @param t token to partially clone
* @return newly created partial clone
*/
public CommonHiddenStreamToken partialCloneToken(CommonHiddenStreamToken t) {
CommonHiddenStreamToken u = new CommonHiddenStreamToken(t.getType(),
t.getText());
u.setColumn(t.getColumn());
u.setLine(t.getLine());
u.setFilename(t.getFilename());
return u;
}
public void linkAndCopyToken(CommonHiddenStreamToken prev,
CommonHiddenStreamToken monitored) {
// create a copy of the token in the lookahead for use as hidden token
hiddenCopy = partialCloneToken(LA(1));
// attach copy to the previous token, whether hidden or monitored
prev.setHiddenAfter(hiddenCopy);
// if previous token was hidden, set the hiddenBefore pointer of the
// copy to point back to it
if (prev != monitored) {
hiddenCopy.setHiddenBefore(prev);
}
// we don't want the non-hidden copy to link back to the hidden
// copy on the next pass through this function, so we leave
// lastHiddenToken alone
//System.err.println("hidden copy: " + hiddenCopy.toString());
return;
}
private void consumeFirst() throws TokenStreamException {
consume(); // get first token of input stream
// Handle situation where hidden or discarded tokens
// appear first in input stream
CommonHiddenStreamToken p=null;
// while hidden, copied, or discarded scarf tokens
while ( hideMask.member(LA(1).getType()) ||
discardMask.member(LA(1).getType()) ||
copyMask.member(LA(1).getType()) ) {
// if we've hit one of the tokens that needs to be copied, we copy it
// and then break out of the loop, because the parser needs to see it
// too
//
if (copyMask.member(LA(1).getType())) {
// copy the token in the lookahead
hiddenCopy = partialCloneToken(LA(1));
// if there's an existing token before this, link that and the
// copy together
if (p != null) {
p.setHiddenAfter(hiddenCopy);
hiddenCopy.setHiddenBefore(p); // double-link
}
lastHiddenToken = hiddenCopy;
if (firstHidden == null) {
firstHidden = hiddenCopy;
}
// we don't want to consume this token, because it also needs to
// be passed through to the parser, so break out of the while look
// entirely
//
break;
} else if (hideMask.member(LA(1).getType())) {
if (p != null) {
p.setHiddenAfter(LA(1));
LA(1).setHiddenBefore(p); // double-link
}
p = LA(1);
lastHiddenToken = p;
if (firstHidden == null) {
firstHidden = p; // record hidden token if first
}
}
consume();
}
}
/** Return the next monitored token.
* Test the token following the monitored token.
* If following is another monitored token, save it
* for the next invocation of nextToken (like a single
* lookahead token) and return it then.
* If following is unmonitored, nondiscarded (hidden)
* channel token, add it to the monitored token.
*
* Note: EOF must be a monitored Token.
*/
public Token nextToken() throws TokenStreamException {
// handle an initial condition; don't want to get lookahead
// token of this splitter until first call to nextToken
if (LA(1) == null) {
consumeFirst();
}
//System.err.println();
// we always consume hidden tokens after monitored, thus,
// upon entry LA(1) is a monitored token.
CommonHiddenStreamToken monitored = LA(1);
// point to hidden tokens found during last invocation
monitored.setHiddenBefore(lastHiddenToken);
lastHiddenToken = null;
// Look for hidden tokens, hook them into list emanating
// from the monitored tokens.
consume();
CommonHiddenStreamToken prev = monitored;
// deal with as many not-purely-monitored tokens as possible
while ( hideMask.member(LA(1).getType()) ||
discardMask.member(LA(1).getType()) ||
copyMask.member(LA(1).getType()) ) {
if (copyMask.member(LA(1).getType())) {
// copy the token and link it backwards
if (hiddenCopy != null) {
linkAndCopyToken(hiddenCopy, monitored);
} else {
linkAndCopyToken(prev, monitored);
}
// we now need to parse it as a monitored token, so we return, which
// avoids the consume() call at the end of this loop. the next call
// will parse it as a monitored token.
//System.err.println("returned: " + monitored.toString());
return monitored;
} else if (hideMask.member(LA(1).getType())) {
// attach the hidden token to the monitored in a chain
// link forwards
prev.setHiddenAfter(LA(1));
// link backwards
if (prev != monitored) { //hidden cannot point to monitored tokens
LA(1).setHiddenBefore(prev);
} else if (hiddenCopy != null) {
hiddenCopy.setHiddenAfter(LA(1));
LA(1).setHiddenBefore(hiddenCopy);
hiddenCopy = null;
}
//System.err.println("hidden: " + prev.getHiddenAfter().toString() + "\" after: " + prev.toString());
prev = lastHiddenToken = LA(1);
}
consume();
}
// remember the last hidden token for next time around
if (hiddenCopy != null) {
lastHiddenToken = hiddenCopy;
hiddenCopy = null;
}
//System.err.println("returned: " + monitored.toString());
return monitored;
}
}

View File

@ -1,1277 +0,0 @@
header {
package antlr.java;
}
/** Java 1.3 Recognizer
* <PRE>
* Run 'java Main [-showtree] directory-full-of-java-files'
*
* [The -showtree option pops up a Swing frame that shows
* the AST constructed from the parser.]
*
* Run 'java Main <directory full of java files>'
*
* Contributing authors:
* John Mitchell johnm@non.net
* Terence Parr parrt@magelang.com
* John Lilley jlilley@empathy.com
* Scott Stanchfield thetick@magelang.com
* Markus Mohnen mohnen@informatik.rwth-aachen.de
* Peter Williams pete.williams@sun.com
* Allan Jacobs Allan.Jacobs@eng.sun.com
* Steve Messick messick@redhills.com
* John Pybus john@pybus.org
*
* Version 1.00 December 9, 1997 -- initial release
* Version 1.01 December 10, 1997
* fixed bug in octal def (0..7 not 0..8)
* Version 1.10 August 1998 (parrt)
* added tree construction
* fixed definition of WS,comments for mac,pc,unix newlines
* added unary plus
* Version 1.11 (Nov 20, 1998)
* Added "shutup" option to turn off last ambig warning.
* Fixed inner class def to allow named class defs as statements
* synchronized requires compound not simple statement
* add [] after builtInType DOT class in primaryExpression
* "const" is reserved but not valid..removed from modifiers
* Version 1.12 (Feb 2, 1999)
* Changed LITERAL_xxx to xxx in tree grammar.
* Updated java.g to use tokens {...} now for 2.6.0 (new feature).
*
* Version 1.13 (Apr 23, 1999)
* Didn't have (stat)? for else clause in tree parser.
* Didn't gen ASTs for interface extends. Updated tree parser too.
* Updated to 2.6.0.
* Version 1.14 (Jun 20, 1999)
* Allowed final/abstract on local classes.
* Removed local interfaces from methods
* Put instanceof precedence where it belongs...in relationalExpr
* It also had expr not type as arg; fixed it.
* Missing ! on SEMI in classBlock
* fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
* fixed: didn't like Object[].class in parser or tree parser
* Version 1.15 (Jun 26, 1999)
* Screwed up rule with instanceof in it. :( Fixed.
* Tree parser didn't like (expr).something; fixed.
* Allowed multiple inheritance in tree grammar. oops.
* Version 1.16 (August 22, 1999)
* Extending an interface built a wacky tree: had extra EXTENDS.
* Tree grammar didn't allow multiple superinterfaces.
* Tree grammar didn't allow empty var initializer: {}
* Version 1.17 (October 12, 1999)
* ESC lexer rule allowed 399 max not 377 max.
* java.tree.g didn't handle the expression of synchronized
* statements.
* Version 1.18 (August 12, 2001)
* Terence updated to Java 2 Version 1.3 by
* observing/combining work of Allan Jacobs and Steve
* Messick. Handles 1.3 src. Summary:
* o primary didn't include boolean.class kind of thing
* o constructor calls parsed explicitly now:
* see explicitConstructorInvocation
* o add strictfp modifier
* o missing objBlock after new expression in tree grammar
* o merged local class definition alternatives, moved after declaration
* o fixed problem with ClassName.super.field
* o reordered some alternatives to make things more efficient
* o long and double constants were not differentiated from int/float
* o whitespace rule was inefficient: matched only one char
* o add an examples directory with some nasty 1.3 cases
* o made Main.java use buffered IO and a Reader for Unicode support
* o supports UNICODE?
* Using Unicode charVocabulay makes code file big, but only
* in the bitsets at the end. I need to make ANTLR generate
* unicode bitsets more efficiently.
* Version 1.19 (April 25, 2002)
* Terence added in nice fixes by John Pybus concerning floating
* constants and problems with super() calls. John did a nice
* reorg of the primary/postfix expression stuff to read better
* and makes f.g.super() parse properly (it was METHOD_CALL not
* a SUPER_CTOR_CALL). Also:
*
* o "finally" clause was a root...made it a child of "try"
* o Added stuff for asserts too for Java 1.4, but *commented out*
* as it is not backward compatible.
*
* Version 1.20 (October 27, 2002)
*
* Terence ended up reorging John Pybus' stuff to
* remove some nondeterminisms and some syntactic predicates.
* Note that the grammar is stricter now; e.g., this(...) must
* be the first statement.
*
* Trinary ?: operator wasn't working as array name:
* (isBig ? bigDigits : digits)[i];
*
* Checked parser/tree parser on source for
* Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
* and the 110k-line jGuru server source.
*
* This grammar is in the PUBLIC DOMAIN
* </PRE>
*/
class JavaRecognizer extends Parser;
options {
k = 2; // two token lookahead
exportVocab=Java; // Call its vocabulary "Java"
codeGenMakeSwitchThreshold = 2; // Some optimizations
codeGenBitsetTestThreshold = 3;
defaultErrorHandler = false; // Don't generate parser error handlers
buildAST = true;
}
tokens {
BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL;
}
// Compilation Unit: In Java, this is a single file. This is the start
// rule for this parser
compilationUnit
: // A compilation unit starts with an optional package definition
( packageDefinition
| /* nothing */
)
// Next we have a series of zero or more import statements
( importDefinition )*
// Wrapping things up with any number of class or interface
// definitions
( typeDefinition )*
EOF!
;
// Package statement: "package" followed by an identifier.
packageDefinition
options {defaultErrorHandler = true;} // let ANTLR handle errors
: p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI!
;
// Import statement: import followed by a package or class name
importDefinition
options {defaultErrorHandler = true;}
: i:"import"^ {#i.setType(IMPORT);} identifierStar SEMI!
;
// A type definition in a file is either a class or interface definition.
typeDefinition
options {defaultErrorHandler = true;}
: m:modifiers!
( classDefinition[#m]
| interfaceDefinition[#m]
)
| SEMI!
;
/** A declaration is the creation of a reference or primitive-type variable
* Create a separate Type/Var tree for each var in the var list.
*/
declaration!
: m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
{#declaration = #v;}
;
// A type specification is a type name with possible brackets afterwards
// (which would make it an array type).
typeSpec[boolean addImagNode]
: classTypeSpec[addImagNode]
| builtInTypeSpec[addImagNode]
;
// A class type specification is a class type with possible brackets afterwards
// (which would make it an array type).
classTypeSpec[boolean addImagNode]
: identifier (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
{
if ( addImagNode ) {
#classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
}
}
;
// A builtin type specification is a builtin type with possible brackets
// afterwards (which would make it an array type).
builtInTypeSpec[boolean addImagNode]
: builtInType (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
{
if ( addImagNode ) {
#builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
}
}
;
// A type name. which is either a (possibly qualified) class name or
// a primitive (builtin) type
type
: identifier
| builtInType
;
// The primitive types.
builtInType
: "void"
| "boolean"
| "byte"
| "char"
| "short"
| "int"
| "float"
| "long"
| "double"
;
// A (possibly-qualified) java identifier. We start with the first IDENT
// and expand its name by adding dots and following IDENTS
identifier
: IDENT ( DOT^ IDENT )*
;
identifierStar
: IDENT
( DOT^ IDENT )*
( DOT^ STAR )?
;
// A list of zero or more modifiers. We could have used (modifier)* in
// place of a call to modifiers, but I thought it was a good idea to keep
// this rule separate so they can easily be collected in a Vector if
// someone so desires
modifiers
: ( modifier )*
{#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
;
// modifiers for Java classes, interfaces, class/instance vars and methods
modifier
: "private"
| "public"
| "protected"
| "static"
| "transient"
| "final"
| "abstract"
| "native"
| "threadsafe"
| "synchronized"
// | "const" // reserved word, but not valid
| "volatile"
| "strictfp"
;
// Definition of a Java class
classDefinition![AST modifiers]
: "class" IDENT
// it _might_ have a superclass...
sc:superClassClause
// it might implement some interfaces...
ic:implementsClause
// now parse the body of the class
cb:classBlock
{#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
modifiers,IDENT,sc,ic,cb);}
;
superClassClause!
: ( "extends" id:identifier )?
{#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);}
;
// Definition of a Java Interface
interfaceDefinition![AST modifiers]
: "interface" IDENT
// it might extend some other interfaces
ie:interfaceExtends
// now parse the body of the interface (looks like a class...)
cb:classBlock
{#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
modifiers,IDENT,ie,cb);}
;
// This is the body of a class. You can have fields and extra semicolons,
// That's about it (until you see what a field is...)
classBlock
: LCURLY!
( field | SEMI! )*
RCURLY!
{#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
;
// An interface can extend several other interfaces...
interfaceExtends
: (
e:"extends"!
identifier ( COMMA! identifier )*
)?
{#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
#interfaceExtends);}
;
// A class can implement several interfaces...
implementsClause
: (
i:"implements"! identifier ( COMMA! identifier )*
)?
{#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
#implementsClause);}
;
// Now the various things that can be defined inside a class or interface...
// Note that not all of these are really valid in an interface (constructors,
// for example), and if this grammar were used for a compiler there would
// need to be some semantic checks to make sure we're doing the right thing...
field!
: // method, constructor, or variable declaration
mods:modifiers
( h:ctorHead s:constructorBody // constructor
{#field = #(#[CTOR_DEF,"CTOR_DEF"], mods, h, s);}
| cd:classDefinition[#mods] // inner class
{#field = #cd;}
| id:interfaceDefinition[#mods] // inner interface
{#field = #id;}
| t:typeSpec[false] // method or variable declaration(s)
( IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN! param:parameterDeclarationList RPAREN!
rt:declaratorBrackets[#t]
// get the list of exceptions that this method is
// declared to throw
(tc:throwsClause)?
( s2:compoundStatement | SEMI )
{#field = #(#[METHOD_DEF,"METHOD_DEF"],
mods,
#(#[TYPE,"TYPE"],rt),
IDENT,
param,
tc,
s2);}
| v:variableDefinitions[#mods,#t] SEMI
// {#field = #(#[VARIABLE_DEF,"VARIABLE_DEF"], v);}
{#field = #v;}
)
)
// "static { ... }" class initializer
| "static" s3:compoundStatement
{#field = #(#[STATIC_INIT,"STATIC_INIT"], s3);}
// "{ ... }" instance initializer
| s4:compoundStatement
{#field = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);}
;
constructorBody
: lc:LCURLY^ {#lc.setType(SLIST);}
( options { greedy=true; } : explicitConstructorInvocation)?
(statement)*
RCURLY!
;
/** Catch obvious constructor calls, but not the expr.super(...) calls */
explicitConstructorInvocation
: "this"! lp1:LPAREN^ argList RPAREN! SEMI!
{#lp1.setType(CTOR_CALL);}
| "super"! lp2:LPAREN^ argList RPAREN! SEMI!
{#lp2.setType(SUPER_CTOR_CALL);}
;
variableDefinitions[AST mods, AST t]
: variableDeclarator[getASTFactory().dupTree(mods),
getASTFactory().dupTree(t)]
( COMMA!
variableDeclarator[getASTFactory().dupTree(mods),
getASTFactory().dupTree(t)]
)*
;
/** Declaration of a variable. This can be a class/instance variable,
* or a local variable in a method
* It can also include possible initialization.
*/
variableDeclarator![AST mods, AST t]
: id:IDENT d:declaratorBrackets[t] v:varInitializer
{#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);}
;
declaratorBrackets[AST typ]
: {#declaratorBrackets=typ;}
(lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
;
varInitializer
: ( ASSIGN^ initializer )?
;
// This is an initializer used to set up an array.
arrayInitializer
: lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
( initializer
(
// CONFLICT: does a COMMA after an initializer start a new
// initializer or start the option ',' at end?
// ANTLR generates proper code by matching
// the comma as soon as possible.
options {
warnWhenFollowAmbig = false;
}
:
COMMA! initializer
)*
(COMMA!)?
)?
RCURLY!
;
// The two "things" that can initialize an array element are an expression
// and another (nested) array initializer.
initializer
: expression
| arrayInitializer
;
// This is the header of a method. It includes the name and parameters
// for the method.
// This also watches for a list of exception classes in a "throws" clause.
ctorHead
: IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN! parameterDeclarationList RPAREN!
// get the list of exceptions that this method is declared to throw
(throwsClause)?
;
// This is a list of exception classes that the method is declared to throw
throwsClause
: "throws"^ identifier ( COMMA! identifier )*
;
// A list of formal parameters
parameterDeclarationList
: ( parameterDeclaration ( COMMA! parameterDeclaration )* )?
{#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
#parameterDeclarationList);}
;
// A formal parameter.
parameterDeclaration!
: pm:parameterModifier t:typeSpec[false] id:IDENT
pd:declaratorBrackets[#t]
{#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
pm, #([TYPE,"TYPE"],pd), id);}
;
parameterModifier
: (f:"final")?
{#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], f);}
;
// Compound statement. This is used in many contexts:
// Inside a class definition prefixed with "static":
// it is a class initializer
// Inside a class definition without "static":
// it is an instance initializer
// As the body of a method
// As a completely indepdent braced block of code inside a method
// it starts a new scope for variable definitions
compoundStatement
: lc:LCURLY^ {#lc.setType(SLIST);}
// include the (possibly-empty) list of statements
(statement)*
RCURLY!
;
statement
// A list of statements in curly braces -- start a new scope!
: compoundStatement
// declarations are ambiguous with "ID DOT" relative to expression
// statements. Must backtrack to be sure. Could use a semantic
// predicate to test symbol table to see what the type was coming
// up, but that's pretty hard without a symbol table ;)
| (declaration)=> declaration SEMI!
// An expression statement. This could be a method call,
// assignment statement, or any other expression evaluated for
// side-effects.
| expression SEMI!
// class definition
| m:modifiers! classDefinition[#m]
// Attach a label to the front of a statement
| IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
// If-else statement
| "if"^ LPAREN! expression RPAREN! statement
(
// CONFLICT: the old "dangling-else" problem...
// ANTLR generates proper code matching
// as soon as possible. Hush warning.
options {
warnWhenFollowAmbig = false;
}
:
"else"! statement
)?
// For statement
| "for"^
LPAREN!
forInit SEMI! // initializer
forCond SEMI! // condition test
forIter // updater
RPAREN!
statement // statement to loop over
// While statement
| "while"^ LPAREN! expression RPAREN! statement
// do-while statement
| "do"^ statement "while"! LPAREN! expression RPAREN! SEMI!
// get out of a loop (or switch)
| "break"^ (IDENT)? SEMI!
// do next iteration of a loop
| "continue"^ (IDENT)? SEMI!
// Return an expression
| "return"^ (expression)? SEMI!
// switch/case statement
| "switch"^ LPAREN! expression RPAREN! LCURLY!
( casesGroup )*
RCURLY!
// exception try-catch block
| tryBlock
// throw an exception
| "throw"^ expression SEMI!
// synchronize a statement
| "synchronized"^ LPAREN! expression RPAREN! compoundStatement
// asserts (uncomment if you want 1.4 compatibility)
| "assert"^ expression ( COLON! expression )? SEMI!
// empty statement
| s:SEMI {#s.setType(EMPTY_STAT);}
;
casesGroup
: ( // CONFLICT: to which case group do the statements bind?
// ANTLR generates proper code: it groups the
// many "case"/"default" labels together then
// follows them with the statements
options {
greedy = true;
}
:
aCase
)+
caseSList
{#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
;
aCase
: ("case"^ expression | "default") COLON!
;
caseSList
: (statement)*
{#caseSList = #(#[SLIST,"SLIST"],#caseSList);}
;
// The initializer for a for loop
forInit
// if it looks like a declaration, it is
: ( (declaration)=> declaration
// otherwise it could be an expression list...
| expressionList
)?
{#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
;
forCond
: (expression)?
{#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
;
forIter
: (expressionList)?
{#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
;
// an exception handler try/catch block
tryBlock
: "try"^ compoundStatement
(handler)*
( finallyClause )?
;
finallyClause
: "finally"^ compoundStatement
;
// an exception handler
handler
: "catch"^ LPAREN! parameterDeclaration RPAREN! compoundStatement
;
// expressions
// Note that most of these expressions follow the pattern
// thisLevelExpression :
// nextHigherPrecedenceExpression
// (OPERATOR nextHigherPrecedenceExpression)*
// which is a standard recursive definition for a parsing an expression.
// The operators in java have the following precedences:
// lowest (13) = *= /= %= += -= <<= >>= >>>= &= ^= |=
// (12) ?:
// (11) ||
// (10) &&
// ( 9) |
// ( 8) ^
// ( 7) &
// ( 6) == !=
// ( 5) < <= > >=
// ( 4) << >>
// ( 3) +(binary) -(binary)
// ( 2) * / %
// ( 1) ++ -- +(unary) -(unary) ~ ! (type)
// [] () (method call) . (dot -- identifier qualification)
// new () (explicit parenthesis)
//
// the last two are not usually on a precedence chart; I put them in
// to point out that new has a higher precedence than '.', so you
// can validy use
// new Frame().show()
//
// Note that the above precedence levels map to the rules below...
// Once you have a precedence chart, writing the appropriate rules as below
// is usually very straightfoward
// the mother of all expressions
expression
: assignmentExpression
{#expression = #(#[EXPR,"EXPR"],#expression);}
;
// This is a list of expressions.
expressionList
: expression (COMMA! expression)*
{#expressionList = #(#[ELIST,"ELIST"], expressionList);}
;
// assignment expression (level 13)
assignmentExpression
: conditionalExpression
( ( ASSIGN^
| PLUS_ASSIGN^
| MINUS_ASSIGN^
| STAR_ASSIGN^
| DIV_ASSIGN^
| MOD_ASSIGN^
| SR_ASSIGN^
| BSR_ASSIGN^
| SL_ASSIGN^
| BAND_ASSIGN^
| BXOR_ASSIGN^
| BOR_ASSIGN^
)
assignmentExpression
)?
;
// conditional test (level 12)
conditionalExpression
: logicalOrExpression
( QUESTION^ assignmentExpression COLON! conditionalExpression )?
;
// logical or (||) (level 11)
logicalOrExpression
: logicalAndExpression (LOR^ logicalAndExpression)*
;
// logical and (&&) (level 10)
logicalAndExpression
: inclusiveOrExpression (LAND^ inclusiveOrExpression)*
;
// bitwise or non-short-circuiting or (|) (level 9)
inclusiveOrExpression
: exclusiveOrExpression (BOR^ exclusiveOrExpression)*
;
// exclusive or (^) (level 8)
exclusiveOrExpression
: andExpression (BXOR^ andExpression)*
;
// bitwise or non-short-circuiting and (&) (level 7)
andExpression
: equalityExpression (BAND^ equalityExpression)*
;
// equality/inequality (==/!=) (level 6)
equalityExpression
: relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
;
// boolean relational expressions (level 5)
relationalExpression
: shiftExpression
( ( ( LT^
| GT^
| LE^
| GE^
)
shiftExpression
)*
| "instanceof"^ typeSpec[true]
)
;
// bit shift expressions (level 4)
shiftExpression
: additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
;
// binary addition/subtraction (level 3)
additiveExpression
: multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
;
// multiplication/division/modulo (level 2)
multiplicativeExpression
: unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
;
unaryExpression
: INC^ unaryExpression
| DEC^ unaryExpression
| MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
| PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
| unaryExpressionNotPlusMinus
;
unaryExpressionNotPlusMinus
: BNOT^ unaryExpression
| LNOT^ unaryExpression
| ( // subrule allows option to shut off warnings
options {
// "(int" ambig with postfixExpr due to lack of sequence
// info in linear approximate LL(k). It's ok. Shut up.
generateAmbigWarnings=false;
}
: // If typecast is built in type, must be numeric operand
// Also, no reason to backtrack if type keyword like int, float...
lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
unaryExpression
// Have to backtrack to see if operator follows. If no operator
// follows, it's a typecast. No semantic checking needed to parse.
// if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
| (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
unaryExpressionNotPlusMinus
| postfixExpression
)
;
// qualified names, array expressions, method invocation, post inc/dec
postfixExpression
:
/*
"this"! lp1:LPAREN^ argList RPAREN!
{#lp1.setType(CTOR_CALL);}
| "super"! lp2:LPAREN^ argList RPAREN!
{#lp2.setType(SUPER_CTOR_CALL);}
|
*/
primaryExpression
(
/*
options {
// the use of postfixExpression in SUPER_CTOR_CALL adds DOT
// to the lookahead set, and gives loads of false non-det
// warnings.
// shut them off.
generateAmbigWarnings=false;
}
: */
DOT^ IDENT
( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
argList
RPAREN!
)?
| DOT^ "this"
| DOT^ "super"
( // (new Outer()).super() (create enclosing instance)
lp3:LPAREN^ argList RPAREN!
{#lp3.setType(SUPER_CTOR_CALL);}
| DOT^ IDENT
( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
argList
RPAREN!
)?
)
| DOT^ newExpression
| lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK!
)*
( // possibly add on a post-increment or post-decrement.
// allows INC/DEC on too much, but semantics can check
in:INC^ {#in.setType(POST_INC);}
| de:DEC^ {#de.setType(POST_DEC);}
)?
;
// the basic element of an expression
primaryExpression
: identPrimary ( options {greedy=true;} : DOT^ "class" )?
| constant
| "true"
| "false"
| "null"
| newExpression
| "this"
| "super"
| LPAREN! assignmentExpression RPAREN!
// look for int.class and int[].class
| builtInType
( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
DOT^ "class"
;
/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
* and a.b.c.class refs. Also this(...) and super(...). Match
* this or super.
*/
identPrimary
: IDENT
(
options {
// .ident could match here or in postfixExpression.
// We do want to match here. Turn off warning.
greedy=true;
}
: DOT^ IDENT
)*
(
options {
// ARRAY_DECLARATOR here conflicts with INDEX_OP in
// postfixExpression on LBRACK RBRACK.
// We want to match [] here, so greedy. This overcomes
// limitation of linear approximate lookahead.
greedy=true;
}
: ( lp:LPAREN^ {#lp.setType(METHOD_CALL);} argList RPAREN! )
| ( options {greedy=true;} :
lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
)+
)?
;
/** object instantiation.
* Trees are built as illustrated by the following input/tree pairs:
*
* new T()
*
* new
* |
* T -- ELIST
* |
* arg1 -- arg2 -- .. -- argn
*
* new int[]
*
* new
* |
* int -- ARRAY_DECLARATOR
*
* new int[] {1,2}
*
* new
* |
* int -- ARRAY_DECLARATOR -- ARRAY_INIT
* |
* EXPR -- EXPR
* | |
* 1 2
*
* new int[3]
* new
* |
* int -- ARRAY_DECLARATOR
* |
* EXPR
* |
* 3
*
* new int[1][2]
*
* new
* |
* int -- ARRAY_DECLARATOR
* |
* ARRAY_DECLARATOR -- EXPR
* | |
* EXPR 1
* |
* 2
*
*/
newExpression
: "new"^ type
( LPAREN! argList RPAREN! (classBlock)?
//java 1.1
// Note: This will allow bad constructs like
// new int[4][][3] {exp,exp}.
// There needs to be a semantic check here...
// to make sure:
// a) [ expr ] and [ ] are not mixed
// b) [ expr ] and an init are not used together
| newArrayDeclarator (arrayInitializer)?
)
;
argList
: ( expressionList
| /*nothing*/
{#argList = #[ELIST,"ELIST"];}
)
;
newArrayDeclarator
: (
// CONFLICT:
// newExpression is a primaryExpression which can be
// followed by an array index reference. This is ok,
// as the generated code will stay in this loop as
// long as it sees an LBRACK (proper behavior)
options {
warnWhenFollowAmbig = false;
}
:
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
(expression)?
RBRACK!
)+
;
constant
: NUM_INT
| CHAR_LITERAL
| STRING_LITERAL
| NUM_FLOAT
| NUM_LONG
| NUM_DOUBLE
;
//----------------------------------------------------------------------------
// The Java scanner
//----------------------------------------------------------------------------
class JavaLexer extends Lexer;
options {
exportVocab=Java; // call the vocabulary "Java"
testLiterals=false; // don't automatically test for literals
k=4; // four characters of lookahead
charVocabulary='\u0003'..'\uFFFF';
// without inlining some bitset tests, couldn't do unicode;
// I need to make ANTLR generate smaller bitsets; see
// bottom of JavaLexer.java
codeGenBitsetTestThreshold=20;
}
// OPERATORS
QUESTION : '?' ;
LPAREN : '(' ;
RPAREN : ')' ;
LBRACK : '[' ;
RBRACK : ']' ;
LCURLY : '{' ;
RCURLY : '}' ;
COLON : ':' ;
COMMA : ',' ;
//DOT : '.' ;
ASSIGN : '=' ;
EQUAL : "==" ;
LNOT : '!' ;
BNOT : '~' ;
NOT_EQUAL : "!=" ;
DIV : '/' ;
DIV_ASSIGN : "/=" ;
PLUS : '+' ;
PLUS_ASSIGN : "+=" ;
INC : "++" ;
MINUS : '-' ;
MINUS_ASSIGN : "-=" ;
DEC : "--" ;
STAR : '*' ;
STAR_ASSIGN : "*=" ;
MOD : '%' ;
MOD_ASSIGN : "%=" ;
SR : ">>" ;
SR_ASSIGN : ">>=" ;
BSR : ">>>" ;
BSR_ASSIGN : ">>>=" ;
GE : ">=" ;
GT : ">" ;
SL : "<<" ;
SL_ASSIGN : "<<=" ;
LE : "<=" ;
LT : '<' ;
BXOR : '^' ;
BXOR_ASSIGN : "^=" ;
BOR : '|' ;
BOR_ASSIGN : "|=" ;
LOR : "||" ;
BAND : '&' ;
BAND_ASSIGN : "&=" ;
LAND : "&&" ;
SEMI : ';' ;
// Whitespace -- ignored
WS : ( ' '
| '\t'
| '\f'
// handle newlines
| ( options {generateAmbigWarnings=false;}
: "\r\n" // Evil DOS
| '\r' // Macintosh
| '\n' // Unix (the right way)
)
{ newline(); }
)+
{ _ttype = Token.SKIP; }
;
// Single-line comments
SL_COMMENT
: "//"
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
{$setType(Token.SKIP); newline();}
;
// multiple-line comments
ML_COMMENT
: "/*"
( /* '\r' '\n' can be matched in one alternative or by matching
'\r' in one iteration and '\n' in another. I am trying to
handle any flavor of newline that comes in, but the language
that allows both "\r\n" and "\r" and "\n" to all be valid
newline is ambiguous. Consequently, the resulting grammar
must be ambiguous. I'm shutting this warning off.
*/
options {
generateAmbigWarnings=false;
}
:
{ LA(2)!='/' }? '*'
| '\r' '\n' {newline();}
| '\r' {newline();}
| '\n' {newline();}
| ~('*'|'\n'|'\r')
)*
"*/"
{$setType(Token.SKIP);}
;
// character literals
CHAR_LITERAL
: '\'' ( ESC | ~'\'' ) '\''
;
// string literals
STRING_LITERAL
: '"' (ESC|~('"'|'\\'))* '"'
;
// escape sequence -- note that this is protected; it can only be called
// from another lexer rule -- it will not ever directly return a token to
// the parser
// There are various ambiguities hushed in this rule. The optional
// '0'...'9' digit matches should be matched here rather than letting
// them go back to STRING_LITERAL to be matched. ANTLR does the
// right thing by matching immediately; hence, it's ok to shut off
// the FOLLOW ambig warnings.
protected
ESC
: '\\'
( 'n'
| 'r'
| 't'
| 'b'
| 'f'
| '"'
| '\''
| '\\'
| ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
| '0'..'3'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
)?
)?
| '4'..'7'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
)?
)
;
// hexadecimal digit (again, note it's protected!)
protected
HEX_DIGIT
: ('0'..'9'|'A'..'F'|'a'..'f')
;
// a dummy rule to force vocabulary to be all characters (except special
// ones that ANTLR uses internally (0 to 2)
protected
VOCAB
: '\3'..'\377'
;
// an identifier. Note that testLiterals is set to true! This means
// that after we match the rule, we look in the literals table to see
// if it's a literal or really an identifer
IDENT
options {testLiterals=true;}
: ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
;
// a numeric literal
NUM_INT
{boolean isDecimal=false; Token t=null;}
: '.' {_ttype = DOT;}
( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
{
if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
_ttype = NUM_FLOAT;
}
else {
_ttype = NUM_DOUBLE; // assume double
}
}
)?
| ( '0' {isDecimal = true;} // special case for just '0'
( ('x'|'X')
( // hex
// the 'e'|'E' and float suffix stuff look
// like hex digits, hence the (...)+ doesn't
// know when to stop: ambig. ANTLR resolves
// it correctly by matching immediately. It
// is therefor ok to hush warning.
options {
warnWhenFollowAmbig=false;
}
: HEX_DIGIT
)+
| ('0'..'7')+ // octal
)?
| ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
)
( ('l'|'L') { _ttype = NUM_LONG; }
// only check to see if it's a float if looks like decimal so far
| {isDecimal}?
( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
| EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
| f4:FLOAT_SUFFIX {t=f4;}
)
{
if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
_ttype = NUM_FLOAT;
}
else {
_ttype = NUM_DOUBLE; // assume double
}
}
)?
;
// a couple protected methods to assist in matching floating point numbers
protected
EXPONENT
: ('e'|'E') ('+'|'-')? ('0'..'9')+
;
protected
FLOAT_SUFFIX
: 'f'|'F'|'d'|'D'
;

View File

@ -1,2002 +0,0 @@
header
{
package de.hunsicker.jalopy.language.antlr;
import de.hunsicker.jalopy.language.antlr.JavaNode;
import de.hunsicker.jalopy.language.JavaNodeHelper;
}
/** Java 1.5 Recognizer
*
* Run 'java Main [-showtree] directory-full-of-java-files'
*
* [The -showtree option pops up a Swing frame that shows
* the JavaNode constructed from the parser.]
*
* Run 'java Main <directory full of java files>'
*
* Contributing authors:
* John Mitchell johnm@non.net
* Terence Parr parrt@magelang.com
* John Lilley jlilley@empathy.com
* Scott Stanchfield thetick@magelang.com
* Markus Mohnen mohnen@informatik.rwth-aachen.de
* Peter Williams pete.williams@sun.com
* Allan Jacobs Allan.Jacobs@eng.sun.com
* Steve Messick messick@redhills.com
* John Pybus john@pybus.org
*
* Version 1.00 December 9, 1997 -- initial release
* Version 1.01 December 10, 1997
* fixed bug in octal def (0..7 not 0..8)
* Version 1.10 August 1998 (parrt)
* added tree construction
* fixed definition of WS,comments for mac,pc,unix newlines
* added unary plus
* Version 1.11 (Nov 20, 1998)
* Added "shutup" option to turn off last ambig warning.
* Fixed inner class def to allow named class defs as statements
* synchronized requires compound not simple statement
* add [] after builtInType DOT class in primaryExpression
* "const" is reserved but not valid..removed from modifiers
* Version 1.12 (Feb 2, 1999)
* Changed LITERAL_xxx to xxx in tree grammar.
* Updated java.g to use tokens {...} now for 2.6.0 (new feature).
*
* Version 1.13 (Apr 23, 1999)
* Didn't have (stat)? for else clause in tree parser.
* Didn't gen ASTs for interface extends. Updated tree parser too.
* Updated to 2.6.0.
* Version 1.14 (Jun 20, 1999)
* Allowed final/abstract on local classes.
* Removed local interfaces from methods
* Put instanceof precedence where it belongs...in relationalExpr
* It also had expr not type as arg; fixed it.
* Missing ! on SEMI in classBlock
* fixed: (expr) + "string" was parsed incorrectly (+ as unary plus).
* fixed: didn't like Object[].class in parser or tree parser
* Version 1.15 (Jun 26, 1999)
* Screwed up rule with instanceof in it. :( Fixed.
* Tree parser didn't like (expr).something; fixed.
* Allowed multiple inheritance in tree grammar. oops.
* Version 1.16 (August 22, 1999)
* Extending an interface built a wacky tree: had extra EXTENDS.
* Tree grammar didn't allow multiple superinterfaces.
* Tree grammar didn't allow empty var initializer: {}
* Version 1.17 (October 12, 1999)
* ESC lexer rule allowed 399 max not 377 max.
* java.tree.g didn't handle the expression of synchronized
* statements.
* Version 1.18 (August 12, 2001)
* Terence updated to Java 2 Version 1.3 by
* observing/combining work of Allan Jacobs and Steve
* Messick. Handles 1.3 src. Summary:
* o primary didn't include boolean.class kind of thing
* o constructor calls parsed explicitly now:
* see explicitConstructorInvocation
* o add strictfp modifier
* o missing objBlock after new expression in tree grammar
* o merged local class definition alternatives, moved after declaration
* o fixed problem with ClassName.super.field
* o reordered some alternatives to make things more efficient
* o long and double constants were not differentiated from int/float
* o whitespace rule was inefficient: matched only one char
* o add an examples directory with some nasty 1.3 cases
* o made Main.java use buffered IO and a Reader for Unicode support
* o supports UNICODE?
* Using Unicode charVocabulay makes code file big, but only
* in the bitsets at the end. I need to make ANTLR generate
* unicode bitsets more efficiently.
* Version 1.19 (April 25, 2002)
* Terence added in nice fixes by John Pybus concerning floating
* constants and problems with super() calls. John did a nice
* reorg of the primary/postfix expression stuff to read better
* and makes f.g.super() parse properly (it was METHOD_CALL not
* a SUPER_CTOR_CALL). Also:
*
* o "finally" clause was a root...made it a child of "try"
* o Added stuff for asserts too for Java 1.4, but *commented out*
* as it is not backward compatible.
*
* Version 1.20 (October 27, 2002)
*
* Terence ended up reorging John Pybus' stuff to
* remove some nondeterminisms and some syntactic predicates.
* Note that the grammar is stricter now; e.g., this(...) must
* be the first statement.
*
* Trinary ?: operator wasn't working as array name:
* (isBig ? bigDigits : digits)[i];
*
* Checked parser/tree parser on source for
* Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4,
* and the 110k-line jGuru server source.
*
* Version 1.21 (October 17, 2003)
* Fixed lots of problems including:
* Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g
* He found a problem/fix with floating point that start with 0
* Ray also fixed problem that (int.class) was not recognized.
* Thorsten van Ellen noticed that \n are allowed incorrectly in strings.
* TJP fixed CHAR_LITERAL analogously.
*
* Version 1.21.2 (March, 2003)
* Changes by Matt Quail to support generics (as per JDK1.5/JSR14)
* Notes:
* o We only allow the "extends" keyword and not the "implements"
* keyword, since thats what JSR14 seems to imply.
* o Thanks to Monty Zukowski for his help on the antlr-interest
* mail list.
* o Thanks to Alan Eliasen for testing the grammar over his
* Fink source base
*
* Version 1.22 (July, 2004)
* Changes by Michael Studman to support Java 1.5 language extensions
* Notes:
* o Added support for annotations types
* o Finished off Matt Quail's generics enhancements to support bound type arguments
* o Added support for new for statement syntax
* o Added support for static import syntax
* o Added support for enum types
* o Tested against JDK 1.5 source base and source base of jdigraph project
* o Thanks to Matt Quail for doing the hard part by doing most of the generics work
*
* Version 1.22.1 (July 28, 2004)
* Bug/omission fixes for Java 1.5 language support
* o Fixed tree structure bug with classOrInterface - thanks to Pieter Vangorpto for
* spotting this
* o Fixed bug where incorrect handling of SR and BSR tokens would cause type
* parameters to be recognised as type arguments.
* o Enabled type parameters on constructors, annotations on enum constants
* and package definitions
* o Fixed problems when parsing if ((char.class.equals(c))) {} - solution by Matt Quail at Cenqua
*
* Version 1.22.2 (July 28, 2004)
* Slight refactoring of Java 1.5 language support
* o Refactored for/"foreach" productions so that original literal "for" literal
* is still used but the for sub-clauses vary by token type
* o Fixed bug where type parameter was not included in generic constructor's branch of AST
*
* Version 1.22.3 (August 26, 2004)
* Bug fixes as identified by Michael Stahl; clean up of tabs/spaces
* and other refactorings
* o Fixed typeParameters omission in identPrimary and newStatement
* o Replaced GT reconcilliation code with simple semantic predicate
* o Adapted enum/assert keyword checking support from Michael Stahl's java15 grammar
* o Refactored typeDefinition production and field productions to reduce duplication
*
* Version 1.22.4 (October 21, 2004)
* Small bux fixes
* o Added typeArguments to explicitConstructorInvocation, e.g. new <String>MyParameterised()
* o Added typeArguments to postfixExpression productions for anonymous inner class super
* constructor invocation, e.g. new Outer().<String>super()
* o Fixed bug in array declarations identified by Geoff Roy
*
* This grammar is in the PUBLIC DOMAIN
*/
class InternalJavaParser extends Parser;
options {
k = 2; // two token lookahead
exportVocab=Java; // Call its vocabulary "Java"
codeGenMakeSwitchThreshold = 2; // Some optimizations
codeGenBitsetTestThreshold = 3;
defaultErrorHandler = false; // Don't generate parser error handlers
buildAST = true;
// classHeaderSuffix = "Parser";
importVocab = Common;
ASTLabelType = JavaNode;
// useTokenPrefix = true;
// This class is abstract
classHeaderPrefix = "public abstract";
}
tokens {
BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF;
INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF;
PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE;
PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP;
POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT;
IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION;
FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";
STRICTFP="strictfp"; SUPER_CTOR_CALL; CTOR_CALL; VARIABLE_PARAMETER_DEF;
STATIC_IMPORT; ENUM_DEF; ENUM_CONSTANT_DEF; FOR_EACH_CLAUSE; ANNOTATION_DEF; ANNOTATIONS;
ANNOTATION; ANNOTATION_MEMBER_VALUE_PAIR; ANNOTATION_FIELD_DEF; ANNOTATION_ARRAY_INIT;
TYPE_ARGUMENTS; TYPE_ARGUMENT; TYPE_PARAMETERS; TYPE_PARAMETER; WILDCARD_TYPE;
TYPE_UPPER_BOUNDS; TYPE_LOWER_BOUNDS;
ROOT;CASESLIST;SEPARATOR_COMMENT;BOF;SYNBLOCK;SPECIAL_COMMENT;
}
{
/**
* Counts the number of LT seen in the typeArguments production.
* It is used in semantic predicates to ensure we have seen
* enough closing '>' characters; which actually may have been
* either GT, SR or BSR tokens.
*/
private int ltCounter = 0;
protected abstract void attachStuff(JavaNode[] nodes) throws TokenStreamIOException;
}
// Compilation Unit: In Java, this is a single file. This is the start
// rule for this parser compilationUnit
parse
{
JavaNode root = (JavaNode) getASTFactory().create();
root.setType(JavaTokenTypes.ROOT);
root.setText(getFilename());
currentAST.root = root;
}
: // A compilation unit starts with an optional package definition
( (annotations "package")=> packageDefinition
| /* nothing */
)
// Next we have a series of zero or more import statements
( importDefinition )*
// Wrapping things up with any number of class or interface
// definitions
( typeDefinition )*
EOF
;
// Package statement: optional annotations followed by "package" then the package identifier.
packageDefinition
options {defaultErrorHandler = true;} // let ANTLR handle errors
: annotations p:"package"^ {#p.setType(PACKAGE_DEF);} identifier SEMI
;
// Import statement: import followed by a package or class name
importDefinition
options {defaultErrorHandler = true;}
{ boolean isStatic = false; }
: i:"import"^ {#i.setType(IMPORT);} ( "static"! {#i.setType(STATIC_IMPORT);} )? identifierStar SEMI
;
// A type definition is either a class, interface, enum or annotation with possible additional semis.
typeDefinition
options {defaultErrorHandler = true;}
: m:modifiers!
typeDefinitionInternal[#m]
| SEMI
;
// Protected type definitions production for reuse in other productions
protected typeDefinitionInternal[JavaNode mods]
: classDefinition[#mods] // inner class
| interfaceDefinition[#mods] // inner interface
| enumDefinition[#mods] // inner enum
| annotationDefinition[#mods] // inner annotation
;
// A declaration is the creation of a reference or primitive-type variable
// Create a separate Type/Var tree for each var in the var list.
declaration!
: m:modifiers t:typeSpec[false] v:variableDefinitions[#m,#t]
{#declaration = #v;}
;
// A type specification is a type name with possible brackets afterwards
// (which would make it an array type).
typeSpec[boolean addImagNode]
: classTypeSpec[addImagNode]
| builtInTypeSpec[addImagNode]
;
// A class type specification is a class type with either:
// - possible brackets afterwards
// (which would make it an array type).
// - generic type arguments after
classTypeSpec[boolean addImagNode]
: classOrInterfaceType[false]
(options{greedy=true;}: // match as many as possible
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
)*
{
if ( addImagNode ) {
#classTypeSpec = #(#[TYPE,"TYPE"], #classTypeSpec);
}
}
;
// A non-built in type name, with possible type parameters
classOrInterfaceType[boolean addImagNode]
: IDENT^ (typeArguments)?
(options{greedy=true;}: // match as many as possible
DOT^
IDENT (typeArguments)?
)*
{
if ( addImagNode ) {
#classOrInterfaceType = #(#[TYPE,"TYPE"], #classOrInterfaceType);
}
}
;
// A specialised form of typeSpec where built in types must be arrays
typeArgumentSpec
: classTypeSpec[true]
| builtInTypeArraySpec[true]
;
// A generic type argument is a class type, a possibly bounded wildcard type or a built-in type array
typeArgument
: ( typeArgumentSpec
| wildcardType
)
{#typeArgument = #(#[TYPE_ARGUMENT,"TYPE_ARGUMENT"], #typeArgument);}
;
// Wildcard type indicating all types (with possible constraint)
wildcardType
: q:QUESTION^ {#q.setType(WILDCARD_TYPE);}
(("extends" | "super")=> typeArgumentBounds)?
;
// Type arguments to a class or interface type
typeArguments
{int currentLtLevel = 0;}
:
{currentLtLevel = ltCounter;}
LT! {ltCounter++;}
typeArgument
(options{greedy=true;}: // match as many as possible
{inputState.guessing !=0 || ltCounter == currentLtLevel + 1}?
COMMA typeArgument
)*
( // turn warning off since Antlr generates the right code,
// plus we have our semantic predicate below
options{generateAmbigWarnings=false;}:
typeArgumentsOrParametersEnd
)?
// make sure we have gobbled up enough '>' characters
// if we are at the "top level" of nested typeArgument productions
{(currentLtLevel != 0) || ltCounter == currentLtLevel}?
{#typeArguments = #(#[TYPE_ARGUMENTS, "TYPE_ARGUMENTS"], #typeArguments);}
;
// this gobbles up *some* amount of '>' characters, and counts how many
// it gobbled.
protected typeArgumentsOrParametersEnd
: GT! {ltCounter-=1;}
| SR! {ltCounter-=2;}
| BSR! {ltCounter-=3;}
;
// Restriction on wildcard types based on super class or derrived class
typeArgumentBounds
{boolean isUpperBounds = false;}
:
( "extends"! {isUpperBounds=true;} | "super"! ) classOrInterfaceType[false]
{
if (isUpperBounds)
{
#typeArgumentBounds = #(#[TYPE_UPPER_BOUNDS,"TYPE_UPPER_BOUNDS"], #typeArgumentBounds);
}
else
{
#typeArgumentBounds = #(#[TYPE_LOWER_BOUNDS,"TYPE_LOWER_BOUNDS"], #typeArgumentBounds);
}
}
;
// A builtin type array specification is a builtin type with brackets afterwards
builtInTypeArraySpec[boolean addImagNode]
: builtInType
(options{greedy=true;}: // match as many as possible
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
)+
{
if ( addImagNode ) {
#builtInTypeArraySpec = #(#[TYPE,"TYPE"], #builtInTypeArraySpec);
}
}
;
// A builtin type specification is a builtin type with possible brackets
// afterwards (which would make it an array type).
builtInTypeSpec[boolean addImagNode]
: builtInType
(options{greedy=true;}: // match as many as possible
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
)*
{
if ( addImagNode ) {
#builtInTypeSpec = #(#[TYPE,"TYPE"], #builtInTypeSpec);
}
}
;
// A type name. which is either a (possibly qualified and parameterized)
// class name or a primitive (builtin) type
type
: classOrInterfaceType[false]
| builtInType
;
// The primitive types.
builtInType
: "void"
| "boolean"
| "byte"
| "char"
| "short"
| "int"
| "float"
| "long"
| "double"
;
// A (possibly-qualified) java identifier. We start with the first IDENT
// and expand its name by adding dots and following IDENTS
identifier
: IDENT ( DOT^ IDENT )*
;
identifierStar
: IDENT
( DOT^ IDENT )*
( DOT^ STAR )?
;
// A list of zero or more modifiers. We could have used (modifier)* in
// place of a call to modifiers, but I thought it was a good idea to keep
// this rule separate so they can easily be collected in a Vector if
// someone so desires
modifiers
:
(
//hush warnings since the semantic check for "@interface" solves the non-determinism
options{generateAmbigWarnings=false;}:
modifier
|
//Semantic check that we aren't matching @interface as this is not an annotation
//A nicer way to do this would be nice
{LA(1)==AT && !LT(2).getText().equals("interface")}? annotation
)*
{#modifiers = #([MODIFIERS, "MODIFIERS"], #modifiers);}
;
// modifiers for Java classes, interfaces, class/instance vars and methods
modifier
: "private"
| "public"
| "protected"
| "static"
| "transient"
| "final"
| "abstract"
| "native"
| "threadsafe"
| "synchronized"
| "volatile"
| "strictfp"
;
annotation!
: a:AT i:identifier ( lp:LPAREN ( args:annotationArguments )? rp:RPAREN )?
{#annotation = #(#[ANNOTATION,"ANNOTATION"],a, i, lp, args, rp);}
;
annotations
: (annotation)*
{#annotations = #([ANNOTATIONS, "ANNOTATIONS"], #annotations);}
;
annotationArguments
: annotationMemberValueInitializer | anntotationMemberValuePairs
;
anntotationMemberValuePairs
: annotationMemberValuePair ( COMMA annotationMemberValuePair )*
;
annotationMemberValuePair!
: i:IDENT ASSIGN! v:annotationMemberValueInitializer
{#annotationMemberValuePair = #(#[ANNOTATION_MEMBER_VALUE_PAIR,"ANNOTATION_MEMBER_VALUE_PAIR"], i, v);}
;
annotationMemberValueInitializer
:
conditionalExpression | annotation | annotationMemberArrayInitializer
;
// This is an initializer used to set up an annotation member array.
annotationMemberArrayInitializer
: lc:LCURLY^ {#lc.setType(ANNOTATION_ARRAY_INIT);}
( annotationMemberArrayValueInitializer
(
// CONFLICT: does a COMMA after an initializer start a new
// initializer or start the option ',' at end?
// ANTLR generates proper code by matching
// the comma as soon as possible.
options {
warnWhenFollowAmbig = false;
}
:
COMMA annotationMemberArrayValueInitializer
)*
(COMMA)?
)?
RCURLY
;
// The two things that can initialize an annotation array element are a conditional expression
// and an annotation (nested annotation array initialisers are not valid)
annotationMemberArrayValueInitializer
: conditionalExpression
| annotation
;
superClassClause!
: ( "extends" c:classOrInterfaceType[false] )?
{#superClassClause = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],c);}
;
// Definition of a Java class
classDefinition![JavaNode modifiers]
: c:"class" IDENT
// it _might_ have type paramaters
(tp:typeParameters)?
// it _might_ have a superclass...
sc:superClassClause
// it might implement some interfaces...
ic:implementsClause
// now parse the body of the class
cb:classBlock
{#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
modifiers,IDENT,tp,sc,ic,cb);
attachStuff(new JavaNode[] {#classDefinition, modifiers, #c});
}
;
// Definition of a Java Interface
interfaceDefinition![JavaNode modifiers]
: i:"interface" IDENT
// it _might_ have type paramaters
(tp:typeParameters)?
// it might extend some other interfaces
ie:interfaceExtends
// now parse the body of the interface (looks like a class...)
ib:interfaceBlock
{#interfaceDefinition = #(#[INTERFACE_DEF,"INTERFACE_DEF"],
modifiers,IDENT,tp,ie,ib);
attachStuff(new JavaNode[] {#interfaceDefinition, modifiers, #i});
}
;
enumDefinition![JavaNode modifiers]
: e:"enum" IDENT
// it might implement some interfaces...
ic:implementsClause
// now parse the body of the enum
eb:enumBlock
{#enumDefinition = #(#[ENUM_DEF,"ENUM_DEF"],
modifiers,IDENT,ic,eb);
attachStuff(new JavaNode[] {#enumDefinition, modifiers, #e});
}
;
annotationDefinition![JavaNode modifiers]
: a:AT "interface" IDENT
// now parse the body of the annotation
ab:annotationBlock
{#annotationDefinition = #(#[ANNOTATION_DEF,"ANNOTATION_DEF"],
modifiers,IDENT,ab);
attachStuff(new JavaNode[] {#annotationDefinition, modifiers, #a});
}
;
typeParameters
{int currentLtLevel = 0;}
:
{currentLtLevel = ltCounter;}
LT {ltCounter++;}
typeParameter (COMMA typeParameter)*
(typeArgumentsOrParametersEnd)?
// make sure we have gobbled up enough '>' characters
// if we are at the "top level" of nested typeArgument productions
{(currentLtLevel != 0) || ltCounter == currentLtLevel}?
{#typeParameters = #(#[TYPE_PARAMETERS, "TYPE_PARAMETERS"], #typeParameters);}
;
typeParameter
:
// I'm pretty sure Antlr generates the right thing here:
(id:IDENT) ( options{generateAmbigWarnings=false;}: typeParameterBounds )?
{#typeParameter = #(#[TYPE_PARAMETER,"TYPE_PARAMETER"], #typeParameter);}
;
typeParameterBounds
:
"extends"! classOrInterfaceType[false]
(BAND classOrInterfaceType[false])*
{#typeParameterBounds = #(#[TYPE_UPPER_BOUNDS,"TYPE_UPPER_BOUNDS"], #typeParameterBounds);}
;
// This is the body of a class. You can have classFields and extra semicolons.
classBlock
: lc:LCURLY^
( classField | SEMI )*
RCURLY
{ #lc.setType(OBJBLOCK);}
//{#classBlock = #([OBJBLOCK, "OBJBLOCK"], #classBlock);}
;
// This is the body of an interface. You can have interfaceField and extra semicolons.
interfaceBlock
: lc:LCURLY^
( interfaceField | SEMI )*
RCURLY
{ #lc.setType(OBJBLOCK);}
//{#interfaceBlock = #([OBJBLOCK, "OBJBLOCK"], #interfaceBlock);}
;
// This is the body of an annotation. You can have annotation fields and extra semicolons,
// That's about it (until you see what an annoation field is...)
annotationBlock
: lc:LCURLY^
( annotationField | SEMI )*
RCURLY
{ #lc.setType(OBJBLOCK);}
// {#annotationBlock = #([OBJBLOCK, "OBJBLOCK"], #annotationBlock);}
;
// This is the body of an enum. You can have zero or more enum constants
// followed by any number of fields like a regular class
enumBlock
: lc:LCURLY^
( enumConstant ( options{greedy=true;}: COMMA! enumConstant )* ( COMMA! )? )?
( SEMI! ( classField | SEMI! )* )?
RCURLY
{ #lc.setType(OBJBLOCK);}
// {#enumBlock = #([OBJBLOCK, "OBJBLOCK"], #enumBlock);}
;
// An annotation field
annotationField!
: mods:modifiers
( td:typeDefinitionInternal[#mods]
{#annotationField = #td;}
| t:typeSpec[false] // annotation field
( i:IDENT // the name of the field
LPAREN RPAREN
rt:declaratorBrackets[#t]
( "default" amvi:annotationMemberValueInitializer ) ?
// { if (#d!=null) #d = #(d,#(amvi)); }
SEMI
{#annotationField =
#(#[ANNOTATION_FIELD_DEF,"ANNOTATION_FIELD_DEF"],
mods,
#(#[TYPE,"TYPE"],rt),
i,LPAREN,RPAREN,amvi,SEMI
);
attachStuff(new JavaNode[] {#annotationField, #mods, #t});
}
| v:variableDefinitions[#mods,#t] // typeVariableDefinitions
{
#annotationField = #v;
}
)
)
;
//An enum constant may have optional parameters and may have a
//a class body
enumConstant!
: an:annotations
i:IDENT
( lp:LPAREN
a:argList
rp:RPAREN
)?
( b:enumConstantBlock )?
{#enumConstant = #([ENUM_CONSTANT_DEF, "ENUM_CONSTANT_DEF"], an, i, lp,a,rp, b);}
;
//The class-like body of an enum constant
enumConstantBlock
: LCURLY
( enumConstantField | SEMI )*
RCURLY
{#enumConstantBlock = #([OBJBLOCK, "OBJBLOCK"], #enumConstantBlock);}
;
//An enum constant field is just like a class field but without
//the posibility of a constructor definition or a static initializer
enumConstantField!
: mods:modifiers
( td:typeDefinitionInternal[#mods]
{#enumConstantField = #td;}
| // A generic method has the typeParameters before the return type.
// This is not allowed for variable definitions, but this production
// allows it, a semantic check could be used if you wanted.
(tp:typeParameters)? t:typeSpec[false] // method or variable declaration(s)
( IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN param:parameterDeclarationList RPAREN
rt:declaratorBrackets[#t]
// get the list of exceptions that this method is
// declared to throw
(tc:throwsClause)?
( s2:compoundStatement | semim:SEMI )
{#enumConstantField = #(#[METHOD_DEF,"METHOD_DEF"],
mods,
tp,
#(#[TYPE,"TYPE"],rt),
IDENT,
param,
tc,
s2,
semim);
attachStuff(new JavaNode[] {#enumConstantField, #mods, #t});
}
| v:variableDefinitions[#mods,#t] // typeVariableDefinitions
{#enumConstantField = #v;
}
)
)
// "{ ... }" instance initializer
| s4:compoundStatement
{#enumConstantField = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);
attachStuff(new JavaNode[] {#enumConstantField, #s4});
}
;
// An interface can extend several other interfaces...
interfaceExtends
: (
e:"extends"!
classOrInterfaceType[false] ( COMMA! classOrInterfaceType[false] )*
)?
{#interfaceExtends = #(#[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],
#interfaceExtends);}
;
// A class can implement several interfaces...
implementsClause
: (
i:"implements"! classOrInterfaceType[false] ( COMMA! classOrInterfaceType[false] )*
)?
{#implementsClause = #(#[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"],
#implementsClause);}
;
// Now the various things that can be defined inside a class
classField!
: // method, constructor, or variable declaration
mods:modifiers
( td:typeDefinitionInternal[#mods]
{#classField = #td;}
| (tp:typeParameters)?
(
h:ctorHead s:constructorBody // constructor
{#classField = #(#[CTOR_DEF,"CTOR_DEF"], mods, tp, h, s);
attachStuff(new JavaNode[] {#classField, #mods, #h});
}
| // A generic method/ctor has the typeParameters before the return type.
// This is not allowed for variable definitions, but this production
// allows it, a semantic check could be used if you wanted.
t:typeSpec[false] // method or variable declaration(s)
( IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN param:parameterDeclarationList RPAREN
rt:declaratorBrackets[#t]
// get the list of exceptions that this method is
// declared to throw
(tc:throwsClause)?
( s2:compoundStatement | semim:SEMI )
{#classField = #(#[METHOD_DEF,"METHOD_DEF"],
mods,
tp,
#(#[TYPE,"TYPE"],rt),
IDENT,
LPAREN,
param,
RPAREN,
tc,
s2,
semim);
attachStuff(new JavaNode[] {#classField, #mods, #t});
}
| v:variableDefinitions[#mods,#t] semi:SEMI!// typeVariableDefinitions
{
#classField = #v;
#classField.addChild(#semi);
AST next = #classField.getNextSibling();
// HACK for multiple variable declaration in one statement
// e.g float x, y, z;
// the semicolon will only be added to the first statement so
// we have to add it manually to all others
if (next != null)
{
AST ssemi = JavaNodeHelper.getFirstChild(#classField, JavaTokenTypes.SEMI);
for (AST var = next; var != null; var = var.getNextSibling())
{
var.addChild(astFactory.create(ssemi));
}
}
}
)
)
)
// "static { ... }" class initializer
| "static" s3:compoundStatement
{#classField = #(#[STATIC_INIT,"STATIC_INIT"], s3);
attachStuff(new JavaNode[] {#classField, #s3});
}
// "{ ... }" instance initializer
| s4:compoundStatement
{#classField = #(#[INSTANCE_INIT,"INSTANCE_INIT"], s4);
attachStuff(new JavaNode[] {#classField, #s4});
}
;
// Now the various things that can be defined inside a interface
interfaceField!
: // method, constructor, or variable declaration
mods:modifiers
( td:typeDefinitionInternal[#mods]
{#interfaceField = #td;}
| (tp:typeParameters)?
// A generic method has the typeParameters before the return type.
// This is not allowed for variable definitions, but this production
// allows it, a semantic check could be used if you want a more strict
// grammar.
t:typeSpec[false] // method or variable declaration(s)
( IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN param:parameterDeclarationList RPAREN
rt:declaratorBrackets[#t]
// get the list of exceptions that this method is
// declared to throw
(tc:throwsClause)?
SEMI
{#interfaceField = #(#[METHOD_DEF,"METHOD_DEF"],
mods,
tp,
#(#[TYPE,"TYPE"],rt),
IDENT,
LPAREN,
param,
RPAREN,
tc,
SEMI);
attachStuff(new JavaNode[] {#interfaceField, #mods, #t});
}
| v:variableDefinitions[#mods,#t] semi:SEMI!
{
#interfaceField = #v;
#interfaceField.addChild(#semi);
AST next = #interfaceField.getNextSibling();
// HACK for multiple variable declaration in one statement
// e.g float x, y, z;
// the semicolon will only be added to the first statement so
// we have to add it manually to all others
if (next != null)
{
AST ssemi = JavaNodeHelper.getFirstChild(#interfaceField, JavaTokenTypes.SEMI);
for (AST var = next; var != null; var = var.getNextSibling())
{
var.addChild(astFactory.create(ssemi));
}
}
}
)
)
;
constructorBody
: lc:LCURLY^ {#lc.setType(SLIST);}
( options { greedy=true; } : explicitConstructorInvocation)?
(statement)*
RCURLY
;
/** Catch obvious constructor calls, but not the expr.super(...) calls */
explicitConstructorInvocation
: (typeArguments)?
( "this" lp1:LPAREN^ argList RPAREN SEMI
{#lp1.setType(CTOR_CALL);}
| "super" lp2:LPAREN^ argList RPAREN SEMI
{#lp2.setType(SUPER_CTOR_CALL);}
)
;
/** Catch variable definitions but add the semicolon ???*/
typeVariableDefinitions[JavaNode mods, JavaNode t]
: v:variableDefinitions[mods,t]
(semi:SEMI
{
#v.addChild(#semi);
}
)
;
variableDefinitions[JavaNode mods, JavaNode t]
: variableDeclarator[(JavaNode)getASTFactory().dupTree(mods),
(JavaNode)getASTFactory().dupTree(t)]
( COMMA!
variableDeclarator[(JavaNode)getASTFactory().dupTree(mods),
(JavaNode)getASTFactory().dupTree(t)]
)*
;
/** Declaration of a variable. This can be a class/instance variable,
* or a local variable in a method
* It can also include possible initialization.
*/
variableDeclarator![JavaNode mods, JavaNode t]
: id:IDENT d:declaratorBrackets[t] v:varInitializer
{#variableDeclarator = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods, #(#[TYPE,"TYPE"],d), id, v);
attachStuff(new JavaNode[] {#variableDeclarator,mods, t});
}
;
declaratorBrackets[JavaNode typ]
: {#declaratorBrackets=typ;}
(lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
;
varInitializer
: ( ASSIGN^ initializer )?
;
// This is an initializer used to set up an array.
arrayInitializer
: lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
( initializer
(
// CONFLICT: does a COMMA after an initializer start a new
// initializer or start the option ',' at end?
// ANTLR generates proper code by matching
// the comma as soon as possible.
options {
warnWhenFollowAmbig = false;
}
:
COMMA initializer
)*
(COMMA)?
)?
RCURLY
;
// The two "things" that can initialize an array element are an expression
// and another (nested) array initializer.
initializer
: expression
| arrayInitializer
;
// This is the header of a method. It includes the name and parameters
// for the method.
// This also watches for a list of exception classes in a "throws" clause.
ctorHead
: IDENT // the name of the method
// parse the formal parameter declarations.
LPAREN parameterDeclarationList RPAREN
// get the list of exceptions that this method is declared to throw
(throwsClause)?
;
// This is a list of exception classes that the method is declared to throw
throwsClause
: "throws"^ identifier ( COMMA identifier )*
;
// A list of formal parameters
// Zero or more parameters
// If a parameter is variable length (e.g. String... myArg) it is the right-most parameter
parameterDeclarationList
// The semantic check in ( .... )* block is flagged as superfluous, and seems superfluous but
// is the only way I could make this work. If my understanding is correct this is a known bug
: ( ( parameterDeclaration )=> parameterDeclaration
( options {warnWhenFollowAmbig=false;} : ( COMMA parameterDeclaration ) => COMMA parameterDeclaration )*
( COMMA variableLengthParameterDeclaration )?
|
variableLengthParameterDeclaration
)?
{#parameterDeclarationList = #(#[PARAMETERS,"PARAMETERS"],
#parameterDeclarationList);}
;
// A formal parameter.
parameterDeclaration!
: pm:parameterModifier t:typeSpec[false] id:IDENT
pd:declaratorBrackets[#t]
{#parameterDeclaration = #(#[PARAMETER_DEF,"PARAMETER_DEF"],
pm, #([TYPE,"TYPE"],pd), id);}
;
variableLengthParameterDeclaration!
: pm:parameterModifier t:typeSpec[false] TRIPLE_DOT id:IDENT
pd:declaratorBrackets[#t]
{#variableLengthParameterDeclaration = #(#[VARIABLE_PARAMETER_DEF,"VARIABLE_PARAMETER_DEF"],
pm, #([TYPE,"TYPE"],pd), id);}
;
parameterModifier
//final can appear amongst annotations in any order - greedily consume any preceding
//annotations to shut nond-eterminism warnings off
: (options{greedy=true;} : annotation)* (f:"final")? (annotation)*
{#parameterModifier = #(#[MODIFIERS,"MODIFIERS"], #parameterModifier);}
;
// Compound statement. This is used in many contexts:
// Inside a class definition prefixed with "static":
// it is a class initializer
// Inside a class definition without "static":
// it is an instance initializer
// As the body of a method
// As a completely indepdent braced block of code inside a method
// it starts a new scope for variable definitions
compoundStatement
: lc:LCURLY^ {#lc.setType(SLIST);}
// include the (possibly-empty) list of statements
(statement)*
RCURLY
;
statement
// A list of statements in curly braces -- start a new scope!
: compoundStatement
// declarations are ambiguous with "ID DOT" relative to expression
// statements. Must backtrack to be sure. Could use a semantic
// predicate to test symbol table to see what the type was coming
// up, but that's pretty hard without a symbol table ;)
// (declaration)=> declaration SEMI
| (declaration)=> decl:declaration semi1:SEMI!
{
// add semicolon to the AST
#decl.addChild(#semi1);
AST next = currentAST.root.getNextSibling();
// HACK for multiple variable declaration in one statement
// e.g float x, y, z;
// the semicolon will only be added to the first statement so
// we have to add it manually to all others
if (next != null)
{
AST semi = JavaNodeHelper.getFirstChild(currentAST.root, JavaTokenTypes.SEMI);
for (AST var = next; var != null; var = var.getNextSibling())
{
var.addChild(astFactory.create(semi));
}
}
}
// An expression statement. This could be a method call,
// assignment statement, or any other expression evaluated for
// side-effects.
| e:expression semi2:SEMI!
{#e.addChild(#semi2);
}
//TODO: what abour interfaces, enums and annotations
// class definition
| m:modifiers! classDefinition[#m]
// Attach a label to the front of a statement
| IDENT c:COLON^ {#c.setType(LABELED_STAT);} statement
// If-else statement
| "if"^ LPAREN expression RPAREN statement
(
// CONFLICT: the old "dangling-else" problem...
// ANTLR generates proper code matching
// as soon as possible. Hush warning.
options {
warnWhenFollowAmbig = false;
}
:
"else" statement
)?
// For statement
| forStatement
// While statement
| "while"^ LPAREN expression RPAREN statement
// do-while statement
| "do"^ statement "while" LPAREN expression RPAREN SEMI
// get out of a loop (or switch)
| "break"^ (IDENT)? SEMI
// do next iteration of a loop
| "continue"^ (IDENT)? SEMI
// Return an expression
| "return"^ (expression)? SEMI
// switch/case statement
| "switch"^ LPAREN expression RPAREN LCURLY
( casesGroup )*
RCURLY
// exception try-catch block
| tryBlock
// throw an exception
| "throw"^ expression SEMI
// synchronize a statement
| synBlock:"synchronized"^ LPAREN expression RPAREN compoundStatement
{ #synBlock.setType(SYNBLOCK);}
// asserts (uncomment if you want 1.4 compatibility)
| "assert"^ expression ( COLON! expression )? SEMI
// empty statement possibly ?????
| s:SEMI {#s.setType(EMPTY_STAT);}
;
forStatement
: f:"for"^
LPAREN
( (forInit SEMI)=>traditionalForClause
| forEachClause
)
RPAREN
statement // statement to loop over
;
traditionalForClause
:
forInit SEMI // initializer
forCond SEMI // condition test
forIter // updater
;
forEachClause
:
p:parameterDeclaration COLON! expression
{#forEachClause = #(#[FOR_EACH_CLAUSE,"FOR_EACH_CLAUSE"], #forEachClause);}
;
casesGroup
: ( // CONFLICT: to which case group do the statements bind?
// ANTLR generates proper code: it groups the
// many "case"/"default" labels together then
// follows them with the statements
options {
greedy = true;
}
:
aCase
)+
caseSList
{#casesGroup = #([CASE_GROUP, "CASE_GROUP"], #casesGroup);}
;
aCase
: ("case"^ expression | "default") COLON
;
caseSList
: (statement)*
{#caseSList = #(#[CASESLIST,"CASESLIST"],#caseSList);}
;
// The initializer for a for loop
forInit
// if it looks like a declaration, it is
: ((declaration)=> declaration
// otherwise it could be an expression list...
| expressionList
)?
{#forInit = #(#[FOR_INIT,"FOR_INIT"],#forInit);}
;
forCond
: (expression)?
{#forCond = #(#[FOR_CONDITION,"FOR_CONDITION"],#forCond);}
;
forIter
: (expressionList)?
{#forIter = #(#[FOR_ITERATOR,"FOR_ITERATOR"],#forIter);}
;
// an exception handler try/catch block
tryBlock
: "try"^ compoundStatement
(handler)*
( finallyClause )?
;
finallyClause
: "finally"^ compoundStatement
;
// an exception handler
handler
: "catch"^ LPAREN parameterDeclaration RPAREN compoundStatement
;
// expressions
// Note that most of these expressions follow the pattern
// thisLevelExpression :
// nextHigherPrecedenceExpression
// (OPERATOR nextHigherPrecedenceExpression)*
// which is a standard recursive definition for a parsing an expression.
// The operators in java have the following precedences:
// lowest (13) = *= /= %= += -= <<= >>= >>>= &= ^= |=
// (12) ?:
// (11) ||
// (10) &&
// ( 9) |
// ( 8) ^
// ( 7) &
// ( 6) == !=
// ( 5) < <= > >=
// ( 4) << >>
// ( 3) +(binary) -(binary)
// ( 2) * / %
// ( 1) ++ -- +(unary) -(unary) ~ ! (type)
// [] () (method call) . (dot -- identifier qualification)
// new () (explicit parenthesis)
//
// the last two are not usually on a precedence chart; I put them in
// to point out that new has a higher precedence than '.', so you
// can validy use
// new Frame().show()
//
// Note that the above precedence levels map to the rules below...
// Once you have a precedence chart, writing the appropriate rules as below
// is usually very straightfoward
// the mother of all expressions
expression
: assignmentExpression
{#expression = #(#[EXPR,"EXPR"],#expression);}
;
// This is a list of expressions.
expressionList
: expression (COMMA expression)*
{#expressionList = #(#[ELIST,"ELIST"], expressionList);}
;
// assignment expression (level 13)
assignmentExpression
: conditionalExpression
( ( ASSIGN^
| PLUS_ASSIGN^
| MINUS_ASSIGN^
| STAR_ASSIGN^
| DIV_ASSIGN^
| MOD_ASSIGN^
| SR_ASSIGN^
| BSR_ASSIGN^
| SL_ASSIGN^
| BAND_ASSIGN^
| BXOR_ASSIGN^
| BOR_ASSIGN^
)
assignmentExpression
)?
;
// conditional test (level 12)
conditionalExpression
: logicalOrExpression
( QUESTION^ assignmentExpression COLON conditionalExpression )?
;
// logical or (||) (level 11)
logicalOrExpression
: logicalAndExpression (LOR^ logicalAndExpression)*
;
// logical and (&&) (level 10)
logicalAndExpression
: inclusiveOrExpression (LAND^ inclusiveOrExpression)*
;
// bitwise or non-short-circuiting or (|) (level 9)
inclusiveOrExpression
: exclusiveOrExpression (BOR^ exclusiveOrExpression)*
;
// exclusive or (^) (level 8)
exclusiveOrExpression
: andExpression (BXOR^ andExpression)*
;
// bitwise or non-short-circuiting and (&) (level 7)
andExpression
: equalityExpression (BAND^ equalityExpression)*
;
// equality/inequality (==/!=) (level 6)
equalityExpression
: relationalExpression ((NOT_EQUAL^ | EQUAL^) relationalExpression)*
;
// boolean relational expressions (level 5)
relationalExpression
: shiftExpression
( ( ( LT^
| GT^
| LE^
| GE^
)
shiftExpression
)*
| "instanceof"^ typeSpec[true]
)
;
// bit shift expressions (level 4)
shiftExpression
: additiveExpression ((SL^ | SR^ | BSR^) additiveExpression)*
;
// binary addition/subtraction (level 3)
additiveExpression
: multiplicativeExpression ((PLUS^ | MINUS^) multiplicativeExpression)*
;
// multiplication/division/modulo (level 2)
multiplicativeExpression
: unaryExpression ((STAR^ | DIV^ | MOD^ ) unaryExpression)*
;
unaryExpression
: INC^ unaryExpression
| DEC^ unaryExpression
| MINUS^ {#MINUS.setType(UNARY_MINUS);} unaryExpression
| PLUS^ {#PLUS.setType(UNARY_PLUS);} unaryExpression
| unaryExpressionNotPlusMinus
;
unaryExpressionNotPlusMinus
: BNOT^ unaryExpression
| LNOT^ unaryExpression
| ( // subrule allows option to shut off warnings
options {
// "(int" ambig with postfixExpr due to lack of sequence
// info in linear approximate LL(k). It's ok. Shut up.
generateAmbigWarnings=false;
}
: // If typecast is built in type, must be numeric operand
// Have to backtrack to see if operator follows
(LPAREN builtInTypeSpec[true] RPAREN unaryExpression)=>
lpb:LPAREN^ {#lpb.setType(TYPECAST);} builtInTypeSpec[true] RPAREN!
unaryExpression
// Have to backtrack to see if operator follows. If no operator
// follows, it's a typecast. No semantic checking needed to parse.
// if it _looks_ like a cast, it _is_ a cast; else it's a "(expr)"
| (LPAREN classTypeSpec[true] RPAREN unaryExpressionNotPlusMinus)=>
lp:LPAREN^ {#lp.setType(TYPECAST);} classTypeSpec[true] RPAREN!
unaryExpressionNotPlusMinus
| postfixExpression
)
;
// qualified names, array expressions, method invocation, post inc/dec
postfixExpression
:
primaryExpression
(
/*
options {
// the use of postfixExpression in SUPER_CTOR_CALL adds DOT
// to the lookahead set, and gives loads of false non-det
// warnings.
// shut them off.
generateAmbigWarnings=false;
}
: */
//type arguments are only appropriate for a parameterized method/ctor invocations
//semantic check may be needed here to ensure that this is the case
DOT^ (typeArguments)?
( IDENT
( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
argList
RPAREN
)?
| "super"
( // (new Outer()).super() (create enclosing instance)
lp3:LPAREN^ argList RPAREN
{#lp3.setType(SUPER_CTOR_CALL);}
| DOT^ (typeArguments)? IDENT
( lps:LPAREN^ {#lps.setType(METHOD_CALL);}
argList
RPAREN
)?
)
)
| DOT^ "this"
| DOT^ newExpression
| lb:LBRACK^ {#lb.setType(INDEX_OP);} expression RBRACK
)*
( // possibly add on a post-increment or post-decrement.
// allows INC/DEC on too much, but semantics can check
in:INC^ {#in.setType(POST_INC);}
| de:DEC^ {#de.setType(POST_DEC);}
)?
;
// the basic element of an expression
primaryExpression
: identPrimary ( options {greedy=true;} : DOT^ "class" )?
| constant
| "true"
| "false"
| "null"
| newExpression
| "this"
| "super"
| LPAREN assignmentExpression RPAREN
// look for int.class and int[].class
| builtInType
( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
DOT^ "class"
;
/** Match a, a.b.c refs, a.b.c(...) refs, a.b.c[], a.b.c[].class,
* and a.b.c.class refs. Also this(...) and super(...). Match
* this or super.
*/
identPrimary
: (ta1:typeArguments!)?
IDENT
// Syntax for method invocation with type arguments is
// <String>foo("blah")
(
options {
// .ident could match here or in postfixExpression.
// We do want to match here. Turn off warning.
greedy=true;
// This turns the ambiguity warning of the second alternative
// off. See below. (The "false" predicate makes it non-issue)
warnWhenFollowAmbig=false;
}
// we have a new nondeterminism because of
// typeArguments... only a syntactic predicate will help...
// The problem is that this loop here conflicts with
// DOT typeArguments "super" in postfixExpression (k=2)
// A proper solution would require a lot of refactoring...
// Original way.
// : (DOT (typeArguments)? IDENT) =>
// DOT^ (ta2:typeArguments!)? IDENT
: (DOT^ (typeArguments)? IDENT)
| {false}? // FIXME: this is very ugly but it seems to work...
// this will also produce an ANTLR warning!
// Unfortunately a syntactic predicate can only select one of
// multiple alternatives on the same level, not break out of
// an enclosing loop, which is why this ugly hack (a fake
// empty alternative with always-false semantic predicate)
// is necessary.
)*
(
options {
// ARRAY_DECLARATOR here conflicts with INDEX_OP in
// postfixExpression on LBRACK RBRACK.
// We want to match [] here, so greedy. This overcomes
// limitation of linear approximate lookahead.
greedy=true;
}
: ( lp:LPAREN^ {#lp.setType(METHOD_CALL);}
// if the input is valid, only the last IDENT may
// have preceding typeArguments... rather hacky, this is...
// Not required because see above
// {if (#ta2 != null) astFactory.addASTChild(currentAST, #ta2);}
// {if (#ta2 == null) astFactory.addASTChild(currentAST, #ta1);}
argList RPAREN
)
| ( options {greedy=true;} :
lbc:LBRACK^ {#lbc.setType(ARRAY_DECLARATOR);} RBRACK!
)+
)?
;
/** object instantiation.
* Trees are built as illustrated by the following input/tree pairs:
*
* new T()
*
* new
* |
* T -- ELIST
* |
* arg1 -- arg2 -- .. -- argn
*
* new int[]
*
* new
* |
* int -- ARRAY_DECLARATOR
*
* new int[] {1,2}
*
* new
* |
* int -- ARRAY_DECLARATOR -- ARRAY_INIT
* |
* EXPR -- EXPR
* | |
* 1 2
*
* new int[3]
* new
* |
* int -- ARRAY_DECLARATOR
* |
* EXPR
* |
* 3
*
* new int[1][2]
*
* new
* |
* int -- ARRAY_DECLARATOR
* |
* ARRAY_DECLARATOR -- EXPR
* | |
* EXPR 1
* |
* 2
*
*/
newExpression
: "new"^ (typeArguments)? type
( LPAREN argList RPAREN (classBlock)?
//java 1.1
// Note: This will allow bad constructs like
// new int[4][][3] {exp,exp}.
// There needs to be a semantic check here...
// to make sure:
// a) [ expr ] and [ ] are not mixed
// b) [ expr ] and an init are not used together
| newArrayDeclarator (arrayInitializer)?
)
;
argList
: ( expressionList
| /*nothing*/
{#argList = #[ELIST,"ELIST"];}
)
;
newArrayDeclarator
: (
// CONFLICT:
// newExpression is a primaryExpression which can be
// followed by an array index reference. This is ok,
// as the generated code will stay in this loop as
// long as it sees an LBRACK (proper behavior)
options {
warnWhenFollowAmbig = false;
}
:
lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);}
(expression)?
RBRACK!
)+
;
constant
: NUM_INT
| CHAR_LITERAL
| STRING_LITERAL
| NUM_FLOAT
| NUM_LONG
| NUM_DOUBLE
;
//----------------------------------------------------------------------------
// The Java scanner
//----------------------------------------------------------------------------
class InternalJavaLexer extends Lexer;
options {
exportVocab=Java; // call the vocabulary "Java"
testLiterals=false; // don't automatically test for literals
k=4; // four characters of lookahead
charVocabulary='\u0003'..'\uFFFF';
// without inlining some bitset tests, couldn't do unicode;
// I need to make ANTLR generate smaller bitsets; see
// bottom of JavaLexer.java
codeGenBitsetTestThreshold=20;
// This class is abstract
classHeaderPrefix = "public abstract";
}
{
/** flag for enabling the "assert" keyword */
private boolean assertEnabled = true;
/** flag for enabling the "enum" keyword */
private boolean enumEnabled = true;
/** Enable the "assert" keyword */
public void enableAssert(boolean shouldEnable) { assertEnabled = shouldEnable; }
/** Query the "assert" keyword state */
public boolean isAssertEnabled() { return assertEnabled; }
/** Enable the "enum" keyword */
public void enableEnum(boolean shouldEnable) { enumEnabled = shouldEnable; }
/** Query the "enum" keyword state */
public boolean isEnumEnabled() { return enumEnabled; }
protected abstract Token makeJavaDoc(Token node, String text) throws TokenStreamIOException;
}
// OPERATORS
QUESTION : '?' ;
LPAREN : '(' ;
RPAREN : ')' ;
LBRACK : '[' ;
RBRACK : ']' ;
LCURLY : '{' ;
RCURLY : '}' ;
COLON : ':' ;
COMMA : ',' ;
//DOT : '.' ;
ASSIGN : '=' ;
EQUAL : "==" ;
LNOT : '!' ;
BNOT : '~' ;
NOT_EQUAL : "!=" ;
DIV : '/' ;
DIV_ASSIGN : "/=" ;
PLUS : '+' ;
PLUS_ASSIGN : "+=" ;
INC : "++" ;
MINUS : '-' ;
MINUS_ASSIGN : "-=" ;
DEC : "--" ;
STAR : '*' ;
STAR_ASSIGN : "*=" ;
MOD : '%' ;
MOD_ASSIGN : "%=" ;
SR : ">>" ;
SR_ASSIGN : ">>=" ;
BSR : ">>>" ;
BSR_ASSIGN : ">>>=" ;
GE : ">=" ;
GT : ">" ;
SL : "<<" ;
SL_ASSIGN : "<<=" ;
LE : "<=" ;
LT : '<' ;
BXOR : '^' ;
BXOR_ASSIGN : "^=" ;
BOR : '|' ;
BOR_ASSIGN : "|=" ;
LOR : "||" ;
BAND : '&' ;
BAND_ASSIGN : "&=" ;
LAND : "&&" ;
SEMI : ';' ;
// Whitespace -- ignored
WS : ( ' '
| '\t'
| '\f'
// handle newlines
| ( options {generateAmbigWarnings=false;}
: "\r\n" // Evil DOS
| '\r' // Macintosh
| '\n' // Unix (the right way)
)
{ newline(); }
)+
{ // _ttype = Token.SKIP;
}
;
protected SEPARATOR_COMMENT
: "//~" (~('\n'|'\r') {if (LA(1) == EOF_CHAR) break;} )*
( '\n'! | '\r'!('\n'!)? )?
{newline();}
;
// Single-line comments
protected SL_COMMENT
: "//" (~('\n'|'\r') {if (LA(1) == EOF_CHAR) break;} )*
( '\n'! | '\r'!('\n'!)? )?
{newline();
}
;
COMMENT
:
(
options {
// ANTLR does it right by consuming input as soon as possible
generateAmbigWarnings=false;
// TODO spec:SPECIAL_COMMENT {$setToken(spec);} |
}:
sep:SEPARATOR_COMMENT {$setToken(sep); } |
sl:SL_COMMENT {$setToken(sl); }
)
;
// multiple-line comments
ML_COMMENT
: "/*"
( /* '\r' '\n' can be matched in one alternative or by matching
'\r' in one iteration and '\n' in another. I am trying to
handle any flavor of newline that comes in, but the language
that allows both "\r\n" and "\r" and "\n" to all be valid
newline is ambiguous. Consequently, the resulting grammar
must be ambiguous. I'm shutting this warning off.
*/
options {
generateAmbigWarnings=false;
}
:
{ LA(2)!='/' }? '*'
| '\r' '\n' {newline();}
| '\r' {newline();}
| '\n' {newline();}
| ~('*'|'\n'|'\r')
)*
"*/"
{
// $setType(Token.SKIP);
Token n = makeJavaDoc(makeToken(_ttype), $getText);
$setToken(n);
$setType(n.getType());
}
;
// character literals
CHAR_LITERAL
: '\'' ( ESC | ~('\''|'\n'|'\r'|'\\') ) '\''
;
// string literals
STRING_LITERAL
: '"' (ESC|~('"'|'\\'|'\n'|'\r'))* '"'
;
// escape sequence -- note that this is protected; it can only be called
// from another lexer rule -- it will not ever directly return a token to
// the parser
// There are various ambiguities hushed in this rule. The optional
// '0'...'9' digit matches should be matched here rather than letting
// them go back to STRING_LITERAL to be matched. ANTLR does the
// right thing by matching immediately; hence, it's ok to shut off
// the FOLLOW ambig warnings.
protected
ESC
: '\\'
( 'n'
| 'r'
| 't'
| 'b'
| 'f'
| '"'
| '\''
| '\\'
| ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
| '0'..'3'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
)?
)?
| '4'..'7'
(
options {
warnWhenFollowAmbig = false;
}
: '0'..'7'
)?
)
;
// hexadecimal digit (again, note it's protected!)
protected
HEX_DIGIT
: ('0'..'9'|'A'..'F'|'a'..'f')
;
// a dummy rule to force vocabulary to be all characters (except special
// ones that ANTLR uses internally (0 to 2)
protected
VOCAB
: '\3'..'\377'
;
// an identifier. Note that testLiterals is set to true! This means
// that after we match the rule, we look in the literals table to see
// if it's a literal or really an identifer
IDENT
options {testLiterals=true;}
: ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')*
{
// check if "assert" keyword is enabled
if (assertEnabled && "assert".equals($getText)) {
$setType(LITERAL_assert); // set token type for the rule in the parser
}
// check if "enum" keyword is enabled
if (enumEnabled && "enum".equals($getText)) {
$setType(LITERAL_enum); // set token type for the rule in the parser
}
}
;
// a numeric literal
NUM_INT
{boolean isDecimal=false; Token t=null;}
: '.' {_ttype = DOT;}
(
(('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
{
if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
_ttype = NUM_FLOAT;
}
else {
_ttype = NUM_DOUBLE; // assume double
}
})
|
// JDK 1.5 token for variable length arguments
(".." {_ttype = TRIPLE_DOT;})
)?
| ( '0' {isDecimal = true;} // special case for just '0'
( ('x'|'X')
( // hex
// the 'e'|'E' and float suffix stuff look
// like hex digits, hence the (...)+ doesn't
// know when to stop: ambig. ANTLR resolves
// it correctly by matching immediately. It
// is therefor ok to hush warning.
options {
warnWhenFollowAmbig=false;
}
: HEX_DIGIT
)+
| //float or double with leading zero
(('0'..'9')+ ('.'|EXPONENT|FLOAT_SUFFIX)) => ('0'..'9')+
| ('0'..'7')+ // octal
)?
| ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
)
( ('l'|'L') { _ttype = NUM_LONG; }
// only check to see if it's a float if looks like decimal so far
| {isDecimal}?
( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
| EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
| f4:FLOAT_SUFFIX {t=f4;}
)
{
if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
_ttype = NUM_FLOAT;
}
else {
_ttype = NUM_DOUBLE; // assume double
}
}
)?
;
// JDK 1.5 token for annotations and their declarations
AT
: '@'
;
// a couple protected methods to assist in matching floating point numbers
protected
EXPONENT
: ('e'|'E') ('+'|'-')? ('0'..'9')+
;
protected
FLOAT_SUFFIX
: 'f'|'F'|'d'|'D'
;

View File

@ -1,326 +0,0 @@
package antlr;
/** Java 1.3 AST Recognizer Grammar
*
* Author: (see java.g preamble)
*
* This grammar is in the PUBLIC DOMAIN
*/
class JavaTreeParser extends TreeParser;
options {
importVocab = Java;
}
compilationUnit
: (packageDefinition)?
(importDefinition)*
(typeDefinition)*
;
packageDefinition
: #( PACKAGE_DEF identifier )
;
importDefinition
: #( IMPORT identifierStar )
;
typeDefinition
: #(CLASS_DEF modifiers IDENT extendsClause implementsClause objBlock )
| #(INTERFACE_DEF modifiers IDENT extendsClause interfaceBlock )
;
typeSpec
: #(TYPE typeSpecArray)
;
typeSpecArray
: #( ARRAY_DECLARATOR typeSpecArray )
| type
;
type: identifier
| builtInType
;
builtInType
: "void"
| "boolean"
| "byte"
| "char"
| "short"
| "int"
| "float"
| "long"
| "double"
;
modifiers
: #( MODIFIERS (modifier)* )
;
modifier
: "private"
| "public"
| "protected"
| "static"
| "transient"
| "final"
| "abstract"
| "native"
| "threadsafe"
| "synchronized"
| "const"
| "volatile"
| "strictfp"
;
extendsClause
: #(EXTENDS_CLAUSE (identifier)* )
;
implementsClause
: #(IMPLEMENTS_CLAUSE (identifier)* )
;
interfaceBlock
: #( OBJBLOCK
( methodDecl
| variableDef
)*
)
;
objBlock
: #( OBJBLOCK
( ctorDef
| methodDef
| variableDef
| typeDefinition
| #(STATIC_INIT slist)
| #(INSTANCE_INIT slist)
)*
)
;
ctorDef
: #(CTOR_DEF modifiers methodHead (slist)?)
;
methodDecl
: #(METHOD_DEF modifiers typeSpec methodHead)
;
methodDef
: #(METHOD_DEF modifiers typeSpec methodHead (slist)?)
;
variableDef
: #(VARIABLE_DEF modifiers typeSpec variableDeclarator varInitializer)
;
parameterDef
: #(PARAMETER_DEF modifiers typeSpec IDENT )
;
objectinitializer
: #(INSTANCE_INIT slist)
;
variableDeclarator
: IDENT
| LBRACK variableDeclarator
;
varInitializer
: #(ASSIGN initializer)
|
;
initializer
: expression
| arrayInitializer
;
arrayInitializer
: #(ARRAY_INIT (initializer)*)
;
methodHead
: IDENT #( PARAMETERS (parameterDef)* ) (throwsClause)?
;
throwsClause
: #( "throws" (identifier)* )
;
identifier
: IDENT
| #( DOT identifier IDENT )
;
identifierStar
: IDENT
| #( DOT identifier (STAR|IDENT) )
;
slist
: #( SLIST (stat)* )
;
stat: typeDefinition
| variableDef
| expression
| #(LABELED_STAT IDENT stat)
| #("if" expression stat (stat)? )
| #( "for"
#(FOR_INIT (variableDef | elist)?)
#(FOR_CONDITION (expression)?)
#(FOR_ITERATOR (elist)?)
stat
)
| #("while" expression stat)
| #("do" stat expression)
| #("break" (IDENT)? )
| #("continue" (IDENT)? )
| #("return" (expression)? )
| #("switch" expression (caseGroup)*)
| #("throw" expression)
| #("synchronized" expression stat)
| tryBlock
| slist // nested SLIST
// uncomment to make assert JDK 1.4 stuff work
| #("assert" expression (expression)?)
| EMPTY_STAT
;
caseGroup
: #(CASE_GROUP (#("case" expression) | "default")+ slist)
;
tryBlock
: #( "try" slist (handler)* (#("finally" slist))? )
;
handler
: #( "catch" parameterDef slist )
;
elist
: #( ELIST (expression)* )
;
expression
: #(EXPR expr)
;
expr: #(QUESTION expr expr expr) // trinary operator
| #(ASSIGN expr expr) // binary operators...
| #(PLUS_ASSIGN expr expr)
| #(MINUS_ASSIGN expr expr)
| #(STAR_ASSIGN expr expr)
| #(DIV_ASSIGN expr expr)
| #(MOD_ASSIGN expr expr)
| #(SR_ASSIGN expr expr)
| #(BSR_ASSIGN expr expr)
| #(SL_ASSIGN expr expr)
| #(BAND_ASSIGN expr expr)
| #(BXOR_ASSIGN expr expr)
| #(BOR_ASSIGN expr expr)
| #(LOR expr expr)
| #(LAND expr expr)
| #(BOR expr expr)
| #(BXOR expr expr)
| #(BAND expr expr)
| #(NOT_EQUAL expr expr)
| #(EQUAL expr expr)
| #(LT expr expr)
| #(GT expr expr)
| #(LE expr expr)
| #(GE expr expr)
| #(SL expr expr)
| #(SR expr expr)
| #(BSR expr expr)
| #(PLUS expr expr)
| #(MINUS expr expr)
| #(DIV expr expr)
| #(MOD expr expr)
| #(STAR expr expr)
| #(INC expr)
| #(DEC expr)
| #(POST_INC expr)
| #(POST_DEC expr)
| #(BNOT expr)
| #(LNOT expr)
| #("instanceof" expr expr)
| #(UNARY_MINUS expr)
| #(UNARY_PLUS expr)
| primaryExpression
;
primaryExpression
: IDENT
| #( DOT
( expr
( IDENT
| arrayIndex
| "this"
| "class"
| #( "new" IDENT elist )
| "super"
)
| #(ARRAY_DECLARATOR typeSpecArray)
| builtInType ("class")?
)
)
| arrayIndex
| #(METHOD_CALL primaryExpression elist)
| ctorCall
| #(TYPECAST typeSpec expr)
| newExpression
| constant
| "super"
| "true"
| "false"
| "this"
| "null"
| typeSpec // type name used with instanceof
;
ctorCall
: #( CTOR_CALL elist )
| #( SUPER_CTOR_CALL
( elist
| primaryExpression elist
)
)
;
arrayIndex
: #(INDEX_OP expr expression)
;
constant
: NUM_INT
| CHAR_LITERAL
| STRING_LITERAL
| NUM_FLOAT
| NUM_DOUBLE
| NUM_LONG
;
newExpression
: #( "new" type
( newArrayDeclarator (arrayInitializer)?
| elist (objBlock)?
)
)
;
newArrayDeclarator
: #( ARRAY_DECLARATOR (newArrayDeclarator)? (expression)? )
;

445
build/build.xml Normal file
View File

@ -0,0 +1,445 @@
<?xml version="1.0"?>
<project name="Arduino" default="build">
<!-- Sets properties for macosx/windows/linux depending on current system -->
<condition property="macosx"><os family="mac" /></condition>
<condition property="windows"><os family="windows" /></condition>
<condition property="linux"><os family="unix" /></condition>
<condition property="platform"
value="macosx"><os family="mac" /></condition>
<condition property="platform"
value="windows"><os family="windows" /></condition>
<condition property="platform"
value="linux"><os family="unix" /></condition>
<!-- Libraries required for running arduino -->
<fileset dir=".." id="runtime.jars">
<include name="core/core.jar" />
<include name="app/pde.jar" />
<include name="app/lib/ecj.jar" />
<include name="app/lib/jna.jar" />
<include name="app/lib/oro.jar" />
<include name="app/lib/RXTXcomm.jar" />
<include name="app/lib/ant.jar" />
<include name="app/lib/ant-launcher.jar" />
</fileset>
<target name="build" description="Build Arduino.">
<antcall target="${platform}-build" />
</target>
<target name="run" description="Run Arduino.">
<antcall target="${platform}-run" />
</target>
<target name="dist" depends="revision-check"
description="Build Arduino for distribution.">
<input message="Enter version number:"
addproperty="version"
defaultvalue="${revision}" />
<antcall target="${platform}-dist" />
</target>
<!-- "§$§$&, ant doesn't have a built-in help target :( -->
<target name="help" description="Show project help">
<java classname="org.apache.tools.ant.Main">
<arg value="-p" />
</java>
</target>
<!-- - - - - - - - - - - - - - - - - - -->
<!-- Subprojects: Core, App, Libraries -->
<!-- - - - - - - - - - - - - - - - - - -->
<target name="subprojects-clean">
<subant buildpath="../core" target="clean"/>
<subant buildpath="../app" target="clean"/>
</target>
<target name="subprojects-build">
<subant buildpath="../core" target="build"/>
<subant buildpath="../app" target="build"/>
</target>
<!-- - - - - - - - - -->
<!-- Basic Assembly -->
<!-- - - - - - - - - -->
<target name="assemble">
<fail unless="target.path"
message="Do not call assemble from the command line." />
<!-- copy shared tools folder -->
<copy todir="${target.path}/tools">
<fileset dir="shared/tools" />
</copy>
<!-- copy library folder -->
<copy todir="${target.path}/libraries">
<fileset dir="../libraries" />
</copy>
<!-- copy hardware folder -->
<copy todir="${target.path}/hardware">
<fileset dir="../hardware" />
</copy>
<!-- copy shared examples folder -->
<copy todir="${target.path}/examples">
<fileset dir="shared/examples" />
</copy>
<!-- Unzip documentation -->
<unzip dest="${target.path}" src="shared/reference.zip" overwrite="false"/>
<!-- Write the revision file! -->
<echo file="${target.path}/lib/version.txt" message="${version}" />
</target>
<!-- - - - - - - - - -->
<!-- Revision check -->
<!-- - - - - - - - - -->
<target name="revision-check">
<!-- figure out the revision number -->
<loadfile srcfile="../todo.txt" property="revision">
<filterchain>
<headfilter lines="1"/>
<tokenfilter>
<stringtokenizer suppressdelims="true"/>
<!-- grab the thing from the first line that's 4 digits -->
<containsregex pattern="(\d\d\d\d)" />
</tokenfilter>
</filterchain>
</loadfile>
<!-- <echo message="revision is ${revision}." /> -->
<!-- figure out the revision number in base.java -->
<loadfile srcfile="../app/src/processing/app/Base.java"
property="revision.base">
<filterchain>
<tokenfilter>
<linetokenizer />
<containsregex pattern="String VERSION_NAME = "/>
<replaceregex pattern="[^0-9]*" flags="g" replace=""/>
</tokenfilter>
</filterchain>
</loadfile>
<!-- <echo message="base revision is ${revision.base}." /> -->
<condition property="revision.correct">
<!-- Using contains because I can't figure out how to get rid of the
LF in revision.base. Please file a bug if you have a fix. -->
<contains string="${revision.base}" substring="${revision}"/>
</condition>
<!-- the revision.base property won't be set
if $revision wasn't found... -->
<fail unless="revision.correct"
message="Fix revision number in Base.java" />
</target>
<!-- - - - - - - - -->
<!-- Mac OS X -->
<!-- - - - - - - - -->
<target name="macosx-clean" depends="subprojects-clean" description="Clean Mac OS X build">
<delete dir="macosx/work" />
<delete dir="macosx/working_dir" />
<delete dir="macosx/working.dmg" />
<delete file="macosx/arduino-*.dmg" />
</target>
<target name="macosx-checkos" unless="macosx">
<echo>
=======================================================
Arduino for Mac OS X can only be built on Mac OS X.
Bye.
=======================================================
</echo>
<fail message="wrong platform (${os.name})" />
</target>
<target name="macosx-build" if="macosx" depends="revision-check, macosx-checkos, subprojects-build" description="Build Mac OS X version">
<mkdir dir="macosx/work" />
<!-- assemble the pde -->
<copy todir="macosx/work">
<fileset dir="macosx/" includes="template.app/**"/>
</copy>
<!-- <rename src="macosx/work/template.app"
dest="macosx/work/Arduino.app" />-->
<move file="macosx/work/template.app"
tofile="macosx/work/Arduino.app" />
<chmod file="macosx/work/Arduino.app/Contents/MacOS/JavaApplicationStub" perm="755" />
<copy todir="macosx/work/Arduino.app/Contents/Resources/Java" flatten="true">
<fileset refid="runtime.jars"/>
</copy>
<copy todir="macosx/work/Arduino.app/Contents/Resources/Java">
<fileset dir="shared" includes="lib/**" />
<fileset file="shared/revisions.txt" />
</copy>
<!-- Unzip AVR tools -->
<!-- <unzip dest="macosx/work/Arduino.app/Contents/Resources/Java/hardware" src="macosx/dist/tools-universal.zip" overwrite="false"/> -->
<exec executable="unzip">
<arg value="-q" />
<arg value="-d" />
<arg value="macosx/work/Arduino.app/Contents/Resources/Java/hardware" />
<arg value="macosx/dist/tools-universal.zip" />
</exec>
<antcall target="assemble">
<param name="target.path" value="macosx/work/Arduino.app/Contents/Resources/Java" />
</antcall>
</target>
<target name="macosx-run" depends="macosx-build" description="Run Mac OS X version">
<exec executable="macosx/work/Arduino.app/Contents/MacOS/JavaApplicationStub" spawn="true"/>
</target>
<target name="macosx-dist" if="macosx" depends="macosx-build" description="Create a .dmg of the Mac OS X version">
<!-- now build the dmg -->
<gunzip src="macosx/template.dmg.gz" dest="macosx/working.dmg" />
<mkdir dir="macosx/working_dir" />
<exec executable="hdiutil">
<arg line="attach macosx/working.dmg -noautoopen -mountpoint macosx/working_dir" />
<!--<arg line="attach macosx/working.dmg -noautoopen -quiet -mountpoint macosx/working_dir" />-->
</exec>
<copy todir="macosx/working_dir">
<fileset dir="macosx/work" />
</copy>
<!-- The ant copy command does not preserve permissions. -->
<chmod file="macosx/working_dir/Arduino.app/Contents/MacOS/JavaApplicationStub" perm="+x" />
<!-- Pause briefly for the OS to catch up with the DMG changes.
This prevents "hdiutil: couldn't eject "disk3" - Resource busy"
errors when ejecting the disk in the next step.
You may need to set this value higher for your system. -->
<sleep seconds="3" />
<exec executable="hdiutil">
<!--<arg line="detach macosx/working_dir -quiet -force" />-->
<arg line="detach macosx/working_dir" />
</exec>
<delete file="macosx/arduino-*.dmg" />
<exec executable="hdiutil">
<arg line="convert macosx/working.dmg -quiet -format UDZO -imagekey zlib-level=9 -o macosx/arduino-${version}.dmg" />
</exec>
<!-- Clean up the interim files. -->
<delete file="macosx/working.dmg" />
<delete dir="macosx/working_dir" />
<echo>
=======================================================
Arduino for Mac OS X was built. Grab the image from
macosx/arduino-${version}.dmg
=======================================================
</echo>
</target>
<!-- - - - - - - - -->
<!-- Linux -->
<!-- - - - - - - - -->
<target name="linux-clean" depends="subprojects-clean" description="Clean linux version">
<delete dir="linux/work" />
</target>
<target name="linux-checkos" unless="linux">
<echo>
=======================================================
Arduino for Linux can only be built on on unix systems.
Bye.
=======================================================
</echo>
<fail message="wrong platform (${os.name})" />
</target>
<target name="linux-build" depends="revision-check, linux-checkos, subprojects-build" description="Build linux version">
<mkdir dir="linux/work" />
<copy todir="linux/work">
<fileset dir="shared" includes="lib/**" />
<fileset file="shared/revisions.txt" />
</copy>
<copy todir="linux/work/lib" flatten="true">
<fileset refid="runtime.jars" />
</copy>
<antcall target="assemble">
<param name="target.path" value="linux/work" />
</antcall>
<copy todir="linux/work" file="linux/arduino" />
<chmod perm="755" file="linux/work/arduino" />
</target>
<target name="linux-run" depends="linux-build"
description="Run Linux version">
<exec executable="./arduino" dir="linux/work" spawn="true"/>
</target>
<target name="linux-dist" depends="linux-build"
description="Build .tar.gz of linux version">
<get src="http://dev.processing.org/build/jre-tools-6u18-linux-i586.tgz"
dest="linux/jre.tgz"
usetimestamp="true" />
<untar compression="gzip"
dest="linux/work"
src="linux/jre.tgz"
overwrite="false"/>
<!--
<tar compression="gzip" basedir="linux/work"
destfile="linux/arduino-${version}.tgz" />
-->
<tar compression="gzip" destfile="linux/arduino-${version}.tgz">
<tarfileset dir="linux/work" prefix="arduino-${version}" />
</tar>
<echo>
=======================================================
Arduino for Linux was built. Grab the archive from
build/linux/arduino-${version}.tgz
=======================================================
</echo>
</target>
<!-- - - - - - - - -->
<!-- Windows -->
<!-- - - - - - - - -->
<target name="windows-clean" depends="subprojects-clean"
description="Clean windows version">
<delete dir="windows/work" />
</target>
<target name="windows-checkos" unless="windows">
<echo>
=======================================================
Processing for Windows can only be built on windows.
Bye.
=======================================================
</echo>
<fail message="wrong platform (${os.name})" />
</target>
<target name="windows-build"
depends="revision-check, windows-checkos, subprojects-build"
description="Build windows version">
<mkdir dir="windows/work" />
<!-- assemble the pde -->
<mkdir dir="windows/work/lib" />
<copy todir="windows/work/lib" flatten="true">
<fileset refid="runtime.jars" />
</copy>
<copy todir="windows/work">
<fileset dir="shared" includes="lib/**" />
<fileset file="shared/revisions.txt" />
</copy>
<antcall target="assemble">
<param name="target.path" value="windows/work" />
</antcall>
<property name="launch4j.dir" value="windows/launcher/launch4j/" />
<taskdef name="launch4j"
classname="net.sf.launch4j.ant.Launch4jTask"
classpath="${launch4j.dir}/launch4j.jar; ${launch4j.dir}/lib/xstream.jar" />
<copy todir="windows/work">
<fileset dir="windows/launcher"
includes="about.bmp, application.ico, config.xml"/>
</copy>
<launch4j configFile="windows/work/config.xml" />
<delete dir="windows/work"
includes="about.bmp, application.ico, config.xml" />
<!-- cygwin requires html, dll, and exe to have the +x flag -->
<chmod perm="755">
<fileset dir="windows/work" includes="**/*.html, **/*.dll, **/*.exe" />
</chmod>
</target>
<target name="windows-run" depends="windows-build"
description="Run windows version">
<exec executable="windows/work/processing.exe"
dir="windows/work" spawn="true"/>
</target>
<target name="windows-dist" depends="windows-build"
description="Create .zip files of windows version">
<get src="http://dev.processing.org/build/jre-tools-6u18-windows-i586.zip"
dest="windows/jre.zip"
usetimestamp="true" />
<unzip dest="windows/work" src="windows/jre.zip" overwrite="false"/>
<!--
<zip basedir="windows/work"
prefix="processing-${version}"
destfile="windows/processing-${version}.zip" />
<zip basedir="windows/work"
prefix="processing-${version}"
destfile="windows/processing-${version}-expert.zip"
excludes="java/**" />
-->
<zip destfile="windows/processing-${version}.zip">
<zipfileset dir="windows/work"
prefix="processing-${version}" />
</zip>
<zip destfile="windows/processing-${version}-expert.zip">
<zipfileset dir="windows/work"
prefix="processing-${version}"
excludes="java/**" />
</zip>
<echo>
=======================================================
Processing for Windows was built. Grab the archive from
windows/processing-${version}.zip
windows/processing-${version}-expert.zip
=======================================================
</echo>
</target>
<!-- - - - - - - - -->
<!-- Run It! -->
<!-- - - - - - - - -->
<target name="clean" description="Perform a spring cleaning"
depends="linux-clean, windows-clean, macosx-clean, subprojects-clean">
</target>
</project>

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleName</key>
<string>Arduino</string>
<key>CFBundleAllowMixedLocalizations</key>
<string>true</string>
<key>CFBundleExecutable</key>
<string>JavaApplicationStub</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>Pde1</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleIconFile</key>
<string>processing.icns</string>
<key>CFBundleIdentifier</key>
<string>cc.arduino.Arduino</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>pde</string>
<string>java</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>pde.icns</string>
<key>CFBundleTypeName</key>
<string>Processing Source File</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/plain</string>
</array>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
<key>Java</key>
<dict>
<key>VMOptions</key>
<array>
<string>-Xms128M</string>
<string>-Xmx256M</string>
</array>
<key>MainClass</key>
<string>processing.app.Base</string>
<key>JVMVersion</key>
<string>1.5*</string>
<key>ClassPath</key>
<!-- In 0149, removed /System/Library/Java from the CLASSPATH because
it can cause problems if users have installed weird files there.
http://dev.processing.org/bugs/show_bug.cgi?id=1045 -->
<string>$JAVAROOT/pde.jar:$JAVAROOT/core.jar:$JAVAROOT/antlr.jar:$JAVAROOT/ecj.jar:$JAVAROOT/registry.jar:$JAVAROOT/quaqua.jar:$JAVAROOT/oro.jar:$JAVAROOT/RXTXcomm.jar</string>
<key>JVMArchs</key>
<array>
<!--<string>x86_64</string>--> <!-- currently no 64 bit support -->
<string>i386</string>
<string>ppc</string>
</array>
<!-- More properties can be found in http://developer.apple.com/releasenotes/Java/java141/system_properties/chapter_4_section_1.html#//apple_ref/doc/uid/TP30000285 -->
<key>Properties</key>
<dict>
<!-- Pass the full path of Contents/Resources/Java to the PDE -->
<key>javaroot</key>
<string>$JAVAROOT</string>
<!-- as of 1.0.8, it's safe to use this option again -->
<key>apple.laf.useScreenMenuBar</key>
<string>true</string>
<key>apple.awt.showGrowBox</key>
<string>false</string>
<key>com.apple.smallTabs</key>
<string>true</string>
<key>apple.awt.Antialiasing</key>
<string>false</string>
<key>apple.awt.TextAntialiasing</key>
<string>true</string>
<key>com.apple.hwaccel</key>
<string>true</string>
<key>apple.awt.use-file-dialog-packages</key>
<string>false</string>
<key>apple.awt.graphics.UseQuartz</key>
<string>true</string>
</dict>
</dict>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1 @@
APPLPde1

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -7474,42 +7474,114 @@ public class PApplet extends Applet
}
/**
* Set various hints and hacks for the renderer. This is used to handle obscure rendering features that cannot be implemented in a consistent manner across renderers. Many options will often graduate to standard features instead of hints over time.
* <br><br>hint(ENABLE_OPENGL_4X_SMOOTH) - Enable 4x anti-aliasing for OpenGL. This can help force anti-aliasing if it has not been enabled by the user. On some graphics cards, this can also be set by the graphics driver's control panel, however not all cards make this available. This hint must be called immediately after the size() command because it resets the renderer, obliterating any settings and anything drawn (and like size(), re-running the code that came before it again).
* <br><br>hint(DISABLE_OPENGL_2X_SMOOTH) - In Processing 1.0, Processing always enables 2x smoothing when the OpenGL renderer is used. This hint disables the default 2x smoothing and returns the smoothing behavior found in earlier releases, where smooth() and noSmooth() could be used to enable and disable smoothing, though the quality was inferior.
* <br><br>hint(ENABLE_NATIVE_FONTS) - Use the native version fonts when they are installed, rather than the bitmapped version from a .vlw file. This is useful with the JAVA2D renderer setting, as it will improve font rendering speed. This is not enabled by default, because it can be misleading while testing because the type will look great on your machine (because you have the font installed) but lousy on others' machines if the identical font is unavailable. This option can only be set per-sketch, and must be called before any use of textFont().
* <br><br>hint(DISABLE_DEPTH_TEST) - Disable the zbuffer, allowing you to draw on top of everything at will. When depth testing is disabled, items will be drawn to the screen sequentially, like a painting. This hint is most often used to draw in 3D, then draw in 2D on top of it (for instance, to draw GUI controls in 2D on top of a 3D interface). Starting in release 0149, this will also clear the depth buffer. Restore the default with hint(ENABLE_DEPTH_TEST), but note that with the depth buffer cleared, any 3D drawing that happens later in draw() will ignore existing shapes on the screen.
* <br><br>hint(ENABLE_DEPTH_SORT) - Enable primitive z-sorting of triangles and lines in P3D and OPENGL. This can slow performance considerably, and the algorithm is not yet perfect. Restore the default with hint(DISABLE_DEPTH_SORT).
* <br><br>hint(DISABLE_OPENGL_ERROR_REPORT) - Speeds up the OPENGL renderer setting by not checking for errors while running. Undo with hint(ENABLE_OPENGL_ERROR_REPORT).
* <br><br><!--hint(ENABLE_ACCURATE_TEXTURES) - Enables better texture accuracy for the P3D renderer. This option will do a better job of dealing with textures in perspective. hint(DISABLE_ACCURATE_TEXTURES) returns to the default. This hint is not likely to last long.
* <br/> <br/>-->As of release 0149, unhint() has been removed in favor of adding additional ENABLE/DISABLE constants to reset the default behavior. This prevents the double negatives, and also reinforces which hints can be enabled or disabled.
*
* @webref rendering
* @param which name of the hint to be enabled or disabled
*
* @see processing.core.PGraphics
* @see processing.core.PApplet#createGraphics(int, int, String, String)
* @see processing.core.PApplet#size(int, int)
*/
public void hint(int which) {
if (recorder != null) recorder.hint(which);
g.hint(which);
}
/**
* Start a new shape of type POLYGON
*/
public void beginShape() {
if (recorder != null) recorder.beginShape();
g.beginShape();
}
/**
* Start a new shape.
* <P>
* <B>Differences between beginShape() and line() and point() methods.</B>
* <P>
* beginShape() is intended to be more flexible at the expense of being
* a little more complicated to use. it handles more complicated shapes
* that can consist of many connected lines (so you get joins) or lines
* mixed with curves.
* <P>
* The line() and point() command are for the far more common cases
* (particularly for our audience) that simply need to draw a line
* or a point on the screen.
* <P>
* From the code side of things, line() may or may not call beginShape()
* to do the drawing. In the beta code, they do, but in the alpha code,
* they did not. they might be implemented one way or the other depending
* on tradeoffs of runtime efficiency vs. implementation efficiency &mdash
* meaning the speed that things run at vs. the speed it takes me to write
* the code and maintain it. for beta, the latter is most important so
* that's how things are implemented.
*/
public void beginShape(int kind) {
if (recorder != null) recorder.beginShape(kind);
g.beginShape(kind);
}
/**
* Sets whether the upcoming vertex is part of an edge.
* Equivalent to glEdgeFlag(), for people familiar with OpenGL.
*/
public void edge(boolean edge) {
if (recorder != null) recorder.edge(edge);
g.edge(edge);
}
/**
* Sets the current normal vector. Only applies with 3D rendering
* and inside a beginShape/endShape block.
* <P/>
* This is for drawing three dimensional shapes and surfaces,
* allowing you to specify a vector perpendicular to the surface
* of the shape, which determines how lighting affects it.
* <P/>
* For the most part, PGraphics3D will attempt to automatically
* assign normals to shapes, but since that's imperfect,
* this is a better option when you want more control.
* <P/>
* For people familiar with OpenGL, this function is basically
* identical to glNormal3f().
*/
public void normal(float nx, float ny, float nz) {
if (recorder != null) recorder.normal(nx, ny, nz);
g.normal(nx, ny, nz);
}
/**
* Set texture mode to either to use coordinates based on the IMAGE
* (more intuitive for new users) or NORMALIZED (better for advanced chaps)
*/
public void textureMode(int mode) {
if (recorder != null) recorder.textureMode(mode);
g.textureMode(mode);
}
/**
* Set texture image for current shape.
* Needs to be called between @see beginShape and @see endShape
*
* @param image reference to a PImage object
*/
public void texture(PImage image) {
if (recorder != null) recorder.texture(image);
g.texture(image);
@ -7528,6 +7600,11 @@ public class PApplet extends Applet
}
/**
* Used by renderer subclasses or PShape to efficiently pass in already
* formatted vertex information.
* @param v vertex parameters, as a float array of length VERTEX_FIELD_COUNT
*/
public void vertex(float[] v) {
if (recorder != null) recorder.vertex(v);
g.vertex(v);
@ -7546,6 +7623,7 @@ public class PApplet extends Applet
}
/** This feature is in testing, do not use or rely upon its implementation */
public void breakShape() {
if (recorder != null) recorder.breakShape();
g.breakShape();
@ -7598,6 +7676,26 @@ public class PApplet extends Applet
}
/**
* Draws a point, a coordinate in space at the dimension of one pixel.
* The first parameter is the horizontal value for the point, the second
* value is the vertical value for the point, and the optional third value
* is the depth value. Drawing this shape in 3D using the <b>z</b>
* parameter requires the P3D or OPENGL parameter in combination with
* size as shown in the above example.
* <br><br>Due to what appears to be a bug in Apple's Java implementation,
* the point() and set() methods are extremely slow in some circumstances
* when used with the default renderer. Using P2D or P3D will fix the
* problem. Grouping many calls to point() or set() together can also
* help. (<a href="http://dev.processing.org/bugs/show_bug.cgi?id=1094">Bug 1094</a>)
*
* @webref shape:2d_primitives
* @param x x-coordinate of the point
* @param y y-coordinate of the point
* @param z z-coordinate of the point
*
* @see PGraphics#beginShape()
*/
public void point(float x, float y, float z) {
if (recorder != null) recorder.point(x, y, z);
g.point(x, y, z);
@ -7610,6 +7708,31 @@ public class PApplet extends Applet
}
/**
* Draws a line (a direct path between two points) to the screen.
* The version of <b>line()</b> with four parameters draws the line in 2D.
* To color a line, use the <b>stroke()</b> function. A line cannot be
* filled, therefore the <b>fill()</b> method will not affect the color
* of a line. 2D lines are drawn with a width of one pixel by default,
* but this can be changed with the <b>strokeWeight()</b> function.
* The version with six parameters allows the line to be placed anywhere
* within XYZ space. Drawing this shape in 3D using the <b>z</b> parameter
* requires the P3D or OPENGL parameter in combination with size as shown
* in the above example.
*
* @webref shape:2d_primitives
* @param x1 x-coordinate of the first point
* @param y1 y-coordinate of the first point
* @param z1 z-coordinate of the first point
* @param x2 x-coordinate of the second point
* @param y2 y-coordinate of the second point
* @param z2 z-coordinate of the second point
*
* @see PGraphics#strokeWeight(float)
* @see PGraphics#strokeJoin(int)
* @see PGraphics#strokeCap(int)
* @see PGraphics#beginShape()
*/
public void line(float x1, float y1, float z1,
float x2, float y2, float z2) {
if (recorder != null) recorder.line(x1, y1, z1, x2, y2, z2);
@ -7617,6 +7740,21 @@ public class PApplet extends Applet
}
/**
* A triangle is a plane created by connecting three points. The first two
* arguments specify the first point, the middle two arguments specify
* the second point, and the last two arguments specify the third point.
*
* @webref shape:2d_primitives
* @param x1 x-coordinate of the first point
* @param y1 y-coordinate of the first point
* @param x2 x-coordinate of the second point
* @param y2 y-coordinate of the second point
* @param x3 x-coordinate of the third point
* @param y3 y-coordinate of the third point
*
* @see PApplet#beginShape()
*/
public void triangle(float x1, float y1, float x2, float y2,
float x3, float y3) {
if (recorder != null) recorder.triangle(x1, y1, x2, y2, x3, y3);
@ -7624,6 +7762,24 @@ public class PApplet extends Applet
}
/**
* A quad is a quadrilateral, a four sided polygon. It is similar to
* a rectangle, but the angles between its edges are not constrained
* ninety degrees. The first pair of parameters (x1,y1) sets the
* first vertex and the subsequent pairs should proceed clockwise or
* counter-clockwise around the defined shape.
*
* @webref shape:2d_primitives
* @param x1 x-coordinate of the first corner
* @param y1 y-coordinate of the first corner
* @param x2 x-coordinate of the second corner
* @param y2 y-coordinate of the second corner
* @param x3 x-coordinate of the third corner
* @param y3 y-coordinate of the third corner
* @param x4 x-coordinate of the fourth corner
* @param y4 y-coordinate of the fourth corner
*
*/
public void quad(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4) {
if (recorder != null) recorder.quad(x1, y1, x2, y2, x3, y3, x4, y4);
@ -7637,24 +7793,90 @@ public class PApplet extends Applet
}
/**
* Draws a rectangle to the screen. A rectangle is a four-sided shape with
* every angle at ninety degrees. The first two parameters set the location,
* the third sets the width, and the fourth sets the height. The origin is
* changed with the <b>rectMode()</b> function.
*
* @webref shape:2d_primitives
* @param a x-coordinate of the rectangle
* @param b y-coordinate of the rectangle
* @param c width of the rectangle
* @param d height of the rectangle
*
* @see PGraphics#rectMode(int)
* @see PGraphics#quad(float, float, float, float, float, float, float, float)
*/
public void rect(float a, float b, float c, float d) {
if (recorder != null) recorder.rect(a, b, c, d);
g.rect(a, b, c, d);
}
/**
* The origin of the ellipse is modified by the <b>ellipseMode()</b>
* function. The default configuration is <b>ellipseMode(CENTER)</b>,
* which specifies the location of the ellipse as the center of the shape.
* The RADIUS mode is the same, but the width and height parameters to
* <b>ellipse()</b> specify the radius of the ellipse, rather than the
* diameter. The CORNER mode draws the shape from the upper-left corner
* of its bounding box. The CORNERS mode uses the four parameters to
* <b>ellipse()</b> to set two opposing corners of the ellipse's bounding
* box. The parameter must be written in "ALL CAPS" because Processing
* syntax is case sensitive.
*
* @webref shape:attributes
*
* @param mode Either CENTER, RADIUS, CORNER, or CORNERS.
* @see PApplet#ellipse(float, float, float, float)
*/
public void ellipseMode(int mode) {
if (recorder != null) recorder.ellipseMode(mode);
g.ellipseMode(mode);
}
/**
* Draws an ellipse (oval) in the display window. An ellipse with an equal
* <b>width</b> and <b>height</b> is a circle. The first two parameters set
* the location, the third sets the width, and the fourth sets the height.
* The origin may be changed with the <b>ellipseMode()</b> function.
*
* @webref shape:2d_primitives
* @param a x-coordinate of the ellipse
* @param b y-coordinate of the ellipse
* @param c width of the ellipse
* @param d height of the ellipse
*
* @see PApplet#ellipseMode(int)
*/
public void ellipse(float a, float b, float c, float d) {
if (recorder != null) recorder.ellipse(a, b, c, d);
g.ellipse(a, b, c, d);
}
/**
* Draws an arc in the display window.
* Arcs are drawn along the outer edge of an ellipse defined by the
* <b>x</b>, <b>y</b>, <b>width</b> and <b>height</b> parameters.
* The origin or the arc's ellipse may be changed with the
* <b>ellipseMode()</b> function.
* The <b>start</b> and <b>stop</b> parameters specify the angles
* at which to draw the arc.
*
* @webref shape:2d_primitives
* @param a x-coordinate of the arc's ellipse
* @param b y-coordinate of the arc's ellipse
* @param c width of the arc's ellipse
* @param d height of the arc's ellipse
* @param start angle to start the arc, specified in radians
* @param stop angle to stop the arc, specified in radians
*
* @see PGraphics#ellipseMode(int)
* @see PGraphics#ellipse(float, float, float, float)
*/
public void arc(float a, float b, float c, float d,
float start, float stop) {
if (recorder != null) recorder.arc(a, b, c, d, start, stop);
@ -7662,52 +7884,243 @@ public class PApplet extends Applet
}
/**
* @param size dimension of the box in all dimensions, creates a cube
*/
public void box(float size) {
if (recorder != null) recorder.box(size);
g.box(size);
}
/**
* A box is an extruded rectangle. A box with equal dimension
* on all sides is a cube.
*
* @webref shape:3d_primitives
* @param w dimension of the box in the x-dimension
* @param h dimension of the box in the y-dimension
* @param d dimension of the box in the z-dimension
*
* @see PApplet#sphere(float)
*/
public void box(float w, float h, float d) {
if (recorder != null) recorder.box(w, h, d);
g.box(w, h, d);
}
/**
* @param res number of segments (minimum 3) used per full circle revolution
*/
public void sphereDetail(int res) {
if (recorder != null) recorder.sphereDetail(res);
g.sphereDetail(res);
}
/**
* Controls the detail used to render a sphere by adjusting the number of
* vertices of the sphere mesh. The default resolution is 30, which creates
* a fairly detailed sphere definition with vertices every 360/30 = 12
* degrees. If you're going to render a great number of spheres per frame,
* it is advised to reduce the level of detail using this function.
* The setting stays active until <b>sphereDetail()</b> is called again with
* a new parameter and so should <i>not</i> be called prior to every
* <b>sphere()</b> statement, unless you wish to render spheres with
* different settings, e.g. using less detail for smaller spheres or ones
* further away from the camera. To control the detail of the horizontal
* and vertical resolution independently, use the version of the functions
* with two parameters.
*
* =advanced
* Code for sphereDetail() submitted by toxi [031031].
* Code for enhanced u/v version from davbol [080801].
*
* @webref shape:3d_primitives
* @param ures number of segments used horizontally (longitudinally)
* per full circle revolution
* @param vres number of segments used vertically (latitudinally)
* from top to bottom
*
* @see PGraphics#sphere(float)
*/
/**
* Set the detail level for approximating a sphere. The ures and vres params
* control the horizontal and vertical resolution.
*
*/
public void sphereDetail(int ures, int vres) {
if (recorder != null) recorder.sphereDetail(ures, vres);
g.sphereDetail(ures, vres);
}
/**
* Draw a sphere with radius r centered at coordinate 0, 0, 0.
* A sphere is a hollow ball made from tessellated triangles.
* =advanced
* <P>
* Implementation notes:
* <P>
* cache all the points of the sphere in a static array
* top and bottom are just a bunch of triangles that land
* in the center point
* <P>
* sphere is a series of concentric circles who radii vary
* along the shape, based on, er.. cos or something
* <PRE>
* [toxi 031031] new sphere code. removed all multiplies with
* radius, as scale() will take care of that anyway
*
* [toxi 031223] updated sphere code (removed modulos)
* and introduced sphereAt(x,y,z,r)
* to avoid additional translate()'s on the user/sketch side
*
* [davbol 080801] now using separate sphereDetailU/V
* </PRE>
*
* @webref shape:3d_primitives
* @param r the radius of the sphere
*/
public void sphere(float r) {
if (recorder != null) recorder.sphere(r);
g.sphere(r);
}
/**
* Evalutes quadratic bezier at point t for points a, b, c, d.
* The parameter t varies between 0 and 1. The a and d parameters are the
* on-curve points, b and c are the control points. To make a two-dimensional
* curve, call this function once with the x coordinates and a second time
* with the y coordinates to get the location of a bezier curve at t.
*
* =advanced
* For instance, to convert the following example:<PRE>
* stroke(255, 102, 0);
* line(85, 20, 10, 10);
* line(90, 90, 15, 80);
* stroke(0, 0, 0);
* bezier(85, 20, 10, 10, 90, 90, 15, 80);
*
* // draw it in gray, using 10 steps instead of the default 20
* // this is a slower way to do it, but useful if you need
* // to do things with the coordinates at each step
* stroke(128);
* beginShape(LINE_STRIP);
* for (int i = 0; i <= 10; i++) {
* float t = i / 10.0f;
* float x = bezierPoint(85, 10, 90, 15, t);
* float y = bezierPoint(20, 10, 90, 80, t);
* vertex(x, y);
* }
* endShape();</PRE>
*
* @webref shape:curves
* @param a coordinate of first point on the curve
* @param b coordinate of first control point
* @param c coordinate of second control point
* @param d coordinate of second point on the curve
* @param t value between 0 and 1
*
* @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#bezierVertex(float, float, float, float, float, float)
* @see PGraphics#curvePoint(float, float, float, float, float)
*/
public float bezierPoint(float a, float b, float c, float d, float t) {
return g.bezierPoint(a, b, c, d, t);
}
/**
* Calculates the tangent of a point on a Bezier curve. There is a good
* definition of "tangent" at Wikipedia: <a href="http://en.wikipedia.org/wiki/Tangent" target="new">http://en.wikipedia.org/wiki/Tangent</a>
*
* =advanced
* Code submitted by Dave Bollinger (davol) for release 0136.
*
* @webref shape:curves
* @param a coordinate of first point on the curve
* @param b coordinate of first control point
* @param c coordinate of second control point
* @param d coordinate of second point on the curve
* @param t value between 0 and 1
*
* @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#bezierVertex(float, float, float, float, float, float)
* @see PGraphics#curvePoint(float, float, float, float, float)
*/
public float bezierTangent(float a, float b, float c, float d, float t) {
return g.bezierTangent(a, b, c, d, t);
}
/**
* Sets the resolution at which Beziers display. The default value is 20. This function is only useful when using the P3D or OPENGL renderer as the default (JAVA2D) renderer does not use this information.
*
* @webref shape:curves
* @param detail resolution of the curves
*
* @see PApplet#curve(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PApplet#curveVertex(float, float)
* @see PApplet#curveTightness(float)
*/
public void bezierDetail(int detail) {
if (recorder != null) recorder.bezierDetail(detail);
g.bezierDetail(detail);
}
/**
* Draws a Bezier curve on the screen. These curves are defined by a series
* of anchor and control points. The first two parameters specify the first
* anchor point and the last two parameters specify the other anchor point.
* The middle parameters specify the control points which define the shape
* of the curve. Bezier curves were developed by French engineer Pierre
* Bezier. Using the 3D version of requires rendering with P3D or OPENGL
* (see the Environment reference for more information).
*
* =advanced
* Draw a cubic bezier curve. The first and last points are
* the on-curve points. The middle two are the 'control' points,
* or 'handles' in an application like Illustrator.
* <P>
* Identical to typing:
* <PRE>beginShape();
* vertex(x1, y1);
* bezierVertex(x2, y2, x3, y3, x4, y4);
* endShape();
* </PRE>
* In Postscript-speak, this would be:
* <PRE>moveto(x1, y1);
* curveto(x2, y2, x3, y3, x4, y4);</PRE>
* If you were to try and continue that curve like so:
* <PRE>curveto(x5, y5, x6, y6, x7, y7);</PRE>
* This would be done in processing by adding these statements:
* <PRE>bezierVertex(x5, y5, x6, y6, x7, y7)
* </PRE>
* To draw a quadratic (instead of cubic) curve,
* use the control point twice by doubling it:
* <PRE>bezier(x1, y1, cx, cy, cx, cy, x2, y2);</PRE>
*
* @webref shape:curves
* @param x1 coordinates for the first anchor point
* @param y1 coordinates for the first anchor point
* @param z1 coordinates for the first anchor point
* @param x2 coordinates for the first control point
* @param y2 coordinates for the first control point
* @param z2 coordinates for the first control point
* @param x3 coordinates for the second control point
* @param y3 coordinates for the second control point
* @param z3 coordinates for the second control point
* @param x4 coordinates for the second anchor point
* @param y4 coordinates for the second anchor point
* @param z4 coordinates for the second anchor point
*
* @see PGraphics#bezierVertex(float, float, float, float, float, float)
* @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float)
*/
public void bezier(float x1, float y1,
float x2, float y2,
float x3, float y3,
@ -7726,28 +8139,137 @@ public class PApplet extends Applet
}
/**
* Evalutes the Catmull-Rom curve at point t for points a, b, c, d. The
* parameter t varies between 0 and 1, a and d are points on the curve,
* and b and c are the control points. This can be done once with the x
* coordinates and a second time with the y coordinates to get the
* location of a curve at t.
*
* @webref shape:curves
* @param a coordinate of first point on the curve
* @param b coordinate of second point on the curve
* @param c coordinate of third point on the curve
* @param d coordinate of fourth point on the curve
* @param t value between 0 and 1
*
* @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#curveVertex(float, float)
* @see PGraphics#bezierPoint(float, float, float, float, float)
*/
public float curvePoint(float a, float b, float c, float d, float t) {
return g.curvePoint(a, b, c, d, t);
}
/**
* Calculates the tangent of a point on a Catmull-Rom curve. There is a good definition of "tangent" at Wikipedia: <a href="http://en.wikipedia.org/wiki/Tangent" target="new">http://en.wikipedia.org/wiki/Tangent</a>.
*
* =advanced
* Code thanks to Dave Bollinger (Bug #715)
*
* @webref shape:curves
* @param a coordinate of first point on the curve
* @param b coordinate of first control point
* @param c coordinate of second control point
* @param d coordinate of second point on the curve
* @param t value between 0 and 1
*
* @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#curveVertex(float, float)
* @see PGraphics#curvePoint(float, float, float, float, float)
* @see PGraphics#bezierTangent(float, float, float, float, float)
*/
public float curveTangent(float a, float b, float c, float d, float t) {
return g.curveTangent(a, b, c, d, t);
}
/**
* Sets the resolution at which curves display. The default value is 20.
* This function is only useful when using the P3D or OPENGL renderer as
* the default (JAVA2D) renderer does not use this information.
*
* @webref shape:curves
* @param detail resolution of the curves
*
* @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#curveVertex(float, float)
* @see PGraphics#curveTightness(float)
*/
public void curveDetail(int detail) {
if (recorder != null) recorder.curveDetail(detail);
g.curveDetail(detail);
}
/**
* Modifies the quality of forms created with <b>curve()</b> and
*<b>curveVertex()</b>. The parameter <b>squishy</b> determines how the
* curve fits to the vertex points. The value 0.0 is the default value for
* <b>squishy</b> (this value defines the curves to be Catmull-Rom splines)
* and the value 1.0 connects all the points with straight lines.
* Values within the range -5.0 and 5.0 will deform the curves but
* will leave them recognizable and as values increase in magnitude,
* they will continue to deform.
*
* @webref shape:curves
* @param tightness amount of deformation from the original vertices
*
* @see PGraphics#curve(float, float, float, float, float, float, float, float, float, float, float, float)
* @see PGraphics#curveVertex(float, float)
*
*/
public void curveTightness(float tightness) {
if (recorder != null) recorder.curveTightness(tightness);
g.curveTightness(tightness);
}
/**
* Draws a curved line on the screen. The first and second parameters
* specify the beginning control point and the last two parameters specify
* the ending control point. The middle parameters specify the start and
* stop of the curve. Longer curves can be created by putting a series of
* <b>curve()</b> functions together or using <b>curveVertex()</b>.
* An additional function called <b>curveTightness()</b> provides control
* for the visual quality of the curve. The <b>curve()</b> function is an
* implementation of Catmull-Rom splines. Using the 3D version of requires
* rendering with P3D or OPENGL (see the Environment reference for more
* information).
*
* =advanced
* As of revision 0070, this function no longer doubles the first
* and last points. The curves are a bit more boring, but it's more
* mathematically correct, and properly mirrored in curvePoint().
* <P>
* Identical to typing out:<PRE>
* beginShape();
* curveVertex(x1, y1);
* curveVertex(x2, y2);
* curveVertex(x3, y3);
* curveVertex(x4, y4);
* endShape();
* </PRE>
*
* @webref shape:curves
* @param x1 coordinates for the beginning control point
* @param y1 coordinates for the beginning control point
* @param z1 coordinates for the beginning control point
* @param x2 coordinates for the first point
* @param y2 coordinates for the first point
* @param z2 coordinates for the first point
* @param x3 coordinates for the second point
* @param y3 coordinates for the second point
* @param z3 coordinates for the second point
* @param x4 coordinates for the ending control point
* @param y4 coordinates for the ending control point
* @param z4 coordinates for the ending control point
*
* @see PGraphics#curveVertex(float, float)
* @see PGraphics#curveTightness(float)
* @see PGraphics#bezier(float, float, float, float, float, float, float, float, float, float, float, float)
*/
public void curve(float x1, float y1,
float x2, float y2,
float x3, float y3,
@ -7766,18 +8288,46 @@ public class PApplet extends Applet
}
/**
* If true in PImage, use bilinear interpolation for copy()
* operations. When inherited by PGraphics, also controls shapes.
*/
public void smooth() {
if (recorder != null) recorder.smooth();
g.smooth();
}
/**
* Disable smoothing. See smooth().
*/
public void noSmooth() {
if (recorder != null) recorder.noSmooth();
g.noSmooth();
}
/**
* Modifies the location from which images draw. The default mode is
* <b>imageMode(CORNER)</b>, which specifies the location to be the
* upper-left corner and uses the fourth and fifth parameters of
* <b>image()</b> to set the image's width and height. The syntax
* <b>imageMode(CORNERS)</b> uses the second and third parameters of
* <b>image()</b> to set the location of one corner of the image and
* uses the fourth and fifth parameters to set the opposite corner.
* Use <b>imageMode(CENTER)</b> to draw images centered at the given
* x and y position.
* <br><br>The parameter to <b>imageMode()</b> must be written in
* ALL CAPS because Processing syntax is case sensitive.
*
* @webref image:loading_displaying
* @param mode Either CORNER, CORNERS, or CENTER
*
* @see processing.core.PApplet#loadImage(String, String)
* @see processing.core.PImage
* @see processing.core.PApplet#image(PImage, float, float, float, float)
* @see processing.core.PGraphics#background(float, float, float, float)
*/
public void imageMode(int mode) {
if (recorder != null) recorder.imageMode(mode);
g.imageMode(mode);
@ -7790,12 +8340,50 @@ public class PApplet extends Applet
}
/**
* Displays images to the screen. The images must be in the sketch's "data"
* directory to load correctly. Select "Add file..." from the "Sketch" menu
* to add the image. Processing currently works with GIF, JPEG, and Targa
* images. The color of an image may be modified with the <b>tint()</b>
* function and if a GIF has transparency, it will maintain its transparency.
* The <b>img</b> parameter specifies the image to display and the <b>x</b>
* and <b>y</b> parameters define the location of the image from its
* upper-left corner. The image is displayed at its original size unless
* the <b>width</b> and <b>height</b> parameters specify a different size.
* The <b>imageMode()</b> function changes the way the parameters work.
* A call to <b>imageMode(CORNERS)</b> will change the width and height
* parameters to define the x and y values of the opposite corner of the
* image.
*
* =advanced
* Starting with release 0124, when using the default (JAVA2D) renderer,
* smooth() will also improve image quality of resized images.
*
* @webref image:loading_displaying
* @param image the image to display
* @param x x-coordinate of the image
* @param y y-coordinate of the image
* @param c width to display the image
* @param d height to display the image
*
* @see processing.core.PApplet#loadImage(String, String)
* @see processing.core.PImage
* @see processing.core.PGraphics#imageMode(int)
* @see processing.core.PGraphics#tint(float)
* @see processing.core.PGraphics#background(float, float, float, float)
* @see processing.core.PGraphics#alpha(int)
*/
public void image(PImage image, float x, float y, float c, float d) {
if (recorder != null) recorder.image(image, x, y, c, d);
g.image(image, x, y, c, d);
}
/**
* Draw an image(), also specifying u/v coordinates.
* In this method, the u, v coordinates are always based on image space
* location, regardless of the current textureMode().
*/
public void image(PImage image,
float a, float b, float c, float d,
int u1, int v1, int u2, int v2) {
@ -7804,6 +8392,26 @@ public class PApplet extends Applet
}
/**
* Modifies the location from which shapes draw.
* The default mode is <b>shapeMode(CORNER)</b>, which specifies the
* location to be the upper left corner of the shape and uses the third
* and fourth parameters of <b>shape()</b> to specify the width and height.
* The syntax <b>shapeMode(CORNERS)</b> uses the first and second parameters
* of <b>shape()</b> to set the location of one corner and uses the third
* and fourth parameters to set the opposite corner.
* The syntax <b>shapeMode(CENTER)</b> draws the shape from its center point
* and uses the third and forth parameters of <b>shape()</b> to specify the
* width and height.
* The parameter must be written in "ALL CAPS" because Processing syntax
* is case sensitive.
*
* @param mode One of CORNER, CORNERS, CENTER
*
* @webref shape:loading_displaying
* @see PGraphics#shape(PShape)
* @see PGraphics#rectMode(int)
*/
public void shapeMode(int mode) {
if (recorder != null) recorder.shapeMode(mode);
g.shapeMode(mode);
@ -7816,64 +8424,138 @@ public class PApplet extends Applet
}
/**
* Convenience method to draw at a particular location.
*/
public void shape(PShape shape, float x, float y) {
if (recorder != null) recorder.shape(shape, x, y);
g.shape(shape, x, y);
}
/**
* Displays shapes to the screen. The shapes must be in the sketch's "data"
* directory to load correctly. Select "Add file..." from the "Sketch" menu
* to add the shape.
* Processing currently works with SVG shapes only.
* The <b>sh</b> parameter specifies the shape to display and the <b>x</b>
* and <b>y</b> parameters define the location of the shape from its
* upper-left corner.
* The shape is displayed at its original size unless the <b>width</b>
* and <b>height</b> parameters specify a different size.
* The <b>shapeMode()</b> function changes the way the parameters work.
* A call to <b>shapeMode(CORNERS)</b>, for example, will change the width
* and height parameters to define the x and y values of the opposite corner
* of the shape.
* <br><br>
* Note complex shapes may draw awkwardly with P2D, P3D, and OPENGL. Those
* renderers do not yet support shapes that have holes or complicated breaks.
*
* @param shape
* @param x x-coordinate of the shape
* @param y y-coordinate of the shape
* @param c width to display the shape
* @param d height to display the shape
*
* @webref shape:loading_displaying
* @see PShape
* @see PGraphics#loadShape(String)
* @see PGraphics#shapeMode(int)
*/
public void shape(PShape shape, float x, float y, float c, float d) {
if (recorder != null) recorder.shape(shape, x, y, c, d);
g.shape(shape, x, y, c, d);
}
/**
* Sets the alignment of the text to one of LEFT, CENTER, or RIGHT.
* This will also reset the vertical text alignment to BASELINE.
*/
public void textAlign(int align) {
if (recorder != null) recorder.textAlign(align);
g.textAlign(align);
}
/**
* Sets the horizontal and vertical alignment of the text. The horizontal
* alignment can be one of LEFT, CENTER, or RIGHT. The vertical alignment
* can be TOP, BOTTOM, CENTER, or the BASELINE (the default).
*/
public void textAlign(int alignX, int alignY) {
if (recorder != null) recorder.textAlign(alignX, alignY);
g.textAlign(alignX, alignY);
}
/**
* Returns the ascent of the current font at the current size.
* This is a method, rather than a variable inside the PGraphics object
* because it requires calculation.
*/
public float textAscent() {
return g.textAscent();
}
/**
* Returns the descent of the current font at the current size.
* This is a method, rather than a variable inside the PGraphics object
* because it requires calculation.
*/
public float textDescent() {
return g.textDescent();
}
/**
* Sets the current font. The font's size will be the "natural"
* size of this font (the size that was set when using "Create Font").
* The leading will also be reset.
*/
public void textFont(PFont which) {
if (recorder != null) recorder.textFont(which);
g.textFont(which);
}
/**
* Useful function to set the font and size at the same time.
*/
public void textFont(PFont which, float size) {
if (recorder != null) recorder.textFont(which, size);
g.textFont(which, size);
}
/**
* Set the text leading to a specific value. If using a custom
* value for the text leading, you'll have to call textLeading()
* again after any calls to textSize().
*/
public void textLeading(float leading) {
if (recorder != null) recorder.textLeading(leading);
g.textLeading(leading);
}
/**
* Sets the text rendering/placement to be either SCREEN (direct
* to the screen, exact coordinates, only use the font's original size)
* or MODEL (the default, where text is manipulated by translate() and
* can have a textSize). The text size cannot be set when using
* textMode(SCREEN), because it uses the pixels directly from the font.
*/
public void textMode(int mode) {
if (recorder != null) recorder.textMode(mode);
g.textMode(mode);
}
/**
* Sets the text size, also resets the value for the leading.
*/
public void textSize(float size) {
if (recorder != null) recorder.textSize(size);
g.textSize(size);
@ -7885,52 +8567,87 @@ public class PApplet extends Applet
}
/**
* Return the width of a line of text. If the text has multiple
* lines, this returns the length of the longest line.
*/
public float textWidth(String str) {
return g.textWidth(str);
}
/**
* TODO not sure if this stays...
*/
public float textWidth(char[] chars, int start, int length) {
return g.textWidth(chars, start, length);
}
/**
* Write text where we just left off.
*/
public void text(char c) {
if (recorder != null) recorder.text(c);
g.text(c);
}
/**
* Draw a single character on screen.
* Extremely slow when used with textMode(SCREEN) and Java 2D,
* because loadPixels has to be called first and updatePixels last.
*/
public void text(char c, float x, float y) {
if (recorder != null) recorder.text(c, x, y);
g.text(c, x, y);
}
/**
* Draw a single character on screen (with a z coordinate)
*/
public void text(char c, float x, float y, float z) {
if (recorder != null) recorder.text(c, x, y, z);
g.text(c, x, y, z);
}
/**
* Write text where we just left off.
*/
public void text(String str) {
if (recorder != null) recorder.text(str);
g.text(str);
}
/**
* Draw a chunk of text.
* Newlines that are \n (Unix newline or linefeed char, ascii 10)
* are honored, but \r (carriage return, Windows and Mac OS) are
* ignored.
*/
public void text(String str, float x, float y) {
if (recorder != null) recorder.text(str, x, y);
g.text(str, x, y);
}
/**
* Method to draw text from an array of chars. This method will usually be
* more efficient than drawing from a String object, because the String will
* not be converted to a char array before drawing.
*/
public void text(char[] chars, int start, int stop, float x, float y) {
if (recorder != null) recorder.text(chars, start, stop, x, y);
g.text(chars, start, stop, x, y);
}
/**
* Same as above but with a z coordinate.
*/
public void text(String str, float x, float y, float z) {
if (recorder != null) recorder.text(str, x, y, z);
g.text(str, x, y, z);
@ -7944,6 +8661,19 @@ public class PApplet extends Applet
}
/**
* Draw text in a box that is constrained to a particular size.
* The current rectMode() determines what the coordinates mean
* (whether x1/y1/x2/y2 or x/y/w/h).
* <P/>
* Note that the x,y coords of the start of the box
* will align with the *ascent* of the text, not the baseline,
* as is the case for the other text() functions.
* <P/>
* Newlines that are \n (Unix newline or linefeed char, ascii 10)
* are honored, and \r (carriage return, Windows and Mac OS) are
* ignored.
*/
public void text(String str, float x1, float y1, float x2, float y2) {
if (recorder != null) recorder.text(str, x1, y1, x2, y2);
g.text(str, x1, y1, x2, y2);
@ -7968,6 +8698,13 @@ public class PApplet extends Applet
}
/**
* This does a basic number formatting, to avoid the
* generally ugly appearance of printing floats.
* Users who want more control should use their own nf() cmmand,
* or if they want the long, ugly version of float,
* use String.valueOf() to convert the float to a String first.
*/
public void text(float num, float x, float y) {
if (recorder != null) recorder.text(num, x, y);
g.text(num, x, y);
@ -7980,78 +8717,131 @@ public class PApplet extends Applet
}
/**
* Push a copy of the current transformation matrix onto the stack.
*/
public void pushMatrix() {
if (recorder != null) recorder.pushMatrix();
g.pushMatrix();
}
/**
* Replace the current transformation matrix with the top of the stack.
*/
public void popMatrix() {
if (recorder != null) recorder.popMatrix();
g.popMatrix();
}
/**
* Translate in X and Y.
*/
public void translate(float tx, float ty) {
if (recorder != null) recorder.translate(tx, ty);
g.translate(tx, ty);
}
/**
* Translate in X, Y, and Z.
*/
public void translate(float tx, float ty, float tz) {
if (recorder != null) recorder.translate(tx, ty, tz);
g.translate(tx, ty, tz);
}
/**
* Two dimensional rotation.
*
* Same as rotateZ (this is identical to a 3D rotation along the z-axis)
* but included for clarity. It'd be weird for people drawing 2D graphics
* to be using rotateZ. And they might kick our a-- for the confusion.
*
* <A HREF="http://www.xkcd.com/c184.html">Additional background</A>.
*/
public void rotate(float angle) {
if (recorder != null) recorder.rotate(angle);
g.rotate(angle);
}
/**
* Rotate around the X axis.
*/
public void rotateX(float angle) {
if (recorder != null) recorder.rotateX(angle);
g.rotateX(angle);
}
/**
* Rotate around the Y axis.
*/
public void rotateY(float angle) {
if (recorder != null) recorder.rotateY(angle);
g.rotateY(angle);
}
/**
* Rotate around the Z axis.
*
* The functions rotate() and rotateZ() are identical, it's just that it make
* sense to have rotate() and then rotateX() and rotateY() when using 3D;
* nor does it make sense to use a function called rotateZ() if you're only
* doing things in 2D. so we just decided to have them both be the same.
*/
public void rotateZ(float angle) {
if (recorder != null) recorder.rotateZ(angle);
g.rotateZ(angle);
}
/**
* Rotate about a vector in space. Same as the glRotatef() function.
*/
public void rotate(float angle, float vx, float vy, float vz) {
if (recorder != null) recorder.rotate(angle, vx, vy, vz);
g.rotate(angle, vx, vy, vz);
}
/**
* Scale in all dimensions.
*/
public void scale(float s) {
if (recorder != null) recorder.scale(s);
g.scale(s);
}
/**
* Scale in X and Y. Equivalent to scale(sx, sy, 1).
*
* Not recommended for use in 3D, because the z-dimension is just
* scaled by 1, since there's no way to know what else to scale it by.
*/
public void scale(float sx, float sy) {
if (recorder != null) recorder.scale(sx, sy);
g.scale(sx, sy);
}
/**
* Scale in X, Y, and Z.
*/
public void scale(float x, float y, float z) {
if (recorder != null) recorder.scale(x, y, z);
g.scale(x, y, z);
}
/**
* Set the current transformation matrix to identity.
*/
public void resetMatrix() {
if (recorder != null) recorder.resetMatrix();
g.resetMatrix();
@ -8070,6 +8860,9 @@ public class PApplet extends Applet
}
/**
* Apply a 3x2 affine transformation matrix.
*/
public void applyMatrix(float n00, float n01, float n02,
float n10, float n11, float n12) {
if (recorder != null) recorder.applyMatrix(n00, n01, n02, n10, n11, n12);
@ -8083,6 +8876,9 @@ public class PApplet extends Applet
}
/**
* Apply a 4x4 transformation matrix.
*/
public void applyMatrix(float n00, float n01, float n02, float n03,
float n10, float n11, float n12, float n13,
float n20, float n21, float n22, float n23,
@ -8097,34 +8893,54 @@ public class PApplet extends Applet
}
/**
* Copy the current transformation matrix into the specified target.
* Pass in null to create a new matrix.
*/
public PMatrix2D getMatrix(PMatrix2D target) {
return g.getMatrix(target);
}
/**
* Copy the current transformation matrix into the specified target.
* Pass in null to create a new matrix.
*/
public PMatrix3D getMatrix(PMatrix3D target) {
return g.getMatrix(target);
}
/**
* Set the current transformation matrix to the contents of another.
*/
public void setMatrix(PMatrix source) {
if (recorder != null) recorder.setMatrix(source);
g.setMatrix(source);
}
/**
* Set the current transformation to the contents of the specified source.
*/
public void setMatrix(PMatrix2D source) {
if (recorder != null) recorder.setMatrix(source);
g.setMatrix(source);
}
/**
* Set the current transformation to the contents of the specified source.
*/
public void setMatrix(PMatrix3D source) {
if (recorder != null) recorder.setMatrix(source);
g.setMatrix(source);
}
/**
* Print the current model (or "transformation") matrix.
*/
public void printMatrix() {
if (recorder != null) recorder.printMatrix();
g.printMatrix();
@ -8203,41 +9019,91 @@ public class PApplet extends Applet
}
/**
* Given an x and y coordinate, returns the x position of where
* that point would be placed on screen, once affected by translate(),
* scale(), or any other transformations.
*/
public float screenX(float x, float y) {
return g.screenX(x, y);
}
/**
* Given an x and y coordinate, returns the y position of where
* that point would be placed on screen, once affected by translate(),
* scale(), or any other transformations.
*/
public float screenY(float x, float y) {
return g.screenY(x, y);
}
/**
* Maps a three dimensional point to its placement on-screen.
* <P>
* Given an (x, y, z) coordinate, returns the x position of where
* that point would be placed on screen, once affected by translate(),
* scale(), or any other transformations.
*/
public float screenX(float x, float y, float z) {
return g.screenX(x, y, z);
}
/**
* Maps a three dimensional point to its placement on-screen.
* <P>
* Given an (x, y, z) coordinate, returns the y position of where
* that point would be placed on screen, once affected by translate(),
* scale(), or any other transformations.
*/
public float screenY(float x, float y, float z) {
return g.screenY(x, y, z);
}
/**
* Maps a three dimensional point to its placement on-screen.
* <P>
* Given an (x, y, z) coordinate, returns its z value.
* This value can be used to determine if an (x, y, z) coordinate
* is in front or in back of another (x, y, z) coordinate.
* The units are based on how the zbuffer is set up, and don't
* relate to anything "real". They're only useful for in
* comparison to another value obtained from screenZ(),
* or directly out of the zbuffer[].
*/
public float screenZ(float x, float y, float z) {
return g.screenZ(x, y, z);
}
/**
* Returns the model space x value for an x, y, z coordinate.
* <P>
* This will give you a coordinate after it has been transformed
* by translate(), rotate(), and camera(), but not yet transformed
* by the projection matrix. For instance, his can be useful for
* figuring out how points in 3D space relate to the edge
* coordinates of a shape.
*/
public float modelX(float x, float y, float z) {
return g.modelX(x, y, z);
}
/**
* Returns the model space y value for an x, y, z coordinate.
*/
public float modelY(float x, float y, float z) {
return g.modelY(x, y, z);
}
/**
* Returns the model space z value for an x, y, z coordinate.
*/
public float modelZ(float x, float y, float z) {
return g.modelZ(x, y, z);
}
@ -8279,12 +9145,26 @@ public class PApplet extends Applet
}
/**
* Disables drawing the stroke (outline). If both <b>noStroke()</b> and
* <b>noFill()</b> are called, no shapes will be drawn to the screen.
*
* @webref color:setting
*
* @see PGraphics#stroke(float, float, float, float)
*/
public void noStroke() {
if (recorder != null) recorder.noStroke();
g.noStroke();
}
/**
* Set the tint to either a grayscale or ARGB value.
* See notes attached to the fill() function.
* @param rgb color value in hexadecimal notation
* (i.e. #FFCC00 or 0xFFFFCC00) or any value of the color datatype
*/
public void stroke(int rgb) {
if (recorder != null) recorder.stroke(rgb);
g.stroke(rgb);
@ -8297,6 +9177,10 @@ public class PApplet extends Applet
}
/**
*
* @param gray specifies a value between white and black
*/
public void stroke(float gray) {
if (recorder != null) recorder.stroke(gray);
g.stroke(gray);
@ -8315,30 +9199,70 @@ public class PApplet extends Applet
}
/**
* Sets the color used to draw lines and borders around shapes. This color
* is either specified in terms of the RGB or HSB color depending on the
* current <b>colorMode()</b> (the default color space is RGB, with each
* value in the range from 0 to 255).
* <br><br>When using hexadecimal notation to specify a color, use "#" or
* "0x" before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six
* digits to specify a color (the way colors are specified in HTML and CSS).
* When using the hexadecimal notation starting with "0x", the hexadecimal
* value must be specified with eight characters; the first two characters
* define the alpha component and the remainder the red, green, and blue
* components.
* <br><br>The value for the parameter "gray" must be less than or equal
* to the current maximum value as specified by <b>colorMode()</b>.
* The default maximum value is 255.
*
* @webref color:setting
* @param alpha opacity of the stroke
* @param x red or hue value (depending on the current color mode)
* @param y green or saturation value (depending on the current color mode)
* @param z blue or brightness value (depending on the current color mode)
*/
public void stroke(float x, float y, float z, float a) {
if (recorder != null) recorder.stroke(x, y, z, a);
g.stroke(x, y, z, a);
}
/**
* Removes the current fill value for displaying images and reverts to displaying images with their original hues.
*
* @webref image:loading_displaying
* @see processing.core.PGraphics#tint(float, float, float, float)
* @see processing.core.PGraphics#image(PImage, float, float, float, float)
*/
public void noTint() {
if (recorder != null) recorder.noTint();
g.noTint();
}
/**
* Set the tint to either a grayscale or ARGB value.
*/
public void tint(int rgb) {
if (recorder != null) recorder.tint(rgb);
g.tint(rgb);
}
/**
* @param rgb color value in hexadecimal notation
* (i.e. #FFCC00 or 0xFFFFCC00) or any value of the color datatype
* @param alpha opacity of the image
*/
public void tint(int rgb, float alpha) {
if (recorder != null) recorder.tint(rgb, alpha);
g.tint(rgb, alpha);
}
/**
* @param gray any valid number
*/
public void tint(float gray) {
if (recorder != null) recorder.tint(gray);
g.tint(gray);
@ -8357,18 +9281,60 @@ public class PApplet extends Applet
}
/**
* Sets the fill value for displaying images. Images can be tinted to
* specified colors or made transparent by setting the alpha.
* <br><br>To make an image transparent, but not change it's color,
* use white as the tint color and specify an alpha value. For instance,
* tint(255, 128) will make an image 50% transparent (unless
* <b>colorMode()</b> has been used).
*
* <br><br>When using hexadecimal notation to specify a color, use "#" or
* "0x" before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six
* digits to specify a color (the way colors are specified in HTML and CSS).
* When using the hexadecimal notation starting with "0x", the hexadecimal
* value must be specified with eight characters; the first two characters
* define the alpha component and the remainder the red, green, and blue
* components.
* <br><br>The value for the parameter "gray" must be less than or equal
* to the current maximum value as specified by <b>colorMode()</b>.
* The default maximum value is 255.
* <br><br>The tint() method is also used to control the coloring of
* textures in 3D.
*
* @webref image:loading_displaying
* @param x red or hue value
* @param y green or saturation value
* @param z blue or brightness value
*
* @see processing.core.PGraphics#noTint()
* @see processing.core.PGraphics#image(PImage, float, float, float, float)
*/
public void tint(float x, float y, float z, float a) {
if (recorder != null) recorder.tint(x, y, z, a);
g.tint(x, y, z, a);
}
/**
* Disables filling geometry. If both <b>noStroke()</b> and <b>noFill()</b>
* are called, no shapes will be drawn to the screen.
*
* @webref color:setting
*
* @see PGraphics#fill(float, float, float, float)
*
*/
public void noFill() {
if (recorder != null) recorder.noFill();
g.noFill();
}
/**
* Set the fill to either a grayscale value or an ARGB int.
* @param rgb color value in hexadecimal notation (i.e. #FFCC00 or 0xFFFFCC00) or any value of the color datatype
*/
public void fill(int rgb) {
if (recorder != null) recorder.fill(rgb);
g.fill(rgb);
@ -8381,6 +9347,9 @@ public class PApplet extends Applet
}
/**
* @param gray number specifying value between white and black
*/
public void fill(float gray) {
if (recorder != null) recorder.fill(gray);
g.fill(gray);
@ -8399,6 +9368,24 @@ public class PApplet extends Applet
}
/**
* Sets the color used to fill shapes. For example, if you run <b>fill(204, 102, 0)</b>, all subsequent shapes will be filled with orange. This color is either specified in terms of the RGB or HSB color depending on the current <b>colorMode()</b> (the default color space is RGB, with each value in the range from 0 to 255).
* <br><br>When using hexadecimal notation to specify a color, use "#" or "0x" before the values (e.g. #CCFFAA, 0xFFCCFFAA). The # syntax uses six digits to specify a color (the way colors are specified in HTML and CSS). When using the hexadecimal notation starting with "0x", the hexadecimal value must be specified with eight characters; the first two characters define the alpha component and the remainder the red, green, and blue components.
* <br><br>The value for the parameter "gray" must be less than or equal to the current maximum value as specified by <b>colorMode()</b>. The default maximum value is 255.
* <br><br>To change the color of an image (or a texture), use tint().
*
* @webref color:setting
* @param x red or hue value
* @param y green or saturation value
* @param z blue or brightness value
* @param alpha opacity of the fill
*
* @see PGraphics#noFill()
* @see PGraphics#stroke(float)
* @see PGraphics#tint(float)
* @see PGraphics#background(float, float, float, float)
* @see PGraphics#colorMode(int, float, float, float, float)
*/
public void fill(float x, float y, float z, float a) {
if (recorder != null) recorder.fill(x, y, z, a);
g.fill(x, y, z, a);
@ -8525,48 +9512,119 @@ public class PApplet extends Applet
}
/**
* Set the background to a gray or ARGB color.
* <p>
* For the main drawing surface, the alpha value will be ignored. However,
* alpha can be used on PGraphics objects from createGraphics(). This is
* the only way to set all the pixels partially transparent, for instance.
* <p>
* Note that background() should be called before any transformations occur,
* because some implementations may require the current transformation matrix
* to be identity before drawing.
*
* @param rgb color value in hexadecimal notation (i.e. #FFCC00 or 0xFFFFCC00)<br/>or any value of the color datatype
*/
public void background(int rgb) {
if (recorder != null) recorder.background(rgb);
g.background(rgb);
}
/**
* See notes about alpha in background(x, y, z, a).
*/
public void background(int rgb, float alpha) {
if (recorder != null) recorder.background(rgb, alpha);
g.background(rgb, alpha);
}
/**
* Set the background to a grayscale value, based on the
* current colorMode.
*/
public void background(float gray) {
if (recorder != null) recorder.background(gray);
g.background(gray);
}
/**
* See notes about alpha in background(x, y, z, a).
* @param gray specifies a value between white and black
* @param alpha opacity of the background
*/
public void background(float gray, float alpha) {
if (recorder != null) recorder.background(gray, alpha);
g.background(gray, alpha);
}
/**
* Set the background to an r, g, b or h, s, b value,
* based on the current colorMode.
*/
public void background(float x, float y, float z) {
if (recorder != null) recorder.background(x, y, z);
g.background(x, y, z);
}
/**
* The <b>background()</b> function sets the color used for the background of the Processing window. The default background is light gray. In the <b>draw()</b> function, the background color is used to clear the display window at the beginning of each frame.
* <br><br>An image can also be used as the background for a sketch, however its width and height must be the same size as the sketch window. To resize an image 'b' to the size of the sketch window, use b.resize(width, height).
* <br><br>Images used as background will ignore the current tint() setting.
* <br><br>It is not possible to use transparency (alpha) in background colors with the main drawing surface, however they will work properly with <b>createGraphics</b>.
*
* =advanced
* <p>Clear the background with a color that includes an alpha value. This can
* only be used with objects created by createGraphics(), because the main
* drawing surface cannot be set transparent.</p>
* <p>It might be tempting to use this function to partially clear the screen
* on each frame, however that's not how this function works. When calling
* background(), the pixels will be replaced with pixels that have that level
* of transparency. To do a semi-transparent overlay, use fill() with alpha
* and draw a rectangle.</p>
*
* @webref color:setting
* @param x red or hue value (depending on the current color mode)
* @param y green or saturation value (depending on the current color mode)
* @param z blue or brightness value (depending on the current color mode)
*
* @see PGraphics#stroke(float)
* @see PGraphics#fill(float)
* @see PGraphics#tint(float)
* @see PGraphics#colorMode(int)
*/
public void background(float x, float y, float z, float a) {
if (recorder != null) recorder.background(x, y, z, a);
g.background(x, y, z, a);
}
/**
* Takes an RGB or ARGB image and sets it as the background.
* The width and height of the image must be the same size as the sketch.
* Use image.resize(width, height) to make short work of such a task.
* <P>
* Note that even if the image is set as RGB, the high 8 bits of each pixel
* should be set opaque (0xFF000000), because the image data will be copied
* directly to the screen, and non-opaque background images may have strange
* behavior. Using image.filter(OPAQUE) will handle this easily.
* <P>
* When using 3D, this will also clear the zbuffer (if it exists).
*/
public void background(PImage image) {
if (recorder != null) recorder.background(image);
g.background(image);
}
/**
* @param mode Either RGB or HSB, corresponding to Red/Green/Blue and Hue/Saturation/Brightness
* @param max range for all color elements
*/
public void colorMode(int mode) {
if (recorder != null) recorder.colorMode(mode);
g.colorMode(mode);
@ -8579,12 +9637,34 @@ public class PApplet extends Applet
}
/**
* Set the colorMode and the maximum values for (r, g, b)
* or (h, s, b).
* <P>
* Note that this doesn't set the maximum for the alpha value,
* which might be confusing if for instance you switched to
* <PRE>colorMode(HSB, 360, 100, 100);</PRE>
* because the alpha values were still between 0 and 255.
*/
public void colorMode(int mode, float maxX, float maxY, float maxZ) {
if (recorder != null) recorder.colorMode(mode, maxX, maxY, maxZ);
g.colorMode(mode, maxX, maxY, maxZ);
}
/**
* Changes the way Processing interprets color data. By default, the parameters for <b>fill()</b>, <b>stroke()</b>, <b>background()</b>, and <b>color()</b> are defined by values between 0 and 255 using the RGB color model. The <b>colorMode()</b> function is used to change the numerical range used for specifying colors and to switch color systems. For example, calling <b>colorMode(RGB, 1.0)</b> will specify that values are specified between 0 and 1. The limits for defining colors are altered by setting the parameters range1, range2, range3, and range 4.
*
* @webref color:setting
* @param maxX range for the red or hue depending on the current color mode
* @param maxY range for the green or saturation depending on the current color mode
* @param maxZ range for the blue or brightness depending on the current color mode
* @param maxA range for the alpha
*
* @see PGraphics#background(float)
* @see PGraphics#fill(float)
* @see PGraphics#stroke(float)
*/
public void colorMode(int mode,
float maxX, float maxY, float maxZ, float maxA) {
if (recorder != null) recorder.colorMode(mode, maxX, maxY, maxZ, maxA);
@ -8592,106 +9672,310 @@ public class PApplet extends Applet
}
/**
* Extracts the alpha value from a color.
*
* @webref color:creating_reading
* @param what any value of the color datatype
*/
public final float alpha(int what) {
return g.alpha(what);
}
/**
* Extracts the red value from a color, scaled to match current <b>colorMode()</b>. This value is always returned as a float so be careful not to assign it to an int value.<br><br>The red() function is easy to use and undestand, but is slower than another technique. To achieve the same results when working in <b>colorMode(RGB, 255)</b>, but with greater speed, use the &gt;&gt; (right shift) operator with a bit mask. For example, the following two lines of code are equivalent:<br><pre>float r1 = red(myColor);<br>float r2 = myColor &gt;&gt; 16 &amp; 0xFF;</pre>
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#green(int)
* @see PGraphics#blue(int)
* @see PGraphics#hue(int)
* @see PGraphics#saturation(int)
* @see PGraphics#brightness(int)
* @ref rightshift
*/
public final float red(int what) {
return g.red(what);
}
/**
* Extracts the green value from a color, scaled to match current <b>colorMode()</b>. This value is always returned as a float so be careful not to assign it to an int value.<br><br>The <b>green()</b> function is easy to use and undestand, but is slower than another technique. To achieve the same results when working in <b>colorMode(RGB, 255)</b>, but with greater speed, use the &gt;&gt; (right shift) operator with a bit mask. For example, the following two lines of code are equivalent:<br><pre>float r1 = green(myColor);<br>float r2 = myColor &gt;&gt; 8 &amp; 0xFF;</pre>
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#red(int)
* @see PGraphics#blue(int)
* @see PGraphics#hue(int)
* @see PGraphics#saturation(int)
* @see PGraphics#brightness(int)
* @ref rightshift
*/
public final float green(int what) {
return g.green(what);
}
/**
* Extracts the blue value from a color, scaled to match current <b>colorMode()</b>. This value is always returned as a float so be careful not to assign it to an int value.<br><br>The <b>blue()</b> function is easy to use and undestand, but is slower than another technique. To achieve the same results when working in <b>colorMode(RGB, 255)</b>, but with greater speed, use a bit mask to remove the other color components. For example, the following two lines of code are equivalent:<br><pre>float r1 = blue(myColor);<br>float r2 = myColor &amp; 0xFF;</pre>
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#red(int)
* @see PGraphics#green(int)
* @see PGraphics#hue(int)
* @see PGraphics#saturation(int)
* @see PGraphics#brightness(int)
*/
public final float blue(int what) {
return g.blue(what);
}
/**
* Extracts the hue value from a color.
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#red(int)
* @see PGraphics#green(int)
* @see PGraphics#blue(int)
* @see PGraphics#saturation(int)
* @see PGraphics#brightness(int)
*/
public final float hue(int what) {
return g.hue(what);
}
/**
* Extracts the saturation value from a color.
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#red(int)
* @see PGraphics#green(int)
* @see PGraphics#blue(int)
* @see PGraphics#hue(int)
* @see PGraphics#brightness(int)
*/
public final float saturation(int what) {
return g.saturation(what);
}
/**
* Extracts the brightness value from a color.
*
*
* @webref color:creating_reading
* @param what any value of the color datatype
*
* @see PGraphics#red(int)
* @see PGraphics#green(int)
* @see PGraphics#blue(int)
* @see PGraphics#hue(int)
* @see PGraphics#saturation(int)
*/
public final float brightness(int what) {
return g.brightness(what);
}
/**
* Calculates a color or colors between two color at a specific increment. The <b>amt</b> parameter is the amount to interpolate between the two values where 0.0 equal to the first point, 0.1 is very near the first point, 0.5 is half-way in between, etc.
*
* @webref color:creating_reading
* @param c1 interpolate from this color
* @param c2 interpolate to this color
* @param amt between 0.0 and 1.0
*
* @see PGraphics#blendColor(int, int, int)
* @see PGraphics#color(float, float, float, float)
*/
public int lerpColor(int c1, int c2, float amt) {
return g.lerpColor(c1, c2, amt);
}
/**
* Interpolate between two colors. Like lerp(), but for the
* individual color components of a color supplied as an int value.
*/
static public int lerpColor(int c1, int c2, float amt, int mode) {
return PGraphics.lerpColor(c1, c2, amt, mode);
}
/**
* Return true if this renderer should be drawn to the screen. Defaults to
* returning true, since nearly all renderers are on-screen beasts. But can
* be overridden for subclasses like PDF so that a window doesn't open up.
* <br/> <br/>
* A better name? showFrame, displayable, isVisible, visible, shouldDisplay,
* what to call this?
*/
public boolean displayable() {
return g.displayable();
}
/**
* Store data of some kind for a renderer that requires extra metadata of
* some kind. Usually this is a renderer-specific representation of the
* image data, for instance a BufferedImage with tint() settings applied for
* PGraphicsJava2D, or resized image data and OpenGL texture indices for
* PGraphicsOpenGL.
*/
public void setCache(Object parent, Object storage) {
if (recorder != null) recorder.setCache(parent, storage);
g.setCache(parent, storage);
}
/**
* Get cache storage data for the specified renderer. Because each renderer
* will cache data in different formats, it's necessary to store cache data
* keyed by the renderer object. Otherwise, attempting to draw the same
* image to both a PGraphicsJava2D and a PGraphicsOpenGL will cause errors.
* @param parent The PGraphics object (or any object, really) associated
* @return data stored for the specified parent
*/
public Object getCache(Object parent) {
return g.getCache(parent);
}
/**
* Remove information associated with this renderer from the cache, if any.
* @param parent The PGraphics object whose cache data should be removed
*/
public void removeCache(Object parent) {
if (recorder != null) recorder.removeCache(parent);
g.removeCache(parent);
}
/**
* Returns an ARGB "color" type (a packed 32 bit int with the color.
* If the coordinate is outside the image, zero is returned
* (black, but completely transparent).
* <P>
* If the image is in RGB format (i.e. on a PVideo object),
* the value will get its high bits set, just to avoid cases where
* they haven't been set already.
* <P>
* If the image is in ALPHA format, this returns a white with its
* alpha value set.
* <P>
* This function is included primarily for beginners. It is quite
* slow because it has to check to see if the x, y that was provided
* is inside the bounds, and then has to check to see what image
* type it is. If you want things to be more efficient, access the
* pixels[] array directly.
*/
public int get(int x, int y) {
return g.get(x, y);
}
/**
* Reads the color of any pixel or grabs a group of pixels. If no parameters are specified, the entire image is returned. Get the value of one pixel by specifying an x,y coordinate. Get a section of the display window by specifing an additional <b>width</b> and <b>height</b> parameter. If the pixel requested is outside of the image window, black is returned. The numbers returned are scaled according to the current color ranges, but only RGB values are returned by this function. Even though you may have drawn a shape with <b>colorMode(HSB)</b>, the numbers returned will be in RGB.
* <br><br>Getting the color of a single pixel with <b>get(x, y)</b> is easy, but not as fast as grabbing the data directly from <b>pixels[]</b>. The equivalent statement to "get(x, y)" using <b>pixels[]</b> is "pixels[y*width+x]". Processing requires calling <b>loadPixels()</b> to load the display window data into the <b>pixels[]</b> array before getting the values.
* <br><br>As of release 0149, this function ignores <b>imageMode()</b>.
*
* @webref
* @brief Reads the color of any pixel or grabs a rectangle of pixels
* @param x x-coordinate of the pixel
* @param y y-coordinate of the pixel
* @param w width of pixel rectangle to get
* @param h height of pixel rectangle to get
*
* @see processing.core.PImage#set(int, int, int)
* @see processing.core.PImage#pixels
* @see processing.core.PImage#copy(PImage, int, int, int, int, int, int, int, int)
*/
public PImage get(int x, int y, int w, int h) {
return g.get(x, y, w, h);
}
/**
* Returns a copy of this PImage. Equivalent to get(0, 0, width, height).
*/
public PImage get() {
return g.get();
}
/**
* Changes the color of any pixel or writes an image directly into the display window. The <b>x</b> and <b>y</b> parameters specify the pixel to change and the <b>color</b> parameter specifies the color value. The color parameter is affected by the current color mode (the default is RGB values from 0 to 255). When setting an image, the x and y parameters define the coordinates for the upper-left corner of the image.
* <br><br>Setting the color of a single pixel with <b>set(x, y)</b> is easy, but not as fast as putting the data directly into <b>pixels[]</b>. The equivalent statement to "set(x, y, #000000)" using <b>pixels[]</b> is "pixels[y*width+x] = #000000". You must call <b>loadPixels()</b> to load the display window data into the <b>pixels[]</b> array before setting the values and calling <b>updatePixels()</b> to update the window with any changes.
* <br><br>As of release 1.0, this function ignores <b>imageMode()</b>.
* <br><br>Due to what appears to be a bug in Apple's Java implementation, the point() and set() methods are extremely slow in some circumstances when used with the default renderer. Using P2D or P3D will fix the problem. Grouping many calls to point() or set() together can also help. (<a href="http://dev.processing.org/bugs/show_bug.cgi?id=1094">Bug 1094</a>)
* =advanced
* <br><br>As of release 0149, this function ignores <b>imageMode()</b>.
*
* @webref image:pixels
* @param x x-coordinate of the pixel
* @param y y-coordinate of the pixel
* @param c any value of the color datatype
*/
public void set(int x, int y, int c) {
if (recorder != null) recorder.set(x, y, c);
g.set(x, y, c);
}
/**
* Efficient method of drawing an image's pixels directly to this surface.
* No variations are employed, meaning that any scale, tint, or imageMode
* settings will be ignored.
*/
public void set(int x, int y, PImage src) {
if (recorder != null) recorder.set(x, y, src);
g.set(x, y, src);
}
/**
* Set alpha channel for an image. Black colors in the source
* image will make the destination image completely transparent,
* and white will make things fully opaque. Gray values will
* be in-between steps.
* <P>
* Strictly speaking the "blue" value from the source image is
* used as the alpha color. For a fully grayscale image, this
* is correct, but for a color image it's not 100% accurate.
* For a more accurate conversion, first use filter(GRAY)
* which will make the image into a "correct" grayscale by
* performing a proper luminance-based conversion.
*
* @param maskArray any array of Integer numbers used as the alpha channel, needs to be same length as the image's pixel array
*/
public void mask(int maskArray[]) {
if (recorder != null) recorder.mask(maskArray);
g.mask(maskArray);
}
/**
* Masks part of an image from displaying by loading another image and using it as an alpha channel.
* This mask image should only contain grayscale data, but only the blue color channel is used.
* The mask image needs to be the same size as the image to which it is applied.
* In addition to using a mask image, an integer array containing the alpha channel data can be specified directly.
* This method is useful for creating dynamically generated alpha masks.
* This array must be of the same length as the target image's pixels array and should contain only grayscale data of values between 0-255.
* @webref
* @brief Masks part of the image from displaying
* @param maskImg any PImage object used as the alpha channel for "img", needs to be same size as "img"
*/
public void mask(PImage maskImg) {
if (recorder != null) recorder.mask(maskImg);
g.mask(maskImg);
@ -8704,12 +9988,41 @@ public class PApplet extends Applet
}
/**
* Filters an image as defined by one of the following modes:<br><br>THRESHOLD - converts the image to black and white pixels depending if they are above or below the threshold defined by the level parameter. The level must be between 0.0 (black) and 1.0(white). If no level is specified, 0.5 is used.<br><br>GRAY - converts any colors in the image to grayscale equivalents<br><br>INVERT - sets each pixel to its inverse value<br><br>POSTERIZE - limits each channel of the image to the number of colors specified as the level parameter<br><br>BLUR - executes a Guassian blur with the level parameter specifying the extent of the blurring. If no level parameter is used, the blur is equivalent to Guassian blur of radius 1.<br><br>OPAQUE - sets the alpha channel to entirely opaque.<br><br>ERODE - reduces the light areas with the amount defined by the level parameter.<br><br>DILATE - increases the light areas with the amount defined by the level parameter
* =advanced
* Method to apply a variety of basic filters to this image.
* <P>
* <UL>
* <LI>filter(BLUR) provides a basic blur.
* <LI>filter(GRAY) converts the image to grayscale based on luminance.
* <LI>filter(INVERT) will invert the color components in the image.
* <LI>filter(OPAQUE) set all the high bits in the image to opaque
* <LI>filter(THRESHOLD) converts the image to black and white.
* <LI>filter(DILATE) grow white/light areas
* <LI>filter(ERODE) shrink white/light areas
* </UL>
* Luminance conversion code contributed by
* <A HREF="http://www.toxi.co.uk">toxi</A>
* <P/>
* Gaussian blur code contributed by
* <A HREF="http://incubator.quasimondo.com">Mario Klingemann</A>
*
* @webref
* @brief Converts the image to grayscale or black and white
* @param kind Either THRESHOLD, GRAY, INVERT, POSTERIZE, BLUR, OPAQUE, ERODE, or DILATE
* @param param in the range from 0 to 1
*/
public void filter(int kind, float param) {
if (recorder != null) recorder.filter(kind, param);
g.filter(kind, param);
}
/**
* Copy things from one area of this image
* to another area in the same image.
*/
public void copy(int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh) {
if (recorder != null) recorder.copy(sx, sy, sw, sh, dx, dy, dw, dh);
@ -8717,6 +10030,25 @@ public class PApplet extends Applet
}
/**
* Copies a region of pixels from one image into another. If the source and destination regions aren't the same size, it will automatically resize source pixels to fit the specified target region. No alpha information is used in the process, however if the source image has an alpha channel set, it will be copied as well.
* <br><br>As of release 0149, this function ignores <b>imageMode()</b>.
*
* @webref
* @brief Copies the entire image
* @param sx X coordinate of the source's upper left corner
* @param sy Y coordinate of the source's upper left corner
* @param sw source image width
* @param sh source image height
* @param dx X coordinate of the destination's upper left corner
* @param dy Y coordinate of the destination's upper left corner
* @param dw destination image width
* @param dh destination image height
* @param src an image variable referring to the source image.
*
* @see processing.core.PGraphics#alpha(int)
* @see processing.core.PImage#blend(PImage, int, int, int, int, int, int, int, int, int)
*/
public void copy(PImage src,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh) {
@ -8725,11 +10057,80 @@ public class PApplet extends Applet
}
/**
* Blend two colors based on a particular mode.
* <UL>
* <LI>REPLACE - destination colour equals colour of source pixel: C = A.
* Sometimes called "Normal" or "Copy" in other software.
*
* <LI>BLEND - linear interpolation of colours:
* <TT>C = A*factor + B</TT>
*
* <LI>ADD - additive blending with white clip:
* <TT>C = min(A*factor + B, 255)</TT>.
* Clipped to 0..255, Photoshop calls this "Linear Burn",
* and Director calls it "Add Pin".
*
* <LI>SUBTRACT - substractive blend with black clip:
* <TT>C = max(B - A*factor, 0)</TT>.
* Clipped to 0..255, Photoshop calls this "Linear Dodge",
* and Director calls it "Subtract Pin".
*
* <LI>DARKEST - only the darkest colour succeeds:
* <TT>C = min(A*factor, B)</TT>.
* Illustrator calls this "Darken".
*
* <LI>LIGHTEST - only the lightest colour succeeds:
* <TT>C = max(A*factor, B)</TT>.
* Illustrator calls this "Lighten".
*
* <LI>DIFFERENCE - subtract colors from underlying image.
*
* <LI>EXCLUSION - similar to DIFFERENCE, but less extreme.
*
* <LI>MULTIPLY - Multiply the colors, result will always be darker.
*
* <LI>SCREEN - Opposite multiply, uses inverse values of the colors.
*
* <LI>OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
* and screens light values.
*
* <LI>HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
*
* <LI>SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
* Works like OVERLAY, but not as harsh.
*
* <LI>DODGE - Lightens light tones and increases contrast, ignores darks.
* Called "Color Dodge" in Illustrator and Photoshop.
*
* <LI>BURN - Darker areas are applied, increasing contrast, ignores lights.
* Called "Color Burn" in Illustrator and Photoshop.
* </UL>
* <P>A useful reference for blending modes and their algorithms can be
* found in the <A HREF="http://www.w3.org/TR/SVG12/rendering.html">SVG</A>
* specification.</P>
* <P>It is important to note that Processing uses "fast" code, not
* necessarily "correct" code. No biggie, most software does. A nitpicker
* can find numerous "off by 1 division" problems in the blend code where
* <TT>&gt;&gt;8</TT> or <TT>&gt;&gt;7</TT> is used when strictly speaking
* <TT>/255.0</T> or <TT>/127.0</TT> should have been used.</P>
* <P>For instance, exclusion (not intended for real-time use) reads
* <TT>r1 + r2 - ((2 * r1 * r2) / 255)</TT> because <TT>255 == 1.0</TT>
* not <TT>256 == 1.0</TT>. In other words, <TT>(255*255)>>8</TT> is not
* the same as <TT>(255*255)/255</TT>. But for real-time use the shifts
* are preferrable, and the difference is insignificant for applications
* built with Processing.</P>
*/
static public int blendColor(int c1, int c2, int mode) {
return PGraphics.blendColor(c1, c2, mode);
}
/**
* Blends one area of this image to another area.
*
* @see processing.core.PImage#blendColor(int,int,int)
*/
public void blend(int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh, int mode) {
if (recorder != null) recorder.blend(sx, sy, sw, sh, dx, dy, dw, dh, mode);
@ -8737,6 +10138,42 @@ public class PApplet extends Applet
}
/**
* Blends a region of pixels into the image specified by the <b>img</b> parameter. These copies utilize full alpha channel support and a choice of the following modes to blend the colors of source pixels (A) with the ones of pixels in the destination image (B):<br><br>
* BLEND - linear interpolation of colours: C = A*factor + B<br><br>
* ADD - additive blending with white clip: C = min(A*factor + B, 255)<br><br>
* SUBTRACT - subtractive blending with black clip: C = max(B - A*factor, 0)<br><br>
* DARKEST - only the darkest colour succeeds: C = min(A*factor, B)<br><br>
* LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)<br><br>
* DIFFERENCE - subtract colors from underlying image.<br><br>
* EXCLUSION - similar to DIFFERENCE, but less extreme.<br><br>
* MULTIPLY - Multiply the colors, result will always be darker.<br><br>
* SCREEN - Opposite multiply, uses inverse values of the colors.<br><br>
* OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values, and screens light values.<br><br>
* HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.<br><br>
* SOFT_LIGHT - Mix of DARKEST and LIGHTEST. Works like OVERLAY, but not as harsh.<br><br>
* DODGE - Lightens light tones and increases contrast, ignores darks. Called "Color Dodge" in Illustrator and Photoshop.<br><br>
* BURN - Darker areas are applied, increasing contrast, ignores lights. Called "Color Burn" in Illustrator and Photoshop.<br><br>
* All modes use the alpha information (highest byte) of source image pixels as the blending factor. If the source and destination regions are different sizes, the image will be automatically resized to match the destination size. If the <b>srcImg</b> parameter is not used, the display window is used as the source image.<br><br>
* As of release 0149, this function ignores <b>imageMode()</b>.
*
* @webref
* @brief Copies a pixel or rectangle of pixels using different blending modes
* @param src an image variable referring to the source image
* @param sx X coordinate of the source's upper left corner
* @param sy Y coordinate of the source's upper left corner
* @param sw source image width
* @param sh source image height
* @param dx X coordinate of the destinations's upper left corner
* @param dy Y coordinate of the destinations's upper left corner
* @param dw destination image width
* @param dh destination image height
* @param mode Either BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN
*
* @see processing.core.PGraphics#alpha(int)
* @see processing.core.PGraphics#copy(PImage, int, int, int, int, int, int, int, int)
* @see processing.core.PImage#blendColor(int,int,int)
*/
public void blend(PImage src,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh, int mode) {