text:
APNS/2 is a go package designed for simple, flexible and fast Apple Push Notifications on iOS, OSX and Safari using the new HTTP/2 Push provider API.

[![Build Status](https://github.com/sideshow/apns2/actions/workflows/tests.yml/badge.svg)](https://github.com/sideshow/apns2/actions/workflows/tests.yml) [![Coverage Status](https://coveralls.io/repos/sideshow/apns2/badge.svg?branch=master&service=github)](https://coveralls.io/github/sideshow/apns2?branch=master) [![GoDoc](https://godoc.org/github.com/sideshow/apns2?status.svg)](https://godoc.org/github.com/sideshow/apns2)

## Features

- Uses new Apple APNs HTTP/2 connection
- Fast - See [notes on speed](https://github.com/sideshow/apns2/wiki/APNS-HTTP-2-Push-Speed)
- Works with go 1.7 and later
- Supports new Apple Token Based Authentication (JWT)
- Supports new iOS 10 features such as Collapse IDs, Subtitles and Mutable Notifications
- Supports new iOS 15 features interruptionLevel and relevanceScore
- Supports persistent connections to APNs
- Supports VoIP/PushKit notifications (iOS 8 and later)
- Modular & easy to use
- Tested and working in APNs production environment

## Install

- Make sure you have [Go](https://golang.org/doc/install) installed and have set your [GOPATH](https://golang.org/doc/code.html#GOPATH).
- Install apns2:

```sh
go get -u github.com/sideshow/apns2
```

If you are running the test suite you will also need to install testify:

```sh
go get -u github.com/stretchr/testify
```

## Example

```go
package main

import (
  "log"
  "fmt"

  "github.com/sideshow/apns2"
  "github.com/sideshow/apns2/certificate"
)

func main() {

  cert, err := certificate.FromP12File("../cert.p12", "")
  if err != nil {
    log.Fatal("Cert Error:", err)
  }

  notification := &apns2.Notification{}
  notification.DeviceToken = "11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7"
  notification.Topic = "com.sideshow.Apns2"
  notification.Payload = []byte(`{"aps":{"alert":"Hello!"}}`) // See Payload section below

  // If you want to test push notifications for builds running directly from XCode (Development), use
  // client := apns2.NewClient(cert).Development()
  // For apps published to the app store or installed as an ad-hoc distribution use Production()

  client := apns2.NewClient(cert).Production()
  res, err := client.Push(notification)

  if err != nil {
    log.Fatal("Error:", err)
  }

  fmt.Printf("%v %v %v\n", res.StatusCode, res.ApnsID, res.Reason)
}
```

## JWT Token Example

Instead of using a `.p12` or `.pem` certificate as above, you can optionally use
APNs JWT _Provider Authentication Tokens_. First you will need a signing key (`.p8` file), Key ID and Team ID [from Apple](http://help.apple.com/xcode/mac/current/#/dev54d690a66). Once you have these details, you can create a new client:

```go
authKey, err := token.AuthKeyFromFile("../AuthKey_XXX.p8")
if err != nil {
  log.Fatal("token error:", err)
}

token := &token.Token{
  AuthKey: authKey,
  // KeyID from developer account (Certificates, Identifiers & Profiles -> Keys)
  KeyID:   "ABC123DEFG",
  // TeamID from developer account (View Account -> Membership)
  TeamID:  "DEF123GHIJ",
}
...

client := apns2.NewTokenClient(token)
res, err := client.Push(notification)
```

- You can use one APNs signing key to authenticate tokens for multiple apps.
- A signing key works for both the development and production environments.
- A signing key doesn't expire but can be revoked.

## Notification

At a minimum, a _Notification_ needs a _DeviceToken_, a _Topic_ and a _Payload_.

```go
notification := &apns2.Notification{
  DeviceToken: "11aa01229f15f0f0c52029d8cf8cd0aeaf2365fe4cebc4af26cd6d76b7919ef7",
  Topic: "com.sideshow.Apns2",
  Payload: []byte(`{"aps":{"alert":"Hello!"}}`),
}
```

You can also set an optional _ApnsID_, _Expiration_ or _Priority_.

```go
notification.ApnsID =  "40636A2C-C093-493E-936A-2A4333C06DEA"
notification.Expiration = time.Now()
notification.Priority = apns2.PriorityLow
```

## Payload

You can use raw bytes for the `notification.Payload` as above, or you can use the payload builder package which makes it easy to construct APNs payloads.

```go
// {"aps":{"alert":"hello","badge":1},"key":"val"}

payload := payload.NewPayload().Alert("hello").Badge(1).Custom("key", "val")

notification.Payload = payload
client.Push(notification)
```

Refer to the [payload](https://godoc.org/github.com/sideshow/apns2/payload) docs for more info.

## Response, Error handling

APNS/2 draws the distinction between a valid response from Apple indicating whether or not the _Notification_ was sent or not, and an unrecoverable or unexpected _Error_;

- An `Error` is returned if a non-recoverable error occurs, i.e. if there is a problem with the underlying _http.Client_ connection or _Certificate_, the payload was not sent, or a valid _Response_ was not received.
- A `Response` is returned if the payload was successfully sent to Apple and a documented response was received. This struct will contain more information about whether or not the push notification succeeded, its _apns-id_ and if applicable, more information around why it did not succeed.

To check if a `Notification` was successfully sent;

```go
res, err := client.Push(notification)
if err != nil {
  log.Println("There was an error", err)
  return
}

if res.Sent() {
  log.Println("Sent:", res.ApnsID)
} else {
  fmt.Printf("Not Sent: %v %v %v\n", res.StatusCode, res.ApnsID, res.Reason)
}
```

## Context & Timeouts

For better control over request cancellations and timeouts APNS/2 supports
contexts. Using a context can be helpful if you want to cancel all pushes when
the parent process is cancelled, or need finer grained control over individual
push timeouts. See the [Google post](https://blog.golang.org/context) for more
information on contexts.

```go
ctx, cancel = context.WithTimeout(context.Background(), 10 * time.Second)
res, err := client.PushWithContext(ctx, notification)
defer cancel()
```

## Speed & Performance

Also see the wiki page on [APNS HTTP 2 Push Speed](https://github.com/sideshow/apns2/wiki/APNS-HTTP-2-Push-Speed).

For best performance, you should hold on to an `apns2.Client` instance and not re-create it every push. The underlying TLS connection itself can take a few seconds to connect and negotiate, so if you are setting up an `apns2.Client` and tearing it down every push, then this will greatly affect performance. (Apple suggest keeping the connection open all the time).

You should also limit the amount of `apns2.Client` instances. The underlying transport has a http connection pool itself, so a single client instance will be enough for most users (One instance can potentially do 4,000+ pushes per second). If you need more than this then one instance per CPU core is a good starting point.

Speed is greatly affected by the location of your server and the quality of your network connection. If you're just testing locally, behind a proxy or if your server is outside USA then you're not going to get great performance. With a good server located in AWS, you should be able to get [decent throughput](https://github.com/sideshow/apns2/wiki/APNS-HTTP-2-Push-Speed).

## Command line tool

APNS/2 has a command line tool that can be installed with `go get github.com/sideshow/apns2/apns2`. Usage:

```
apns2 --help
usage: apns2 --certificate-path=CERTIFICATE-PATH --topic=TOPIC [<flags>]

Listens to STDIN to send notifications and writes APNS response code and reason to STDOUT.

The expected format is: <DeviceToken> <APNS Payload>
Example: aff0c63d9eaa63ad161bafee732d5bc2c31f66d552054718ff19ce314371e5d0 {"aps": {"alert": "hi"}}
Flags:
      --help               Show context-sensitive help (also try --help-long and --help-man).
  -c, --certificate-path=CERTIFICATE-PATH
                           Path to certificate file.
  -t, --topic=TOPIC        The topic of the remote notification, which is typically the bundle ID for your app
  -m, --mode="production"  APNS server to send notifications to. `production` or `development`. Defaults to `production`
      --version            Show application version.
```

## License

The MIT License (MIT)

Copyright (c) 2016 Adam Jones

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


text:
<?php
namespace Home\Controller;
use Think\Controller;
class ClientController extends Controller {
    public function index(){
        $this->display(APP_PATH.'Home/View/Client-list.html');
    }
}

redpajama_set_name: RedPajamaGithub


text: Relative Steem Power Ranking


text:
# Performing a test run of your HaSAPPy installation

This tutorial shows how to quickly verify that HaSAPPy is correctly installed on your system and all dependencies are met. For testing the core functionality of HaSAPPy a pre-filled **LoadModule.txt** command script and a **Sequence_test** file are included in the docs/test folder in the installation.
It is recommended to run this text for a new installation before starting to use HaSAPPy for data analysis workflows.

The working directory for this tutorial is:

```
<DATA PATH>:
```

## Prerequisites

1. Installation of HaSAPPy package
2. Necessary Python packages correctly updated
3. Installation of bowtie2

### Create a folder where the experiments and run information will be stored
In the <DATA PATH>: create a new **data/experiments/test** folder:
```
mkdir data
cd data
mkdir experiments
cd experiments
mkdir test
```
The folder structure should look like this:
```
<DATA PATH>:
|
└── HaSAPPy
|   └── ...
└── data
    └── experiments
        └── test
            └── ...
```

### Download and unpack sequence archives for PhiX and Mus Musculus genomes
Add a **reference/** folder where the genome sequences and indices will be stored:
```
mkdir reference
```
The folder structure should look like this:
```
<DATA PATH>:
|
└── HaSAPPy
|   └── ...
└── data
    └── experiments
    |   └── test
    |       └── ...
    └── reference
	    └── ...
```

Genome sequences and indices for read mapping for common species are available at:

http://support.illumina.com/sequencing/sequencing_software/igenome.html

Using a web browser download the PhiX genome (NCBI 1993-04-28) and the mouse genome (GCRm38/mm10) to your <DATA PATH>:/data/reference folder. Then unpack the archives in the terminal:

```
cd reference
tar -xzvf PhiX_NCBI_1993-04-28.tar.gz
tar -xzvf Mus_musculus_UCSC_mm10.tar.gz
```

### Set execute permission on PreprocessReads

PreprocessReads is a precompiled executable file for read trimming (the source code is available at [github](https://github.com/zanton123/PreprocessReads). You need to set the execute permission on Linux based file systems to be able to run the program. Enter the /HaSAPPy/program/** folder and set the execute property with the following commands:

```
cd <DATA PATH>:/HaSAPPy/program
chmod +x PreprocessReads
```

### Build the gene annotation database using GeneReference_built.py

A gene annotation file for the mouse genome (GCRm38/mm10) is supplied with the source.

>**NOTE:** If you need other genomes suitable annotation files can be obtained from the UCSC genome browser (http://genome.ucsc.edu/cgi-bin/hgTables?command=start).
Refer to the [Generate a human gene reference](https://github.com/gdiminin/HaSAPPy/blob/master/docs/Tutorials/CreateHumanGeneAnnotationReference.md) tutorial for a detailed example:

```
python GeneReference_built.py -i <DATA PATH>:/HaSAPPy/docs/mm10_REFSEQgenes.txt -o <DATA PATH>:/HaSAPPy/docs/GeneReference_Mouse-MM10.pkl
```

A new file GeneReference_mouse_mm10.pkl should appear in the current folder.

Now we are ready to start. Your working directory (**/Users/User/HaSAPPy**) should have this structure:

* the <DATA PATH>:

```
<DATA PATH>:
|
└── HaSAPPy
|   ├── ...
|   ├── program
|   |   └── ...
|   └── docs
|       ├── LoadModule.txt
|       ├── mm10REFSEQgenes.txt
|       ├── GeneReference_Mouse-MM10.pkl
|       ├── Tutorials
|       |   └── ...
|       └── test
|            ├── Aligned.sam
|            ├── Sequence.fastq
|            ├── LoadModule_test_from_Trim.txt
|            └── LoadModule_test_from_IIdefinition.txt
|
└── data
    ├── experiments
    |   └── test
    |       └── ...
    └── reference
        └── ...
```

* the reference directory

```
└── reference
    ├── Phix
    |   └── NCBI
    |       └── 1993-04-28
    |           ├── Annotation
    |           |   └── ...
    |           ├── Sequence
    |           ├── ...
    |	        └── Bowtie2Index
    |	            ├── genome.1.ebwt
    |	            └── ...
    └── Mus_musculus
        └── UCSC
            └── mm10
                 ├── Annotation
                 |   └── ...
                 ├── Sequence
                 ├── ...
     	         └── Bowtie2Index
     	             ├── genome.1.ebwt
     	             └── ...
```

* the experiments directory

```
└── experiments
    └── test
         └── ...
```

## Edit the HaSAPPy command script - the LoadModule file

In this tutorial, we are going to test the functionality of the HaSAPPy packages (starting from the **Trim.py** module) using the **LoadModule_test_from_Trim.txt** and the **Sequence.fastq** files in the `docs/test` folder.

```
<DATA PATH>:/HaSAPPy/docs/test
```

In addition, you can test HaSAPPy function from the **IIdefinition.py** module using the **LoadModule_test_from_IIdefinition.txt** and the **Aligned.sam** files.

Open the LoadModule_test_from_Trim.txt file in a text editor. As you can see most of the tasks have already been filled out. You need to provide the missing PATH information where files are stored in your file system (absolute PATH from root `/` is required). Complete the input fields of the form in the following way:

* Section 1
* Task 1A and 1B

```
Operator Name:
@1A) User
Storing location (provide a correct path):
@1B) <DATA PATH>:/data/experiments/test
```
* Section 2
* 2D

```
Location of input file 1 (add additional lines if necessary):
@2D) <DATA PATH>:/HaSAPPy/docs/test/Sequence.fastq
@2D) <DATA PATH>:/HaSAPPy/docs/test/Sequence.fastq
```

* Section 3
*  3A

```
Location of Phix reference genome:
@3A)<DATA PATH>:/data/reference/PhiX/NCBI/1993-04-28/Sequence/Bowtie2Index/genome
```

> **NOTE:** For Bowtie2 the path and filename for the genome index should be provided without the file extension!

* Section 4
* 4B

```
Location of reference genome:
@4B) <DATA PATH>:/data/reference/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/genome
```

* Section 6
* 6A

```
Location of gene reference:
@6A)<DATA PATH>:/HaSAPPy/docs/GeneReference_Mouse-MM10.pkl
```

* Section 9
* 9C

```
FOR Plot I.I. in gene models:
Location of gene reference:
@9C)<DATA PATH>:/HaSAPPy/docs/GeneReference_Mouse-MM10.pkl
```

Save the file and copy the file name to the clipboard.

## Run the test

Move into the HaSAPPy/program folder:

```
cd <DATA PATH>:/HaSAPPy/program
```

Start the analysis using **HaSAPPY_start.py**  with the **LoadModule_test_from_Trim.txt** file path as command line argument:

```
python HaSAPPY.py <DATA PATH>:/HaSAPPy/docs/test/LoadModule_test_from_Trim.txt
```

If everything is correctly installed the analysis should finish without any errors.

## Inspect the output

In the `<DATA PATH>:/data/experiments/test` folder the following files and folders should have been created

```
<DATA PATH>:/data/experiments/test
    ├── test_1_yyyy-mm-dd
    |   ├── test_1_info.txt
    |   ├── graph
    |   └── raw
    |       ├── test_1_Aligned.sam
    |       ├── ...
    |       └── test_1_IIRawdata.pkl
    ├── test_2_yyyy-mm-dd
    |   ├── test_2_info.txt
    |   ├── graph
    |   └── raw
    |       ├── test_2_Aligned.sam
    |       ├── ...
    |       └── test_2_IIRawdata.pkl
    └── Analysis
        └── yyyy-mm-dd
            ├── analysis_info.txt
            ├── graph
            |   ├── Xist_SelectedvsControl.svg
            |   └── ...
            ├── raw
            |   ├── GroupAnalysis.pkl
            |   └── RawData.pkl
            └── Table_yyyy-mm-dd.xlsx
```

Open the **Table_yyyy-mm-dd.xlsx** file in a spreadsheet program (eg. LibreOffice Calc, WPS Office Spreadsheet, or Microsoft Excel) and the **Xist_SelectedvsControl.svg** file in a vector graphics program (eg. Adobe Illustratore, or Inkscape). You should see the output in table format and a graphic view of the insertions in the _Xist_ gene similar as following output:

![alt text] (https://github.com/gdiminin/HaSAPPy/blob/master/docs/Tutorials/Figures/Test_HaSAPPy_installation.png)

If this is what you see, you have now a working HaSAPPy installation. Congratulation!!!!

[**RETURN TO THE MAIN PAGE**](https://github.com/gdiminin/HaSAPPy/blob/master/README.md)


text:
package org.drools.guvnor.server.repository;

import java.util.Iterator;
import java.util.List;

import org.drools.guvnor.client.common.AssetFormats;
import org.drools.guvnor.client.explorer.ExplorerNodeConfig;
import org.drools.guvnor.client.rpc.TableDataResult;
import org.drools.guvnor.client.rpc.TableDataRow;
import org.drools.repository.AssetItem;
import org.drools.repository.RulesRepository;
import org.drools.repository.UserInfo;
import org.drools.repository.UserInfo.InboxEntry;

/**
 * This manages the users "inbox".
 */
public class UserInbox {

    static final int            MAX_RECENT_EDITED = 200;

    private static final String INBOX             = "inbox";

    private final UserInfo      userInfo;

    /**
     * Create an inbox for the given user name (id)
     */
    public UserInbox(RulesRepository repo,
                     String userName) {
        this.userInfo = new UserInfo( repo,
                                      userName );
    }

    /**
     * Create an inbox for the current sessions user id.
     */
    public UserInbox(RulesRepository repo) {
        this.userInfo = new UserInfo( repo );
    }

    /**
     * This should be called when the user edits or comments on an asset. Simply
     * adds to the list...
     */
    public void addToRecentEdited(String assetId,
                                  String note) {
        addToInbox( ExplorerNodeConfig.RECENT_EDITED_ID,
                    assetId,
                    note,
                    "self" );
    }

    public void addToRecentOpened(String assetId,
                                  String note) {
        addToInbox( ExplorerNodeConfig.RECENT_VIEWED_ID,
                    assetId,
                    note,
                    "self" );
    }

    public void addToIncoming(String assetId,
                              String note,
                              String userFrom) {
        addToInbox( ExplorerNodeConfig.INCOMING_ID,
                    assetId,
                    note,
                    userFrom );
    }

    private void addToInbox(String boxName,
                            String assetId,
                            String note,
                            String userFrom) {
        assert boxName.equals( ExplorerNodeConfig.RECENT_EDITED_ID ) || boxName.equals( ExplorerNodeConfig.RECENT_VIEWED_ID ) || boxName.equals( ExplorerNodeConfig.INCOMING_ID );
        List<InboxEntry> entries = removeAnyExisting( assetId,
                                                      userInfo.readEntries( INBOX,
                                                                            boxName ) );

        if ( entries.size() >= MAX_RECENT_EDITED ) {
            entries.remove( 0 );
            entries.add( new InboxEntry( assetId,
                                         note,
                                         userFrom ) );
        } else {
            entries.add( new InboxEntry( assetId,
                                         note,
                                         userFrom ) );
        }

        userInfo.writeEntries( INBOX,
                               boxName,
                               entries );
        userInfo.save();
    }

    private List<InboxEntry> removeAnyExisting(String assetId,
                                               List<InboxEntry> inboxEntries) {
        Iterator<InboxEntry> it = inboxEntries.iterator();
        while ( it.hasNext() ) {
            InboxEntry e = it.next();
            if ( e.assetUUID.equals( assetId ) ) {
                it.remove();
                return inboxEntries;
            }
        }
        return inboxEntries;
    }

    public List<InboxEntry> loadEntries(final String inboxName) {
        List<InboxEntry> entries;
        if ( inboxName.equals( ExplorerNodeConfig.RECENT_VIEWED_ID ) ) {
            entries = loadRecentOpened();
        } else if ( inboxName.equals( ExplorerNodeConfig.RECENT_EDITED_ID ) ) {
            entries = loadRecentEdited();
        } else {
            entries = loadIncoming();

        }
        return entries;
    }

    public List<InboxEntry> loadRecentEdited() {
        return userInfo.readEntries( INBOX,
                                     ExplorerNodeConfig.RECENT_EDITED_ID );
    }

    public List<InboxEntry> loadRecentOpened() {
        return userInfo.readEntries( INBOX,
                                     ExplorerNodeConfig.RECENT_VIEWED_ID );
    }

    public List<InboxEntry> loadIncoming() {
        return userInfo.readEntries( INBOX,
                                     ExplorerNodeConfig.INCOMING_ID );
    }

    /**
     * Wipe them out, all of them.
     */
    public void clearAll() {
        userInfo.clear( INBOX,
                        ExplorerNodeConfig.RECENT_EDITED_ID );
        userInfo.clear( INBOX,
                        ExplorerNodeConfig.RECENT_VIEWED_ID );
        userInfo.clear( INBOX,
                        ExplorerNodeConfig.INCOMING_ID );
    }

    public void clearIncoming() {
        userInfo.clear( INBOX,
                        ExplorerNodeConfig.INCOMING_ID );
    }

    public static TableDataResult toTable(List<InboxEntry> entries,
                                          boolean showFrom) {
        TableDataResult res = new TableDataResult();
        res.currentPosition = 0;
        res.total = entries.size();
        res.hasNext = false;
        res.data = new TableDataRow[entries.size()];
        for ( int i = 0; i < entries.size(); i++ ) {
            TableDataRow tdr = new TableDataRow();
            InboxEntry e = entries.get( i );
            tdr.id = e.assetUUID;
            if ( !showFrom ) {
                tdr.values = new String[2];
                tdr.values[0] = e.note;
                tdr.values[1] = Long.toString( e.timestamp );
            } else {
                tdr.values = new String[3];
                tdr.values[0] = e.note;
                tdr.values[1] = Long.toString( e.timestamp );
                tdr.values[2] = e.from;
            }
            tdr.format = AssetFormats.BUSINESS_RULE;
            res.data[i] = tdr;
        }
        return res;
    }

    /**
     * Helper method to log the opening. Will remove any inbox items that have
     * the same id.
     */
    public synchronized static void recordOpeningEvent(AssetItem item) {
        UserInbox ib = new UserInbox( item.getRulesRepository() );
        ib.addToRecentOpened( item.getUUID(),
                              item.getName() );
        List<InboxEntry> unreadIncoming = ib.removeAnyExisting( item.getUUID(),
                                                                ib.loadIncoming() );
        ib.userInfo.writeEntries( INBOX,
                                  ExplorerNodeConfig.INCOMING_ID,
                                  unreadIncoming );

        ib.save();
    }

    /**
     * Helper method to note the event
     */
    public synchronized static void recordUserEditEvent(AssetItem item) {
        UserInbox ib = new UserInbox( item.getRulesRepository() );
        ib.addToRecentEdited( item.getUUID(),
                              item.getName() );
        ib.save();
    }

    void save() {
        userInfo.save();
    }

}


text:
# clz
This uses callbacks to read and write data. The default is set to stdin and stdout. To start:
clz_create() will return a pointer to an anonymous state structure.
Then use
clz_setcb_get() and clz_setcb_put() to set the callbacks.
Finally call:
clz_decompress() to decompress.

## Example:
    size_t gzput(void *par, void *buf, size_t buflen)
    {
        int i;
        char *text = buf;

        printf("gzput received buffer of size %u\n", buflen);
    }

    ...

    FILE * fp;
    void *gzstate;
    unsigned int crc32;
    ...
    gzstate = clz_create();
    if (!gzstate)
    {
        perror("clz_create fail\n");
        fclose(fp);
        exit(1);
    }

    /* Set get to read from file pointer fp */

    if (!clz_setcb_get(gzstate, 0, (void *)fp, 0))
    {
        printf("clz_setcb_get fail\n");
        fclose(fp);
        exit(1);
    }

    /* Set put to use the gzput callback */

    if (!clz_setcb_put(gzstate, gzput, 0))
    {
        printf("clz_setcb_put fail\n");
        fclose(fp);
        exit(1);
    }

    /* Decompress and calculate crc32 */

    ret = clz_decompress(gzstate, 0, &crc32);
    if (!ret)
    {
        perror("error on decompress");
        fclose(fp);
        exit(1);
    }

    /* ret is how much input it ate */

    printf("decompress returns: %d, crc: %08x\n", ret, crc32);


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                "http://www.w3.org/TR/REC-html40/loose.dtd">

  <title>Description of create_nesting_nodes</title>
  <meta name="keywords" content="create_nesting_nodes">
  <meta name="description" content="create a list of the nesting boundary nodes">
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta name="generator" content="m2html v1.5 © 2003-2005 Guillaume Flandin">
  <meta name="robots" content="index, follow">
  <link type="text/css" rel="stylesheet" href="../m2html.css">

Home >  fvcom_prepro > create_nesting_nodes.m

create_nesting_nodes

PURPOSE

create a list of the nesting boundary nodes

SYNOPSIS

This is a script file.

DESCRIPTION

 create a list of the nesting boundary nodes
 subname = 'create_nesting_nodes'

 DESCRIPTION:
    READ in the following data:
          - FVCOM OBC file
        - FVCOM Grid file (connectivity + nodes)
    Process data:
       - Extract all nodes belonging to elements at the boundary
    Write output
       - Write Node nesting file

 INPUT :
   FVCOM OBC file and Grid file

 OUTPUT:
   Node nesting file

 EXAMPLE USAGE
    create_nesting_nodes

 Author(s):
    Hakeem Johnson (CH2MHILL, Warrington, UK)
    Darren Price(CH2MHILL, Warrington, UK)

 Revision history
   Jan 2014: Beta version including the correct nesting format
==============================================================================

CROSS-REFERENCE INFORMATION

This function calls:

This function is called by:

SOURCE CODE

0001
0002 % create a list of the nesting boundary nodes
0003 % subname = 'create_nesting_nodes'
0004 %
0005 % DESCRIPTION:
0006 %    READ in the following data:
0007 %          - FVCOM OBC file
0008 %        - FVCOM Grid file (connectivity + nodes)
0009 %    Process data:
0010 %       - Extract all nodes belonging to elements at the boundary
0011 %    Write output
0012 %       - Write Node nesting file
0013 %
0014 % INPUT :
0015 %   FVCOM OBC file and Grid file
0016 %
0017 % OUTPUT:
0018 %   Node nesting file
0019 %
0020 % EXAMPLE USAGE
0021 %    create_nesting_nodes
0022 %
0023 % Author(s):
0024 %    Hakeem Johnson (CH2MHILL, Warrington, UK)
0025 %    Darren Price(CH2MHILL, Warrington, UK)
0026 %
0027 % Revision history
0028 %   Jan 2014: Beta version including the correct nesting format
0029 %==============================================================================
0030
0031 clear;
0032 subname = 'create_nesting_nodes';
0033
0034 global ftbverbose;
0035 if(ftbverbose);
0036   fprintf('\n')
0037   fprintf(['begin : ' subname '\n'])
0038 end
0039
0040 %---------------------------------------------------------
0041 % user specify input data & parameters ...
0042 %---------------------------------------------------------
0043 % work & data folders ...
0044 workDir='\\hand-fs-01\maritime\Projects\Scottish Waters\Calcs\Models\WLLS\mesh10\nesting\';
0045 dataDir='\\hand-fs-01\maritime\Projects\Scottish Waters\Calcs\Models\WLLS\mesh10\mesh\';
0046 basename = 'WLLS_v3smth';
0047 % input file names
0048 meshFile=[basename '_grd.dat'];
0049 obcFile=[basename '_obc.dat'];
0050
0051 % output file
0052 NestNodesFile = [basename '_node_nest.dat'];
0053
0054 %---------------------------------------------------------
0055 % set full file names ...
0056 %---------------------------------------------------------
0057 meshFile     = [dataDir meshFile];
0058 obcFile      = [dataDir obcFile];
0059 NestNodesFile     = [workDir NestNodesFile];
0060 checkfile(meshFile);
0061 checkfile(obcFile);
0062
0063 %---------------------------------------------------------
0064 % Read data into matlab
0065 % 1) grid mesh; 2)boundary nodes; ...
0066 %---------------------------------------------------------
0067 % get fvcom grid file in as mesh object ...
0068 FV_Mesh = read_fvcom_mesh_lonlat(meshFile);        % ... from matlab toolbox
0069
0070 % get wave nesting nodes and associated lat/lon coord file
0071 FV_OBC = get_HD_OBC(obcFile);
0072
0073 %---------------------------------------------------------------------
0074 % get elements at boundary & element centres
0075 %---------------------------------------------------------------------
0076 % get elements at boundary
0077 T = FV_Mesh.tri;
0078 X1 = FV_Mesh.lon;
0079 Y1 = FV_Mesh.lat;
0080 P = [X1,Y1];
0081 TR = triangulation(T,P);
0082 vi = FV_OBC.nnodesID;
0083 ti = vertexAttachments(TR,vi);
0084 % arrange as column data; since elements overlap, get unique elements
0085 temp1 = [ti{:}]';
0086 % bdcell = unique(temp1,'stable');
0087 bdcell = unique(temp1);
0088 nCells = numel(bdcell);
0089
0090 nElems = nCells;
0091 bdElem = bdcell;
0092
0093 % get element nodes & arrange in required format
0094 nv= zeros(3*nElems,1);
0095 k = 1;
0096 for i=1:nElems
0097     ielem = bdElem(i);
0098     nv(k)   = FV_Mesh.tri(ielem,1);
0099     nv(k+1) = FV_Mesh.tri(ielem,2);
0100     nv(k+2) = FV_Mesh.tri(ielem,3);
0101     k = k+3;
0102 end
0103
0104 % I don't think preserving the order is the problem - remove next line
0105 % nestNodeID= unique(nv,'stable');
0106 nestNodeID= unique(nv);
0107 nestNodes = numel(nestNodeID);
0108 out = ones(nestNodes,3);
0109 for i=1:nestNodes
0110     out(i,1) = i;
0111     out(i,2) = nestNodeID(i);
0112 end
0113
0114 %------------------------------------------------------------------------------
0115 % Dump the file
0116 %------------------------------------------------------------------------------
0117
0118 filename = NestNodesFile;
0119 if(ftbverbose); fprintf('writing FVCOM obc %s\n',filename); end;
0120
0121 %------------------------------------------------------------------------------
0122 % Check output file
0123 %------------------------------------------------------------------------------
0124 fid = fopen(filename,'w');
0125 fprintf(fid,'Nest_Node Number = %12d\n',nestNodes);
0126 fprintf(fid,'No.           Node_ID            Node_Type\n');
0127 for i=1:nestNodes
0128     fprintf(fid,'%12d %12d %12d\n',out(i,:));
0129 end
0130
0131 fclose(fid);
0132
0133 disp('finished creating nesting file');

<address>Generated on Wed 20-Feb-2019 16:06:01 by m2html © 2005</address>


text:
'use strict'

module.exports = {
  extends: [
    './core/legacy',
    './plugin-node',
    './plugin-unicorn',
  ].map(require.resolve),
  parserOptions: {
    ecmaVersion: 5,
    sourceType: 'script',
  },
  env: {
    node: true,
    browser: true,
  },
  rules: {
    'unicorn/no-for-loop': 'off',
    'unicorn/prefer-array-find': 'off',
    'unicorn/prefer-array-flat-map': 'off',
    'unicorn/prefer-includes': 'off',
    'unicorn/prefer-math-trunc': 'off',
    'unicorn/prefer-number-properties': 'off',
    'unicorn/prefer-optional-catch-binding': 'off',
    'unicorn/prefer-string-replace-all': 'off',
    'unicorn/prefer-string-starts-ends-with': 'off',
    'comma-dangle': [ 'error', 'always-multiline' ],
    'func-names': [ 'error', 'always' ],
    'prefer-exponentiation-operator': 'off',
  },
}


text:
rpm --import https://yum.puppetlabs.com/RPM-GPG-KEY-puppet

rpm -aq |grep puppetlabs-release 1>/dev/null || zypper install -y https://yum.puppetlabs.com/puppetlabs-release-pc1-sles-12.noarch.rpm

rpm -q puppet-agent || zypper install -y puppet-agent

test -x /bin/puppet || ln -s /opt/puppetlabs/bin/puppet /bin/puppet


text:
//
//  Copyright 2011-2016 Twilio. All rights reserved.
//
//  Use of this software is subject to the terms and conditions of the
//  Twilio Terms of Service located at http://www.twilio.com/legal/tos
//

#import <Foundation/Foundation.h>

#import "TCDeviceDelegate.h"
#import "TCConnectionDelegate.h"

/*!
 *
 * TCDeviceState represents the various states of the device's ability to listen for incoming connections and make outgoing connections.
 * The TCDeviceDelegate gets notified of the state changes.
 *
 */
typedef NS_ENUM(NSInteger, TCDeviceState)
{
    /*! TCDevice The device is not connected and cannot receive incoming connections or make outgoing connections. */
    TCDeviceStateOffline = 0,

    /*! TCDevice can receive incoming connections and attempt outgoing connections if capabilities allow. */
    TCDeviceStateReady,

    /*! TCDevice is connected to the network and has an active connection. No additional connections can be created or accepted. */
    TCDeviceStateBusy
};

/*!
 *
 * @name Device capability keys
 *
 * These keys can retrieve values from the TCDevice.capabilities dictionary.
 * The values are extracted from the Capability Token that is used to initialize a TCDevice.
 *
 */
/*! NSNumber of BOOL that indicates whether the device can receive incoming calls. */
extern NSString * __nonnull const TCDeviceCapabilityIncomingKey;

/*! NSNumber of BOOL that indicates whether the device can make outgoing calls. */
extern NSString * __nonnull const TCDeviceCapabilityOutgoingKey;

/*! NSNumber of long long that represents the time the device's capability token expires (number of seconds relative to the UNIX epoch). */
extern NSString * __nonnull const TCDeviceCapabilityExpirationKey;

/*! NSString representing the account SID. */
extern NSString * __nonnull const TCDeviceCapabilityAccountSIDKey;

/*! The application SID used when making an outgoing call. Only present if TCDeviceCapabilityOutgoingKey is also present with a YES value. */
extern NSString * __nonnull const TCDeviceCapabilityApplicationSIDKey;

/*! A non-modifiable NSDictionary of key/value pairs that will be passed to the Twilio Application when making an outgoing call. Only present if TCDeviceCapabilityOutgoingKey is also present with a YES value and the Capability Token contains application parameters. Additional parameters may be specified in the connect:delegate: method if needed. */
extern NSString * __nonnull const TCDeviceCapabilityApplicationParametersKey;

/*! NSString representing the client name. */
extern NSString * __nonnull const TCDeviceCapabilityClientNameKey;

@class TCConnection;

/*!
 *
 * An instance of TCDevice is an object that knows how to interface with Twilio Services.
 *
 * A TCDevice is the primary entry point for Twilio Client. An iOS application should initialize a TCDevice with the initWithCapabilityToken:delegate: method with a Capability Token to talk to Twilio services.
 *
 * A Capability Token is a JSON Web Token (JWT) that specifies what the TCDevice may do with respect to the Twilio Application, such as whether it can make outgoing calls, how long the token and the TCDevice are valid before needing to be refreshed, and so on. Please visit http://www.twilio.com/docs/client/capability-tokens for more information.
 *
 * @see TCDeviceDelegate
 *
 */
@interface TCDevice : NSObject

/*!
 *
 * Current status of the TCDevice.
 *
 * State changes will cause relevant methods to be called in TCDeviceDelegate and will include any NSErrors that occur.
 *
 * @see TCDeviceState
 *
 */
@property (nonatomic, assign, readonly) TCDeviceState state;

/*!
 *
 * Current capabilities of the TCDevice. The keys are defined by the "Device capability keys" constants.
 *
 */
@property (weak, nonatomic, readonly, nullable) NSDictionary <NSString *, id> *capabilities;

/*!
 *
 * The delegate object which will receive events from a TCDevice object.
 *
 * @see TCDeviceDelegate
 *
 */
@property (nonatomic, weak, nullable) id<TCDeviceDelegate> delegate;

/*!
 *
 * A BOOL indicating if a sound should be played for an incoming connection.
 *
 * The default value is YES. See the Twilio Client iOS Usage Guide for more information on sounds.
 *
 */
@property (nonatomic, assign) BOOL incomingSoundEnabled;

/*!
 *
 * A BOOL indicating if a sound should be played for an outgoing connection.
 *
 * The default value is YES. See the Twilio Client iOS Usage Guide for more information on sounds.
 *
 */
@property (nonatomic, assign) BOOL outgoingSoundEnabled;

/*!
 *
 * A BOOL indicating if a sound should be played when a connection is disconnected for any reason.
 *
 * The default value is YES. See the Twilio Client iOS Usage Guide for more information on sounds.
 *
 */
@property (nonatomic, assign) BOOL disconnectSoundEnabled;

/*!
 *
 * Initialize a new TCDevice object. If the incoming capabilities are defined, then the device will automatically begin listening for incoming connections.
 *
 * @param capabilityToken A signed JSON Web Token that defines the features available to the TCDevice. These may be created using the Twilio Helper Libraries included with the SDK or available at http://www.twilio.com . The capabilities are used to begin listening for incoming connections and provide the default parameters used for establishing outgoing connections. Please visit http://www.twilio.com/docs/client/capability-tokens for more information.
 * @param delegate The delegate object which will receive events from a TCDevice object.
 *
 * @returns The initialized receiver
 *
 * @see updateCapabilityToken:
 *
 */
- (nullable id)initWithCapabilityToken:(nonnull NSString *)capabilityToken delegate:(nullable id<TCDeviceDelegate>)delegate;

/*!
 *
 * Start TCDevice to listen for incoming connections.
 *
 * The TCDevice will automatically listen for incoming connections on method calls to initWithCapabilityToken:delegate: or updateCapabilityToken: if the token allows.
 *
 * This method only needs to be called if unlisten was previously called.
 *
 */
- (void)listen;

/*!
 *
 * Stop the device from listening for incoming connections. This could be used for a "silence" mode on the your iOS application, for instance.
 *
 * This method will do nothing if the TCDevice is currently not listening, either because of a previous call to unlisten or because the TCDevice has not been granted the incoming capability.
 *
 */
- (void)unlisten;

/*!
 *
 * Update the capabilities of the TCDevice.
 *
 * There may be circumstances when the defined capabilities have expired. For example, the TCDevice may enter the TCDeviceStateOffline state because the capabilities have expired. In these cases, the capabilities will need to be updated. If the device is currently listening for incoming connections, it will restart the listening process (if permitted) using these updated capabilities.
 *
 * Existing connections are not affected by updating the capability token.
 *
 * @param capabilityToken A signed JWT that defines the capability token available to the TCDevice. Please visit http://www.twilio.com/docs/client/capability-tokens for more information on capability tokens.
 *
 */
- (void)updateCapabilityToken:(nonnull NSString *)capabilityToken;

/*!
 *
 * Create an outgoing connection.
 *
 * @param parameters An optional dictionary containing parameters for the outgoing connection that get passed to your Twilio Application. These parameters are merged with any parameters supplied in the Capability Token (e.g. the dictionary retrived with the TCDeviceCapabilityApplicationParametersKey against the capabilities property). If there are any key collisions with the two dictionaries, the value(s) from TCDeviceCapabilityApplicationParametersKey dictionary will take precedence. Parameters other than NSString are ignored.
 * @param delegate An optional delegate object to receive callbacks when state changes occur to the TCConnection object.
 *
 * @returns A TCConnection object representing the new outgoing connection. If TCConnection is nil, the connection could not be initialized.
 *
 * @see TCConnectionDelegate
 *
 */
- (nullable TCConnection *)connect:(nullable NSDictionary <NSString *, NSString *> *)parameters delegate:(nullable id<TCConnectionDelegate>)delegate;

/*!
 *
 * Disconnect all current connections associated with the receiver.
 *
 * This is a convenient method that disconnects all current incoming and outgoing connections, including pending incoming connections.
 *
 */
- (void)disconnectAll;

@end


text:
package com.twu.menuactions;

public interface MenuActionPerformed {
    void compute(String userId);
}


text:
title: Typography
description: Module for providing typography styles for basic HTML elements
group: Generics
---

[[example file=scss/generics/typography/example/document.html]]

## Variables

[[variables file=scss/generics/typography/_variables.scss]]

## Standalone installation

Install package using NPM.

```bash
$ npm install @bemoid/typography
```

Import required mixins along with a component file from the `node_modules` directory.

```scss
@import 'node_modules/@bemoid/typography/typography';
```


text:
<?php

namespace App\Notifications;

use App\Comment;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;

class ReceivedComment extends Notification implements ShouldQueue
{
    use Queueable;

    protected $comment;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct(Comment $comment)
    {
        $this->comment = $comment;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['database', 'mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        $comment = $this->comment;

        $type = lang(substr(ucfirst($comment->commentable_type), 0, -1));

        $message = lang('Comment Content', [
            'type' => strtolower($type),
            'title' => $comment->commentable->title,
            'user' => $comment->user->name]);

        $url = ($comment->commentable_type == 'articles')
                ? url('article', ['slug'=>$comment->commentable->slug])
                : url('discussion', ['id' => $comment->commentable->id]);

        $data = [
            'username' => $notifiable->name,
            'message'  => $message,
            'content'  => json_decode($comment->content)->raw,
            'url' => $url
        ];

        return (new MailMessage)
                    ->subject(lang('New Comment', ['type' => strtolower($type)]))
                    ->markdown('mail.receive.comment', $data);
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return $this->comment->toArray();
    }
}


text:
package com.sirius.upns.protocol.transfer;

import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * @project protocol
 * @date 2013-8-18-上午11:48:54
 * @author pippo
 */
public class TransferPacket implements Serializable {

	private static final long serialVersionUID = 4733297481691463582L;

	public static final int SIZE_LENGTH = 4;

	public static final int SIZE_PACKET = (1 << 16) - 1;

	public TransferPacket(Payload payload) throws Exception {
		this.body = payload.getBytes();
		this.length = body.length + SIZE_LENGTH;
	}

	/* header */
	private final int length;

	/* body */
	private byte[] body;

	public byte[] toBytes() {
		ByteBuffer buffer = ByteBuffer.allocate(length);
		buffer.putInt(length);
		buffer.put(body);
		return buffer.array();
	}

	@Override
	public String toString() {
		return String.format("TransferPacket [length=%s, body=%s]", length, Arrays.toString(body));
	}

}


text:
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE ExplicitForAll        #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeApplications      #-}
module Language.Java.Parser (
    P, ParseError,
    Parsable(..),

    parseCompilationUnit, parser, parserS,

    compilationUnitNode, compilationUnit, packageDeclParser, importDecl, typeDeclParser,

    classDeclParser, interfaceDeclParser,

    memberDecl, fieldDecl, methodDecl, constrDecl,
    interfaceMemberDecl, absMethodDecl,

    formalParams, formalParam,

    modifier,

    varDecls, varDecl,

    blockParser, blockStmt, stmt,

    stmtExp, expParser, primaryParser, literalParser,

    ttype, primType, refType, classType, resultType, typeDeclSpecifier,

    lambdaExp, methodRef,

    typeParams, typeParam,

    name, ident,

    empty, list, list1, seplist, seplist1, opt, bopt, lopt,

    comma, semiColon, period, colon

    ) where

import           Language.Java.Lexer         (L (..), Token (..), lexer)
import           Language.Java.Position
import           Language.Java.Pretty        (pretty)
import           Language.Java.Java

import           Text.Parsec                 hiding (Empty)
import           Text.Parsec.Pos

import           Data.Char                   (toLower)
import           Data.Maybe                  (catMaybes, fromMaybe, isJust,
                                              listToMaybe, maybe)
import           Prelude                     hiding ((>>), (>>=))
import qualified Prelude                     as P ((>>), (>>=))

import           Control.Applicative         ((<$), (<$>), (<*), (<*>))
import           Control.Monad               (foldM)

type P = Parsec [L Token] ()

-- A trick to allow >> and >>=, normally infixr 1, to be
-- used inside branches of <|>, which is declared as infixl 1.
-- There are no clashes with other operators of precedence 2.
(>>) = (P.>>)
(>>=) = (P.>>=)
infixr 2 >>, >>=
-- Note also when reading that <$> is infixl 4 and thus has
-- lower precedence than all the others (>>, >>=, and <|>).

-- Parsing class for type parameter

class Parsable l where
    toParser :: P (l -> a) -> P a

instance Parsable Segment where
    toParser pConstr = do
        start <- getPosition
        result <- pConstr
        end <- getPosition
        let segmt = sourcePosToSegment start end
        return (result segmt)

tP :: (Parsable l) => P (l -> a) -> P a
tP = toParser

(<$$>) :: (Parsable l) => (l -> a -> b) -> P a -> P (l -> b)
(<$$>) constr pa = (flip constr) <$> pa
infixl 4 <$$>

(<**>) :: (Parsable l) => P (l -> a -> b) -> P a -> P (l -> b)
(<**>) pconstr pa = flip <$> pconstr <*> pa
infixl 4 <**>

returnN :: (Monad m, HasNode a b) => (l -> a l) -> m (l -> b l)
returnN a = return $ \l -> toNode (a l)

returnN' :: (Monad m, HasNode a b) => a l -> m (b l)
returnN' a = return $ toNode a

wrap :: (Applicative f, HasNode a b) => f (a l) -> f (b l)
wrap = fmap toNode

wrapP :: (Parsable l, HasNode a b) => P (l -> a l) -> P (b l)
wrapP = tP . wrapL

wrapL :: (Applicative f, HasNode a b) => f (l -> (a l)) -> f (l -> (b l))
wrapL a = (\a l -> toNode (a l)) <$> a

wrapM :: (Applicative f, HasNode a b) => f (Mod l (a l)) -> f (Mod l (b l))
wrapM a = (\a ms l -> toNode (a ms l)) <$> a

wrapE :: forall b a f l. (Applicative f, HasNode a b) => f (Exp l (a l)) -> f (Exp l (b l))
wrapE a = (\a e l -> toNode (a e l)) <$> a

----------------------------------------------------------------------------
-- Top-level parsing

parseCompilationUnit :: String -> Either ParseError (CompilationUnitNode Segment)
parseCompilationUnit inp =
    runParser compilationUnitNode () "" (lexer inp)

parserS :: P (a Segment) -> String -> Either ParseError (a Segment)
parserS = parser

parser :: P a -> String -> Either ParseError a
parser p = runParser p () "" . lexer

unsafeParser :: P a -> String -> a
unsafeParser p s = let (Right x) = parser p s in x

----------------------------------------------------------------------------
-- Packages and compilation units

compilationUnitNode :: Parsable l => P (CompilationUnitNode l)
compilationUnitNode = try (wrap moduleDeclaration)
        <|> wrap compilationUnit

compilationUnit :: Parsable l => P (CompilationUnit l)
compilationUnit = tP $ do
    mpd <- opt packageDeclParser
    ids <- list importDecl
    tds <- list typeDeclParser
    eof
    return $ \l -> CompilationUnit l mpd ids (catMaybes tds)

moduleDeclaration :: Parsable l => P (ModuleDeclaration l)
moduleDeclaration = tP $ do
    -- only tokens in module descriptions!
    (Ident "module") <- ident
    modulePackageP <- fullQualiPkg
    moduleSpecsP <- braces $ list moduleSpecParser
    return $ \l -> ModuleDeclaration l modulePackageP moduleSpecsP

packageDeclParser :: (Parsable l) => P (PackageDecl l)
packageDeclParser = tP $ do
    tok KW_Package
    pkg <- fullQualiPkg
    semiColon
    return $ flip PackageDecl pkg

moduleSpecParser :: (Parsable l) => P (ModuleSpecNode l)
moduleSpecParser = tP $ try (do
        -- only tokens in module descriptions!
        (Ident "requires") <- ident
        reqMod <- fullQualiPkg
        semiColon
        returnN $ flip ModuleRequires reqMod)
    <|> do
        (Ident "exports") <- ident
        exportsPkg <- fullQualiPkg
        semiColon
        returnN $ flip ModuleExports exportsPkg

importDecl :: (Parsable l) => P (ImportDecl l)
importDecl = tP $ do
    tok KW_Import
    st <- bopt $ tok KW_Static
    pkg  <- seplist1 ident period
    ds <- bopt $ period >> tok Op_Star
    let package = if ds then WildcardPackage pkg else FullQualiPackage pkg
    semiColon
    return $ \l -> ImportDecl l st package

typeDeclParser :: (Parsable l) => P (Maybe (TypeDeclNode l))
typeDeclParser = Just <$> classOrInterfaceDecl <|>
            const Nothing <$> semiColon

----------------------------------------------------------------------------
-- Declarations

-- Class declarations

classOrInterfaceDecl :: (Parsable l) => P (TypeDeclNode l)
classOrInterfaceDecl = tP $ do
    ms <- list modifier
    de <- (wrapM classDeclParser) <|>
          wrapM annInterfaceDecl <|> wrapM interfaceDeclParser
    return $ de ms

classDeclParser :: (Parsable l) => P (Mod l (ClassDeclNode l))
classDeclParser = wrapM normalClassDecl <|> wrapM enumClassDecl

normalClassDecl :: (Parsable l) => P (Mod l (ClassDecl l))
normalClassDecl = do
    tok KW_Class
    i   <- ident
    tps <- lopt typeParams
    mex <- opt extendsParser
    imp <- lopt implementsParsre
    bod <- classBodyParser
    return $ \ms l -> ClassDecl l ms i tps (fmap head mex) imp bod

extendsParser :: (Parsable l) => P [Extends l]
extendsParser = tok KW_Extends >> (map (uncurry Extends)) <$> refTypeList

implementsParsre :: (Parsable l) => P [Implements l]
implementsParsre = tok KW_Implements >> (map (uncurry Implements)) <$> refTypeList

enumClassDecl :: (Parsable l) => P (Mod l (EnumDecl l))
enumClassDecl = do
    tok KW_Enum
    i   <- ident
    imp <- lopt implementsParsre
    bod <- enumBodyParser
    return $ \ms l -> EnumDecl l ms i imp bod

classBodyParser :: (Parsable l) => P (ClassBody l)
classBodyParser = tP $ (flip ClassBody) <$> braces classBodyStatements

enumBodyParser :: (Parsable l) => P (EnumBody l)
enumBodyParser = tP $ braces $ do
    ecs <- seplist enumConst comma
    optional comma
    eds <- lopt enumBodyDecls
    return $ \l -> EnumBody l ecs eds

enumConst :: (Parsable l) => P (EnumConstant l)
enumConst = tP $ do
    idt  <- ident
    as  <- lopt args
    mcb <- opt classBodyParser
    return $ \l -> EnumConstant l idt as mcb

enumBodyDecls :: (Parsable l) => P [DeclNode l]
enumBodyDecls = semiColon >> classBodyStatements

classBodyStatements :: (Parsable l) => P [DeclNode l]
classBodyStatements = catMaybes <$> list classBodyStatement

-- Interface declarations

annInterfaceDecl :: (Parsable l) => P (Mod l (InterfaceDecl l))
annInterfaceDecl = do
    tok KW_AnnInterface
    idt  <- ident
    tps <- lopt typeParams
    exs <- lopt extendsParser
    bod <- interfaceBodyParser
    return $ \ms l -> InterfaceDecl l InterfaceAnnotation ms idt tps exs bod

interfaceDeclParser :: (Parsable l) => P (Mod l (InterfaceDecl l))
interfaceDeclParser = do
    tok KW_Interface
    idt  <- ident
    tps <- lopt typeParams
    exs <- lopt extendsParser
    bod <- interfaceBodyParser
    return $ \ms l -> InterfaceDecl l InterfaceNormal ms idt tps exs bod

interfaceBodyParser :: (Parsable l) => P (InterfaceBody l)
interfaceBodyParser = tP $ (\m l -> InterfaceBody l $ catMaybes m) <$> braces (list interfaceBodyDecl)

-- Declarations

classBodyStatement :: (Parsable l) => P (Maybe (DeclNode l))
classBodyStatement = tP $
    try (do
       _ <- list1 semiColon
       return $ const Nothing) <|>
    try ( do
       mst <- bopt (tok KW_Static)
       blk <- blockParser
       return $ \l ->  Just $ toNode $ InitDecl l mst blk) <|>
    (do ms  <- list modifier
        dec <- memberDecl
        return $ \l -> Just $ toNode $ dec ms l)

memberDecl :: (Parsable l) => P (Mod l (MemberDeclNode l))
memberDecl =
    try (wrapM classDeclParser) <|>
    try (wrapM $ annInterfaceDecl <|> try interfaceDeclParser) <|>
    try (wrapM fieldDecl) <|>
    try (wrapM methodDecl) <|>
    wrapM constrDecl

fieldDecl :: (Parsable l) => P (Mod l (FieldDecl l))
fieldDecl = endSemi $ do
    typ <- ttype
    vds <- varDecls
    return $ \ms l -> FieldDecl l ms typ vds

methodDecl :: (Parsable l) => P (Mod l (MethodDecl l))
methodDecl = do
    tps <- lopt typeParams
    rt  <- resultType
    idt  <- ident
    fps <- formalParams
    thr <- lopt throws
    bod <- methodBodyParser
    return $ \ms l -> MethodDecl l ms tps rt idt fps thr Nothing bod

methodBodyParser :: (Parsable l) => P (MethodBody l)
methodBodyParser = tP $ (flip MethodBody) <$>
    (const Nothing <$> semiColon <|> Just <$> blockParser)

constrDecl :: (Parsable l) => P (Mod l (ConstructorDecl l))
constrDecl = do
    tps <- lopt typeParams
    idt  <- ident
    fps <- formalParams
    thr <- lopt throws
    bod <- constrBodyParser
    return $ \ms l -> ConstructorDecl l ms tps idt fps thr bod

constrBodyParser :: (Parsable l) => P (ConstructorBody l)
constrBodyParser = tP $ braces $ do
    mec <- opt (try explConstrInv)
    bss <- list blockStmt
    return $ \l -> ConstructorBody l mec bss

explConstrInv :: forall l. (Parsable l) => P (ExplConstrInvNode l)
explConstrInv = tP $ endSemi $
    try ( do
        tas <- (map snd) <$> lopt (refTypeArgs @l)
        tok KW_This
        as  <- args
        returnN $ \l -> ThisInvoke l tas as) <|>
    try ( do
        tas <- (map snd) <$> lopt (refTypeArgs @l)
        tok KW_Super
        as  <- args
        returnN $ \l -> SuperInvoke l tas as) <|>
    (do pri <- primaryParser
        period
        tas <- (map snd) <$> lopt (refTypeArgs @l)
        tok KW_Super
        as  <- args
        returnN $ \l -> PrimarySuperInvoke l pri tas as)

-- TODO: This should be parsed like class bodies, and post-checked.
--       That would give far better error messages.
interfaceBodyDecl :: (Parsable l) => P (Maybe (MemberDeclNode l))
interfaceBodyDecl = (semiColon >> return Nothing) <|>
    tP (do
        ms  <- list modifier
        imd <- interfaceMemberDecl
        return $ \l -> Just (imd ms l))

interfaceMemberDecl :: (Parsable l) => P (Mod l (MemberDeclNode l))
interfaceMemberDecl =
    (wrapM classDeclParser) <|>
    (wrapM (try annInterfaceDecl <|> try interfaceDeclParser)) <|>
    try (wrapM fieldDecl) <|>
    wrapM absMethodDecl

absMethodDecl :: (Parsable l) => P (Mod l (MethodDecl l))
absMethodDecl = do
    tps <- lopt typeParams
    rt  <- resultType
    idt  <- ident
    fps <- formalParams
    thr <- lopt throws
    def <- opt defaultValue
    body <- try (methodBodyParser) <|> (tP $ semiColon >> return (flip MethodBody Nothing))
    return $ \ms l -> MethodDecl l ms tps rt idt fps thr def body

throws :: (Parsable l) => P [ExceptionType l]
throws = (map $ uncurry ExceptionType) <$> (tok KW_Throws >> refTypeList)

defaultValue :: (Parsable l) => P (ExpNode l)
defaultValue = tok KW_Default >> expParser

-- Formal parameters

formalParams :: (Parsable l) => P [FormalParam l]
formalParams = parens $ do
    fps <- seplist formalParam comma
    if validateFPs fps
     then return fps
     else fail "Only the last formal parameter may be of variable arity"
  where validateFPs :: [FormalParam l] -> Bool
        validateFPs [] = True
        validateFPs [_] = True
        validateFPs (FormalParam _ _ _ b _ :_) = not b

formalParam :: (Parsable l) => P (FormalParam l)
formalParam = tP $ do
    ms  <- list modifier
    typ <- ttype
    var <- bopt ellipsis
    vid <- varDeclId
    return $ \l -> FormalParam l ms typ var vid

ellipsis :: P ()
ellipsis = period >> period >> period

-- Modifiers

modifier :: (Parsable l) => P (Modifier l)
modifier = tP (
        tok KW_Public      >> return Public
    <|> tok KW_Protected   >> return Protected
    <|> tok KW_Private     >> return Private
    <|> tok KW_Abstract    >> return Abstract
    <|> tok KW_Static      >> return Static
    <|> tok KW_Strictfp    >> return StrictFP
    <|> tok KW_Final       >> return Final
    <|> tok KW_Native      >> return Native
    <|> tok KW_Transient   >> return Transient
    <|> tok KW_Volatile    >> return Volatile
    <|> tok KW_Synchronized >> return Synchronized_
    <|> tok KW_Default >> return DefaultModifier )
    <|> wrap annotationParser

annotationParser :: (Parsable l) => P (Annotation l)
annotationParser = flip ($) <$ tok Op_AtSign <*> name <*> (
               try (flip NormalAnnotation <$> parens evlist)
           <|> try (flip SingleElementAnnotation <$> parens elementValue)
           <|> try (MarkerAnnotation <$ return ())
        )

evlist :: (Parsable l) => P [(Ident, ElementValue l)]
evlist = seplist1 elementValuePair comma

elementValuePair :: (Parsable l) => P (Ident, ElementValue l)
elementValuePair = (,) <$> ident <* tok Op_Equal <*> elementValue

elementValue :: (Parsable l) => P (ElementValue l)
elementValue =
    tP $ (EVVal <$$> ( (wrap arrayInit)
               <|> wrap condExp ))
    <|> EVAnn <$$> annotationParser

----------------------------------------------------------------------------
-- Variable declarations

varDecls :: (Parsable l) => P [VarDecl l]
varDecls = seplist1 varDecl comma

varDecl :: (Parsable l) => P (VarDecl l)
varDecl = tP $ do
    vid <- varDeclId
    mvi <- opt $ tok Op_Equal >> varInitParser
    return $ \l -> VarDecl l vid mvi

varDeclId :: (Parsable l) => P (VarDeclIdNode l)
varDeclId = do
    initID <- (tP . return) (\l e -> toNode $ VarId l e)
    idt <- ident
    brkts <- list arrBrackets
    return $ foldl (\f _ -> VarDeclArrayNode . f) initID brkts idt

arrBrackets :: P ()
arrBrackets = brackets $ return ()

localVarDecl :: (Parsable l) => P ([Modifier l], Type, [VarDecl l])
localVarDecl = do
    ms  <- list modifier
    typ <- ttype
    vds <- varDecls
    return (ms, typ, vds)

varInitParser :: (Parsable l) => P (VarInitNode l)
varInitParser =
    wrap arrayInit <|>
    wrap expParser

arrayInit :: (Parsable l) => P (ArrayInit l)
arrayInit = tP $ braces $ do
    vis <- seplist varInitParser comma
    _ <- opt comma
    return $ \l -> ArrayInit l vis

----------------------------------------------------------------------------
-- Statements

blockParser :: (Parsable l) => P (Block l)
blockParser = tP $ braces $ (flip Block) <$> list blockStmt

blockStmt :: (Parsable l) => P (BlockStmtNode l)
blockStmt =
    tP ( try ( do
        ms  <- list modifier
        cd  <- classDeclParser
        returnN $ cd ms) <|>
    try ( do
        (m,t,vds) <- endSemi localVarDecl
        returnN $ \l -> LocalVars l m t vds)) <|>
    (wrap stmt)

stmt :: (Parsable l) => P (StmtNode l)
stmt = tP (ifStmt <|> whileStmt <|> forStmt <|> labeledStmtParser) <|> stmtNoTrail
  where
    ifStmt = do
        tok KW_If
        e  <- parens expParser
        th <- stmtNSI
        el <- optionMaybe $ tok KW_Else >> stmt
        returnN $ \l -> IfThenElse l e th el
    whileStmt = do
        tok KW_While
        e   <- parens expParser
        s   <- stmt
        returnN $ \l -> While l e s
    forStmt = do
        tok KW_For
        f <- parens $
            try ( do
                fi <- opt forInitParser
                semiColon
                e  <- opt expParser
                semiColon
                fu <- opt forUp
                return $ \s l -> toNode $ BasicFor l fi e fu s) <|>
            (do ms <- list modifier
                t  <- ttype
                i  <- ident
                colon
                e  <- expParser
                return $ \s l -> toNode $ EnhancedFor l ms t i e s)
        s <- stmt
        return $ f s
    labeledStmtParser = try $ do
        lbl <- ident
        colon
        s   <- stmt
        returnN $ \l -> Labeled l lbl s

stmtNSI :: (Parsable l) => P (StmtNode l)
stmtNSI = tP (ifStmt <|> whileStmt <|> forStmt <|> labeledStmtParser) <|> stmtNoTrail
  where
    ifStmt = do
        tok KW_If
        e  <- parens expParser
        th <- stmtNSI
        el <- optionMaybe $ tok KW_Else >> stmtNSI
        returnN $ \l -> IfThenElse l e th el
    whileStmt = do
        tok KW_While
        e <- parens expParser
        s <- stmtNSI
        returnN $ \l -> While l e s
    forStmt = do
        tok KW_For
        f <- parens $ try ( do
                fi <- opt forInitParser
                semiColon
                e  <- opt expParser
                semiColon
                fu <- opt forUp
                return $ \s l -> toNode $ BasicFor l fi e fu s)
            <|> (do
                ms <- list modifier
                t  <- ttype
                i  <- ident
                colon
                e  <- expParser
                return $ \s l -> toNode $ EnhancedFor l ms t i e s)
        s <- stmtNSI
        return $ f s
    labeledStmtParser = try $ do
        i <- ident
        colon
        s <- stmtNSI
        returnN $ \l -> Labeled l i s

stmtNoTrail :: (Parsable l) => P (StmtNode l)
stmtNoTrail = tP (
    -- empty statement
    try ((toNode . Empty) <$ semiColon) <|>
    -- assertions
    endSemi ( do
        tok KW_Assert
        e   <- expParser
        me2 <- opt $ colon >> expParser
        returnN $ \l -> Assert l e me2) <|>
    -- switch stmts
    (do tok KW_Switch
        e  <- parens expParser
        sb <- switchBlock
        returnN $ \l -> Switch l e sb) <|>
    -- do-while loops
    endSemi (do
        tok KW_Do
        s <- stmt
        tok KW_While
        e <- parens expParser
        returnN $ \l -> Do l s e) <|>
    -- break
    endSemi (do
        tok KW_Break
        mi <- opt ident
        returnN $ \l -> Break l mi) <|>
    -- continue
    endSemi (do
        tok KW_Continue
        mi <- opt ident
        returnN $ \l -> Continue l mi) <|>
    -- return
    endSemi (do
        tok KW_Return
        me <- opt expParser
        returnN $ \l -> Return l me) <|>
    -- synchronized
    (do tok KW_Synchronized
        e <- parens expParser
        b <- blockParser
        returnN $ \l -> Synchronized l e b) <|>
    -- throw
    endSemi (do
        tok KW_Throw
        e <- expParser
        returnN $ \l -> Throw l e) <|>
    -- try-catch, both with and without a finally clause
    (do tok KW_Try
        res <- fromMaybe [] <$> optionMaybe (parens tryResources)
        b <- blockParser
        c <- list catch
        mf <- opt $ tok KW_Finally >> blockParser
        -- TODO: here we should check that there exists at
        -- least one catch or finally clause
        returnN $ \l -> Try l res b c mf)) <|>
    -- inner blockParser
    (wrap blockParser) <|>
    -- expressions as stmts
    wrap (endSemi stmtExp)

-- For loops

forInitParser :: (Parsable l) => P (ForInitNode l)
forInitParser = tP $ try (do
                        (m,t,vds) <- localVarDecl
                        returnN $ \l -> ForLocalVars l m t vds) <|>
    (wrapL $ (flip ForInitExps) <$> seplist1 stmtExp comma)

forUp :: (Parsable l) => P [ExpNode l]
forUp = seplist1 stmtExp comma

-- Switches

switchBlock :: (Parsable l) => P [SwitchBlock l]
switchBlock = braces $ list switchStmt

switchStmt :: (Parsable l) => P (SwitchBlock l)
switchStmt = tP $ do
    lbl <- switchLabelParser
    bss <- list $ blockStmt
    return $ \l -> SwitchBlock l lbl bss

switchLabelParser :: (Parsable l) => P (SwitchLabelNode l)
switchLabelParser = (tP $ tok KW_Default >> colon >> return DefaultNode) <|>
    (do tok KW_Case
        e <- expParser
        colon
        return $ toNode e)

-- Try-catch clauses

tryResources :: (Parsable l) => P [TryResourceNode l]
tryResources = seplist tryRes semiColon
    where
      tryRes = tP $ try (do
            mods <- list modifier
            ty <- refType
            vars <- varDecls
            returnN $ \l -> TryResourceVar l mods ty vars
        ) <|> (wrapL $ TryResourceFinalVar <$$> ident)

catch :: (Parsable l) => P (Catch l)
catch = tP $ do
    tok KW_Catch
    fp <- parens formalParam
    b  <- blockParser
    return $ \l -> Catch l fp b

----------------------------------------------------------------------------
-- Expressions

stmtExp :: (Parsable l) => P (ExpNode l)
stmtExp = try preIncDec
    <|> try postIncDec
    <|> try (wrap assignment)
    -- There are sharing gains to be made by unifying these two
    <|> try (methodInvocationExp)
    <|> try lambdaExp
    <|> try methodRef
    <|> instanceCreation

preIncDec :: (Parsable l) => P (ExpNode l)
preIncDec = do
    op <- preIncDecOp
    e <- unaryExp
    return $ op e

postIncDec :: (Parsable l) => P (ExpNode l)
postIncDec = do
    e <- postfixExpNES
    ops <- list1 postfixOp
    return $ foldl (\a s -> s a) e ops

assignment :: (Parsable l) => P (Assign l)
assignment = tP $ do
    lh <- lhs
    op <- assignOpParser
    e  <- assignExp
    return $ \l -> Assign l lh op e

lhs :: (Parsable l) => P (LhsNode l)
lhs = try (wrap fieldAccessParser)
    <|> try (wrap arrayAccess)
    <|> (wrapP $ NameLhs <$$> name)

expParser :: (Parsable l) => P (ExpNode l)
expParser = assignExp

assignExp :: (Parsable l) => P (ExpNode l)
assignExp = try methodRef <|> try lambdaExp <|> try(wrap assignment) <|> condExp

condExp :: (Parsable l) => P (ExpNode l)
condExp = do
    ie <- infixExp
    ces <- (list . tP) ((\c l e -> toNode $ c e l) <$> condExpSuffix)
    return $ foldl (\a s -> s a) ie ces

condExpSuffix :: (Parsable l) => P (Exp l (Cond l))
condExpSuffix =  do
    tok Op_Query
    th <- expParser
    colon
    el <- condExp
    return $ \ce l -> Cond l ce th el

infixExp :: (Parsable l) => P (ExpNode l)
infixExp = infixExpWithOperators infixOperators

-- See Note [Parsing operators]
infixExpWithOperators :: (Parsable l) => [P Op] -> P (ExpNode l)
infixExpWithOperators [] = unaryExp
infixExpWithOperators (op : ops) = do
    ue <- infixExpWithOperators ops
    ies <- (list . tP) (flip <$> (infixExpSuffix op ops))
    return $ foldl (\a s -> s a) ue ies

infixExpSuffix :: (Parsable l) => P Op -> [P Op] -> P (Exp l (ExpNode l))
infixExpSuffix infixOp ops =
    (wrapE $ do
        op <- infixOp
        e2 <- infixExpWithOperators ops
        return $ \e1 l -> BinOp l e1 op e2) <|>

    -- FIXME 'instanceof' should have the same precedence as relational operators
    (wrapE $ tok KW_Instanceof >> (\t e1 l -> InstanceOf l e1 t) <$> refType)

unaryExp :: (Parsable l) => P (ExpNode l)
unaryExp = try preIncDec <|>
    try (do
        op <- prefixOp
        ue <- unaryExp
        return $ op ue) <|>
    try (tP $ do
        t <- parens ttype
        e <- unaryExp
        returnN $ \l -> Cast l t e) <|>
    postfixExp

postfixExpNES :: (Parsable l) => P (ExpNode l)
postfixExpNES = primaryParser

postfixExp :: (Parsable l) => P (ExpNode l)
postfixExp = do
    pe <- postfixExpNES
    ops <- list postfixOp
    return $ foldl (\a s -> s a) pe ops

primaryParser :: (Parsable l) => P (ExpNode l)
primaryParser = primaryNPS |>> primarySuffix

primaryNPS :: (Parsable l) => P (ExpNode l)
primaryNPS = try arrayCreation <|> primaryNoNewArrayNPS

-- primaryNoNewArray = startSuff primaryNoNewArrayNPS primarySuffix

primaryNoNewArrayNPS :: (Parsable l) => P (ExpNode l)
primaryNoNewArrayNPS =
    (wrapP $ Lit <$$> literalParser) <|>
    (wrapP $ This <$ tok KW_This) <|>
    parens expParser <|>
    -- TODO: These two following should probably be merged more
    try (tP $  do
        rt <- resultType
        period >> tok KW_Class
        returnN $ \l -> ClassLit l rt) <|>
    try (tP $ do
        t <- ttype
        period >> tok KW_This
        returnN $ \l -> QualifiedThis l t) <|>
    try (wrap instanceCreationNPS) <|>
    try (wrap methodInvocationNPS) <|>
    try (wrap fieldAccessNPS) <|>
    try (wrapP $ ExpName <$$> name) <|>
    wrap arrayAccessNPS

primarySuffix :: (Parsable l) => P (Exp l (ExpNode l))
primarySuffix = try (wrapE instanceCreationSuffix) <|>
    try (wrapE arrayAccessSuffix) <|>
    try ((wrapE . wrapE @MethodInvocationNode) methodInvocationSuffix) <|>
    ((wrapE . wrapE @FieldAccessNode) fieldAccessSuffix)

instanceCreationNPS :: (Parsable l) => P (InstanceCreation l)
instanceCreationNPS = tP $
    do tok KW_New
       tas <- lopt typeArgsParser
       tds <- typeDeclSpecifier
       as  <- args
       mcb <- opt classBodyParser
       return $ \l -> InstanceCreation l tas tds as mcb

typeDeclSpecifier :: P TypeDeclSpecifier
typeDeclSpecifier = TypeDeclSpecifier <$> classType

instanceCreationSuffix :: (Parsable l) => P (Exp l (QualInstanceCreation l))
instanceCreationSuffix =
    do  period >> tok KW_New
        tas <- lopt typeArgsParser
        i   <- ident
        as  <- args
        mcb <- opt classBodyParser
        return $ \p l -> QualInstanceCreation l p tas i as mcb

instanceCreation :: (Parsable l) => P (ExpNode l)
instanceCreation = try (wrap instanceCreationNPS) <|> do
    p <- primaryNPS
    ss <- (list . tP) (flip <$> primarySuffix)
    let icp = foldl (\a s -> s a) p ss
    case icp of
     QualInstanceCreationNode {} -> return icp
     _ -> fail ""

lambdaParamsParser :: (Parsable l) => P (LambdaParamsNode l)
lambdaParamsParser = tP ( try (wrapL $ LambdaSingleParam <$$> ident)
               <|> try ( (parens . wrapL) $ LambdaFormalParams <$$> seplist formalParam comma)
               <|> (parens . wrapL) (LambdaInferredParams <$$> seplist ident comma ))

lambdaExp :: (Parsable l) => P (ExpNode l)
lambdaExp = wrapP $ Lambda <$$> (lambdaParamsParser <* tok LambdaArrow)
            <**> (((try . wrap) blockParser)
                 <|> (wrap expParser))

methodRef :: (Parsable l) => P (ExpNode l)
methodRef = tP $ do
                n <- name
                tok MethodRefSep
                i <- ident
                returnN $ \l -> MethodRef l n i

{-
instanceCreation =
    (do tok KW_New
        tas <- lopt typeArgsParser
        ct  <- classType
        as  <- args
        mcb <- opt classBodyParser
        return $ InstanceCreation tas ct as mcb) <|>
    (do p   <- primaryParser
        period >> tok KW_New
        tas <- lopt typeArgsParser
        i   <- ident
        as  <- args
        mcb <- opt classBodyParser
        return $ QualInstanceCreation p tas i as mcb)
-}

fieldAccessNPS :: (Parsable l) => P (FieldAccessNode l)
fieldAccessNPS = tP $
    (do tok KW_Super >> period
        i <- ident
        returnN $ \l -> SuperFieldAccess l i) <|>
    (do n <- name
        period >> tok KW_Super >> period
        i <- ident
        returnN $ \l -> ClassFieldAccess l n i)

fieldAccessSuffix :: (Parsable l) => P (Exp l (PrimaryFieldAccess l))
fieldAccessSuffix = do
    period
    i <- ident
    return $ \p l -> PrimaryFieldAccess l p i

fieldAccessParser :: (Parsable l) => P (FieldAccessNode l)
fieldAccessParser = try fieldAccessNPS <|> do
    p <- primaryNPS
    ss <- (list . tP) (flip <$> primarySuffix)
    let fap = foldl (\a s -> s a) p ss
    case fap of
     FieldAccessNode fa -> return fa
     _ -> fail ""

{-
fieldAccessParser :: P FieldAccess
fieldAccessParser = try fieldAccessNPS <|> do
    p <- primaryParser
    fs <- fieldAccessSuffix
    return (fs p)
-}

{-
fieldAccessParser :: P FieldAccess
fieldAccessParser =
    (do tok KW_Super >> period
        i <- ident
        return $ SuperFieldAccess i) <|>
    (try $ do
        n <- name
        period >> tok KW_Super >> period
        i <- ident
        return $ ClassFieldAccess n i) <|>
    (do p <- primaryParser
        period
        i <- ident
        return $ PrimaryFieldAccess p i)
-}

methodInvocationNPS :: forall l. (Parsable l) => P (MethodInvocationNode l)
methodInvocationNPS = tP $
    (do tok KW_Super >> period
        rts <- (map snd) <$> lopt (refTypeArgs @l)
        i   <- ident
        as  <- args
        returnN $ \l -> SuperMethodCall l rts i as) <|>
    (do n <- name
        f <- (do as <- args
                 return $ \na l -> toNode $ MethodCall l na as) <|>
             (period >> do
                msp <- opt (tok KW_Super >> period)
                rts <- (map snd) <$> lopt (refTypeArgs @l)
                i   <- ident
                as  <- args
                let typeM = \na l -> toNode $ TypeMethodCall l na rts i as
                let classM = const $ \na l -> toNode $ ClassMethodCall l na rts i as
                return $ maybe typeM classM msp)
        return $ f n)

methodInvocationSuffix :: forall l. (Parsable l) => P (Exp l (PrimaryMethodCall l))
methodInvocationSuffix = do
        period
        _ <- lopt (refTypeArgs @l)
        i   <- ident
        as  <- args
        return $ \p l -> PrimaryMethodCall l p [] i as

methodInvocationExp :: (Parsable l) => P (ExpNode l)
methodInvocationExp = try (do
    p <- primaryNPS
    ss <- (list . tP) (flip <$> primarySuffix)
    let mip = foldl (\a s -> s a) p ss
    case mip of
     MethodInvNode _ -> return mip
     _ -> fail "") <|>
     (wrap methodInvocationNPS)

{-
methodInvocation :: P MethodInvocation
methodInvocation =
    (do tok KW_Super >> period
        rts <- lopt refTypeArgs
        i   <- ident
        as  <- args
        return $ SuperMethodCall rts i as) <|>
    (do p <- primaryParser
        period
        rts <- lopt refTypeArgs
        i   <- ident
        as  <- args
        return $ PrimaryMethodCall p rts i as) <|>
    (do n <- name
        f <- (do as <- args
                 return $ \n -> MethodCall n as) <|>
             (period >> do
                msp <- opt (tok KW_Super >> period)
                rts <- lopt refTypeArgs
                i   <- ident
                as  <- args
                let mc = maybe TypeMethodCall (const ClassMethodCall) msp
                return $ \n -> mc n rts i as)
        return $ f n)
-}

args :: (Parsable l) => P [Argument l]
args = parens $ seplist expParser comma

-- Arrays

arrayAccessNPS :: (Parsable l) => P (ArrayIndex l)
arrayAccessNPS = tP $ do
    n <- wrap $ tP $ (flip ExpName) <$> name
    e <- list1 $ brackets expParser
    return $ \l -> ArrayIndex l n e

arrayAccessSuffix :: (Parsable l) => P (Exp l (ArrayIndex l))
arrayAccessSuffix = do
    e <- list1 $ brackets expParser
    return $ \ref l -> ArrayIndex l ref e

arrayAccess :: (Parsable l) => P (ArrayIndex l)
arrayAccess = try arrayAccessNPS <|> do
    p <- primaryNoNewArrayNPS
    ss <- (list . tP) (flip <$> primarySuffix)
    let aap = foldl (\a s -> s a) p ss
    case aap of
     ArrayAccessNode ain -> return ain
     _ -> fail ""

{-
arrayAccess :: P (Exp, Exp)
arrayAccess = do
    ref <- arrayRef
    e   <- brackets expParser
    return (ref, e)

arrayRef :: P Exp
arrayRef = ExpName <$> name <|> primaryNoNewArray
-}

arrayCreation :: (Parsable l) => P (ExpNode l)
arrayCreation = tP $ do
    tok KW_New
    t <- nonArrayType
    f <- try (do
             ds <- list1 $ brackets empty
             ai <- arrayInit
             return $ \tt l -> toNode $ ArrayCreateInit l tt (length ds) ai) <|>
         (do des <- list1 $ try $ brackets expParser
             ds  <- list  $ brackets empty
             return $ \tt l -> toNode $ ArrayCreate l tt des (length ds))
    return $ f t

literalParser :: P Literal
literalParser =
    javaToken $ \t -> case t of
        IntTok     i -> Just (Int i)
        LongTok    l -> Just (Word l)
        DoubleTok  d -> Just (Double d)
        FloatTok   f -> Just (Float f)
        CharTok    c -> Just (Char c)
        StringTok  s -> Just (String s)
        BoolTok    b -> Just (Boolean b)
        NullTok      -> Just Null
        _ -> Nothing

-- Operators

preIncDecOp, prefixOp, postfixOp :: (Parsable l) => P (ExpNode l -> ExpNode l)
preIncDecOp =
    (tok Op_PPlus >> return PreIncrementNode) <|>
    (tok Op_MMinus >> return PreDecrementNode)
prefixOp =
    (tok Op_Bang  >> return PreNotNode ) <|>
    (tok Op_Tilde >> return PreBitComplNode ) <|>
    (tok Op_Plus  >> return PrePlusNode ) <|>
    (tok Op_Minus >> return PreMinusNode )
postfixOp =
    (tok Op_PPlus  >> return PostIncrementNode ) <|>
    (tok Op_MMinus >> return PostDecrementNode )

assignOpParser :: P AssignOp
assignOpParser =
    (tok Op_Equal    >> return EqualA   ) <|>
    (tok Op_StarE    >> return MultA    ) <|>
    (tok Op_SlashE   >> return DivA     ) <|>
    (tok Op_PercentE >> return RemA     ) <|>
    (tok Op_PlusE    >> return AddA     ) <|>
    (tok Op_MinusE   >> return SubA     ) <|>
    (tok Op_LShiftE  >> return LShiftA  ) <|>
    (tok Op_RShiftE  >> return RShiftA  ) <|>
    (tok Op_RRShiftE >> return RRShiftA ) <|>
    (tok Op_AndE     >> return AndA     ) <|>
    (tok Op_CaretE   >> return XorA     ) <|>
    (tok Op_OrE      >> return OrA      )

-- The infix operators, grouped by precedence.
-- See Note [Parsing operators]
infixOperators :: [P Op]
infixOperators =
  [ tok Op_OOr     >> return COr

  , tok Op_AAnd    >> return CAnd

  , tok Op_Or      >> return Or

  , tok Op_Caret   >> return Xor

  , tok Op_And     >> return And

  , (tok Op_Equals  >> return Equal     ) <|>
    (tok Op_BangE   >> return NotEq     )

  , (tok Op_LThan   >> return LThan     ) <|>
    (tok Op_GThan   >> return GThan     ) <|>
    (tok Op_LThanE  >> return LThanE    ) <|>
    (tok Op_GThanE  >> return GThanE    )

  , (tok Op_LShift  >> return LShift    ) <|>
    try (do
       tok Op_GThan
       tok Op_GThan
       tok Op_GThan
       return RRShift ) <|>

    try (do
       tok Op_GThan
       tok Op_GThan
       return RShift )

  , (tok Op_Plus    >> return Add       ) <|>
    (tok Op_Minus   >> return Sub       )

  , (tok Op_Star    >> return Mult      ) <|>
    (tok Op_Slash   >> return Div       ) <|>
    (tok Op_Percent >> return Rem       )
  ]

{-
Note [Parsing operators]
~~~~~~~~~~~~~~~~~~~~~~~~
Each entry in 'infixOperators' generates one level of recursion in
'infixExpWithOperators'. This generates a grammar similar to:

@
  ConditionalOrExpression ::=
    ConditionalAndExpression [ "||" ConditionalOrExpression ]

  ConditionalAndExpression ::=
    InclusiveOrExpression [ "&&" ConditionalAndExpression ]

  // and so on...
@

but the operators associate to the left.

A similar (but more general) pattern can be found in 'Text.Parsec.Expr'.
-}

----------------------------------------------------------------------------
-- Types

ttype :: P Type
ttype = try (RefType <$> refType) <|> PrimType <$> primType

primType :: P PrimType
primType =
    tok KW_Boolean >> return BooleanT  <|>
    tok KW_Byte    >> return ByteT     <|>
    tok KW_Short   >> return ShortT    <|>
    tok KW_Int     >> return IntT      <|>
    tok KW_Long    >> return LongT     <|>
    tok KW_Char    >> return CharT     <|>
    tok KW_Float   >> return FloatT    <|>
    tok KW_Double  >> return DoubleT

refType :: P RefType
refType =
    (do pt <- primType
        (_:bs) <- list1 arrBrackets
        return $ foldl (\f _ -> ArrayType . RefType . f)
                        (ArrayType . PrimType) bs pt) <|>
    (do ct <- classType
        bs <- list arrBrackets
        return $ foldl (\f _ -> ArrayType . RefType . f)
                            ClassRefType bs ct) <?> "refType"

nonArrayType :: P Type
nonArrayType = PrimType <$> primType <|>
    (RefType . ClassRefType <$> classType)

classType :: P ClassType
classType = toClassType <$> parseClass
    where
        toClassType :: [(Ident, [TypeArgument])] -> ClassType
        toClassType = constructClassType . stripEmpty . split
        split = span (\(idt, _) -> maybe False (\a -> a == toLower a) ((listToMaybe . fromIdent) idt))
        stripEmpty (a, b) = (map fst a, b)
        constructClassType (a, b) = if null a
                then WithoutPackage (ClassName b)
                else WithPackage (FullQualiPackage a) (ClassName b)

        parseClass = sepListEndOptBy (classTypeSpec typeArgsParser) (classTypeSpec typeArgsWithDiamond) period

        typeArgsWithDiamond = try typeArgsParser <|> (:[]) <$> typeDiamond

classTypeSpec :: P [TypeArgument] -> P (Ident, [TypeArgument])
classTypeSpec argsP = do
    i   <- ident
    tas <- lopt argsP
    return (i, tas)

resultType :: P (Maybe Type)
resultType = tok KW_Void >> return Nothing <|> Just <$> ttype <?> "resultType"

refTypeList :: (Parsable l) => P [(l, RefType)]
refTypeList = seplist1 (tP $ (\r l -> (l, r)) <$> refType) comma

----------------------------------------------------------------------------
-- Type parameters and arguments

typeParams :: P [TypeParam]
typeParams = angles $ seplist1 typeParam comma

typeParam :: P TypeParam
typeParam = do
    i  <- ident
    bs <- lopt bounds
    return $ TypeParam i bs

bounds :: P [RefType]
bounds = tok KW_Extends >> seplist1 refType (tok Op_And)

typeArgsParser :: P [TypeArgument]
typeArgsParser = angles $ seplist1 typeArg comma

typeArg :: P TypeArgument
typeArg = tok Op_Query >> Wildcard <$> opt wildcardBound
    <|> ActualType <$> refType

typeDiamond :: P TypeArgument
typeDiamond = angles $ pure Diamond

wildcardBound :: P WildcardBound
wildcardBound = tok KW_Extends >> ExtendsBound <$> refType
    <|> tok KW_Super >> SuperBound <$> refType

refTypeArgs :: forall l. (Parsable l) => P [(l, RefType)]
refTypeArgs = angles refTypeList

----------------------------------------------------------------------------
-- Names

name :: P Name
name = Name <$> seplist1 ident period

ident :: P Ident
ident = javaToken $ \t -> case t of
    IdentTok s -> Just $ Ident s
    _ -> Nothing

----------------------------------------------------------------------------
-- Package

fullQualiPkg :: P Package
fullQualiPkg = FullQualiPackage <$> seplist1 ident period

wildcardPkg :: P Package
wildcardPkg = WildcardPackage <$> seplist1 ident period
------------------------------------------------------------

empty :: P ()
empty = return ()

opt :: P a -> P (Maybe a)
opt = optionMaybe

bopt :: P a -> P Bool
bopt p = opt p >>= \ma -> return $ isJust ma

lopt :: P [a] -> P [a]
lopt p = do mas <- opt p
            case mas of
             Nothing -> return []
             Just as -> return as

list :: P a -> P [a]
list = option [] . list1

list1 :: P a -> P [a]
list1 = many1

seplist :: P a -> P sep -> P [a]
--seplist = sepBy
seplist p sep = option [] $ seplist1 p sep

seplist1 :: P a -> P sep -> P [a]
--seplist1 = sepBy1
seplist1 p sep =
    p >>= \a ->
        try (do _ <- sep
                as <- seplist1 p sep
                return (a:as))
        <|> return [a]

sepListEndOptBy :: P a -> P a -> P sep -> P [a]
sepListEndOptBy p end sep =
        try (p >>= \a ->
            try (do _ <- sep
                    as <- sepListEndOptBy p end sep
                    return (a:as))
            <|> return [a])
        <|> ((:[]) <$> end)

startSuff, (|>>) :: Parsable l => P a -> P (a -> l -> a) -> P a
startSuff start suffix = do
    x <- start
    ss <- (list . tP) (flip <$> suffix)
    return $ foldl (\a s -> s a) x ss

(|>>) = startSuff

------------------------------------------------------------

javaToken :: (Token -> Maybe a) -> P a
javaToken testTok = token showT posT testT
  where showT (L _ t) = show t
        posT  (L p _) = pos2sourcePos p
        testT (L _ t) = testTok t

tok, matchToken :: Token -> P ()
tok = matchToken
matchToken t = javaToken (\r -> if r == t then Just () else Nothing)

pos2sourcePos :: (Int, Int) -> SourcePos
pos2sourcePos (l,c) = newPos "" l c

type Mod l a = [Modifier l] -> l -> a
type Exp l a = ExpNode l -> l -> a

parens, braces, brackets, angles :: P a -> P a
parens   = between (tok OpenParen)  (tok CloseParen)
braces   = between (tok OpenCurly)  (tok CloseCurly)
brackets = between (tok OpenSquare) (tok CloseSquare)
angles   = between (tok Op_LThan)   (tok Op_GThan)

endSemi :: P a -> P a
endSemi p = p >>= \a -> semiColon >> return a

comma, colon, semiColon, period :: P ()
comma     = tok Comma
colon     = tok Op_Colon
semiColon = tok SemiColon
period    = tok Period

------------------------------------------------------------

test = "public class Foo { }"
testFile file = do
  i <- readFile file
  let r = parseCompilationUnit i
  putStrLn$ either (("Parsing error:\n"++) . show) (show . pretty) r


text:
function foo ( {
  // maybe a ) missing ?
}