You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rh...@apache.org on 2010/01/20 17:38:18 UTC

svn commit: r901268 - in /qpid/trunk/qpid/java/common: bin/ src/main/java/org/apache/qpid/messaging/ src/main/java/org/apache/qpid/messaging/util/

Author: rhs
Date: Wed Jan 20 16:38:18 2010
New Revision: 901268

URL: http://svn.apache.org/viewvc?rev=901268&view=rev
Log:
added java address parser (QPID-1831)

Added:
    qpid/trunk/qpid/java/common/bin/qpid-jaddr   (with props)
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/Address.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/AddressParser.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/JAddr.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LexError.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexer.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexicon.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LineInfo.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/ParseError.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Parser.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Token.java

Added: qpid/trunk/qpid/java/common/bin/qpid-jaddr
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/bin/qpid-jaddr?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/bin/qpid-jaddr (added)
+++ qpid/trunk/qpid/java/common/bin/qpid-jaddr Wed Jan 20 16:38:18 2010
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+if [ -z "$QPID_HOME" ]; then
+    export QPID_HOME=$(dirname $(dirname $(readlink -f $0)))
+    export PATH=${PATH}:${QPID_HOME}/bin
+fi
+
+# Set classpath to include Qpid jar with all required jars in manifest
+QPID_LIBS=$QPID_HOME/lib/qpid-all.jar
+
+# Set other variables used by the qpid-run script before calling
+export JAVA=java \
+       QPID_CLASSPATH=$QPID_LIBS
+
+. qpid-run org.apache.qpid.messaging.util.JAddr "$@"

Propchange: qpid/trunk/qpid/java/common/bin/qpid-jaddr
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/Address.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/Address.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/Address.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/Address.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,67 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging;
+
+import java.util.Map;
+
+import org.apache.qpid.messaging.util.AddressParser;
+
+
+/**
+ * Address
+ *
+ */
+
+public class Address
+{
+
+    public static Address parse(String address)
+    {
+        return new AddressParser(address).parse();
+    }
+
+    private String name;
+    private String subject;
+    private Map options;
+
+    public Address(String name, String subject, Map options)
+    {
+        this.name = name;
+        this.subject = subject;
+        this.options = options;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public String getSubject()
+    {
+        return subject;
+    }
+
+    public Map getOptions()
+    {
+        return options;
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/AddressParser.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/AddressParser.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/AddressParser.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/AddressParser.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,370 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.messaging.Address;
+
+
+/**
+ * AddressParser
+ *
+ */
+
+public class AddressParser extends Parser
+{
+
+    private static Lexicon lxi = new Lexicon();
+
+    private static Token.Type LBRACE = lxi.define("LBRACE", "\\{");
+    private static Token.Type RBRACE = lxi.define("RBRACE", "\\}");
+    private static Token.Type LBRACK = lxi.define("LBRACK", "\\[");
+    private static Token.Type RBRACK = lxi.define("RBRACK", "\\]");
+    private static Token.Type COLON = lxi.define("COLON", ":");
+    private static Token.Type SEMI = lxi.define("SEMI", ";");
+    private static Token.Type SLASH = lxi.define("SLASH", "/");
+    private static Token.Type COMMA = lxi.define("COMMA", ",");
+    private static Token.Type NUMBER = lxi.define("NUMBER", "[+-]?[0-9]*\\.?[0-9]+");
+    private static Token.Type ID = lxi.define("ID", "[a-zA-Z_](?:[a-zA-Z0-9_-]*[a-zA-Z0-9_])?");
+    private static Token.Type STRING = lxi.define("STRING", "\"(?:[^\\\"]|\\.)*\"|'(?:[^\\']|\\.)*'");
+    private static Token.Type ESC = lxi.define("ESC", "\\\\[^ux]|\\\\x[0-9a-fA-F][0-9a-fA-F]|\\\\u[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]");
+    private static Token.Type SYM = lxi.define("SYM", "[.#*%@$^!+-]");
+    private static Token.Type WSPACE = lxi.define("WSPACE", "[\\s]+");
+    private static Token.Type EOF = lxi.eof("EOF");
+
+    private static Lexer LEXER = lxi.compile();
+
+    public static List<Token> lex(String input)
+    {
+        return LEXER.lex(input);
+    }
+
+    static List<Token> wlex(String input)
+    {
+        List<Token> tokens = new ArrayList<Token>();
+        for (Token t : lex(input))
+        {
+            if (t.getType() != WSPACE)
+            {
+                tokens.add(t);
+            }
+        }
+        return tokens;
+    }
+
+    static String unquote(String st, Token tok)
+    {
+        StringBuilder result = new StringBuilder();
+        for (int i = 1; i < st.length() - 1; i++)
+        {
+            char ch = st.charAt(i);
+            if (ch == '\\')
+            {
+                char code = st.charAt(i+1);
+                switch (code)
+                {
+                case '\n':
+                    break;
+                case '\\':
+                    result.append('\\');
+                    break;
+                case '\'':
+                    result.append('\'');
+                    break;
+                case '"':
+                    result.append('"');
+                    break;
+                case 'a':
+                    result.append((char) 0x07);
+                    break;
+                case 'b':
+                    result.append((char) 0x08);
+                    break;
+                case 'f':
+                    result.append('\f');
+                    break;
+                case 'n':
+                    result.append('\n');
+                    break;
+                case 'r':
+                    result.append('\r');
+                    break;
+                case 't':
+                    result.append('\t');
+                    break;
+                case 'u':
+                    result.append(decode(st.substring(i+2, i+6)));
+                    i += 4;
+                    break;
+                case 'v':
+                    result.append((char) 0x0b);
+                    break;
+                case 'o':
+                    result.append(decode(st.substring(i+2, i+4), 8));
+                    i += 2;
+                    break;
+                case 'x':
+                    result.append(decode(st.substring(i+2, i+4)));
+                    i += 2;
+                    break;
+                default:
+                    throw new ParseError(tok);
+                }
+                i += 1;
+            }
+            else
+            {
+                result.append(ch);
+            }
+        }
+
+        return result.toString();
+    }
+
+    static char[] decode(String hex)
+    {
+        return decode(hex, 16);
+    }
+
+    static char[] decode(String code, int radix)
+    {
+        return Character.toChars(Integer.parseInt(code, radix));
+    }
+
+    static String tok2str(Token tok)
+    {
+        Token.Type type = tok.getType();
+        String value = tok.getValue();
+
+        if (type == STRING)
+        {
+            return unquote(value, tok);
+        }
+        else if (type == ESC)
+        {
+            if (value.charAt(1) == 'x' || value.charAt(1) == 'u')
+            {
+                return new String(decode(value.substring(2)));
+            }
+            else
+            {
+                return value.substring(1);
+            }
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    static Object tok2obj(Token tok)
+    {
+        Token.Type type = tok.getType();
+        String value = tok.getValue();
+        if (type == STRING)
+        {
+            return unquote(value, tok);
+        }
+        else if (type == NUMBER)
+        {
+            if (value.indexOf('.') >= 0)
+            {
+                return Double.valueOf(value);
+            }
+            else
+            {
+                return Integer.decode(value);
+            }
+        }
+        else
+        {
+            return value;
+        }
+    }
+
+    static String toks2str(List<Token> toks)
+    {
+        if (toks.size() > 0)
+        {
+            StringBuilder result = new StringBuilder();
+            for (Token t : toks)
+            {
+                result.append(tok2str(t));
+            }
+            return result.toString();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public AddressParser(String input)
+    {
+        super(wlex(input));
+    }
+
+    public Address parse()
+    {
+        Address result = address();
+        eat(EOF);
+        return result;
+    }
+
+    public Address address()
+    {
+        String name = toks2str(eat_until(SLASH, SEMI, EOF));
+
+        if (name == null)
+        {
+            throw new ParseError(next());
+        }
+
+        String subject;
+        if (matches(SLASH))
+        {
+            eat(SLASH);
+            subject = toks2str(eat_until(SEMI, EOF));
+        }
+        else
+        {
+            subject = null;
+        }
+
+        Map options;
+        if (matches(SEMI))
+        {
+            eat(SEMI);
+            options = map();
+        }
+        else
+        {
+            options = null;
+        }
+
+        return new Address(name, subject, options);
+    }
+
+    public Map<Object,Object> map()
+    {
+        eat(LBRACE);
+
+        Map<Object,Object> result = new HashMap<Object,Object>();
+        while (true)
+        {
+            if (matches(NUMBER, STRING, ID, LBRACE, LBRACK))
+            {
+                keyval(result);
+                if (matches(COMMA))
+                {
+                    eat(COMMA);
+                }
+                else if (matches(RBRACE))
+                {
+                    break;
+                }
+                else
+                {
+                    throw new ParseError(next(), COMMA, RBRACE);
+                }
+            }
+            else if (matches(RBRACE))
+            {
+                break;
+            }
+            else
+            {
+                throw new ParseError(next(), NUMBER, STRING, ID, LBRACE, LBRACK,
+                                     RBRACE);
+            }
+        }
+
+        eat(RBRACE);
+        return result;
+    }
+
+    void keyval(Map<Object,Object> map)
+    {
+        Object key = value();
+        eat(COLON);
+        Object val = value();
+        map.put(key, val);
+    }
+
+    Object value()
+    {
+        if (matches(NUMBER, STRING, ID))
+        {
+            return tok2obj(eat());
+        }
+        else if (matches(LBRACE))
+        {
+            return map();
+        }
+        else if (matches(LBRACK))
+        {
+            return list();
+        }
+        else
+        {
+            throw new ParseError(next(), NUMBER, STRING, ID, LBRACE, LBRACK);
+        }
+    }
+
+    List<Object> list()
+    {
+        eat(LBRACK);
+
+        List<Object> result = new ArrayList<Object>();
+
+        while (true)
+        {
+            if (matches(RBRACK))
+            {
+                break;
+            }
+            else
+            {
+                result.add(value());
+                if (matches(COMMA))
+                {
+                    eat(COMMA);
+                }
+                else if (matches(RBRACK))
+                {
+                    break;
+                }
+                else
+                {
+                    throw new ParseError(next(), COMMA, RBRACK);
+                }
+            }
+        }
+
+        eat(RBRACK);
+        return result;
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/JAddr.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/JAddr.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/JAddr.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/JAddr.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,203 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import java.io.InputStreamReader;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.messaging.Address;
+import org.apache.qpid.messaging.util.ParseError;
+import org.apache.qpid.messaging.util.Token;
+
+
+/**
+ * JAddr
+ *
+ */
+
+public class JAddr
+{
+
+    public static final void main(String[] args) throws Exception
+    {
+        StringBuilder addr = new StringBuilder();
+        InputStreamReader reader = new InputStreamReader(System.in);
+
+        char[] buf = new char[1024];
+        while (true)
+        {
+            int n = reader.read(buf, 0, buf.length);
+            if (n < 0)
+            {
+                break;
+            }
+            addr.append(buf, 0, n);
+        }
+
+        if ("parse".equals(args[0]))
+        {
+            try
+            {
+                Address address = Address.parse(addr.toString());
+                System.out.println(pprint_address(address));
+            }
+            catch (ParseError e)
+            {
+                System.out.println(String.format("ERROR: %s", e.getMessage()));
+            }
+        }
+        else
+        {
+            List<Token> tokens = AddressParser.lex(addr.toString());
+            for (Token t : tokens)
+            {
+                String value = t.getValue();
+                if (value != null)
+                {
+                    value = value.replace("\\", "\\\\").replace("\n", "\\n");
+                    System.out.println(String.format("%s:%s:%s", t.getType(), t.getPosition(), value));
+                }
+                else
+                {
+                    System.out.println(String.format("%s:%s", t.getType(), t.getPosition()));
+                }
+            }
+        }
+    }
+
+    private static String pprint_address(Address addr)
+    {
+        return String.format("NAME: %s\nSUBJECT: %s\nOPTIONS: %s",
+                             pprint(addr.getName()),
+                             pprint(addr.getSubject()),
+                             pprint(addr.getOptions()));
+    }
+
+    private static String pprint(Object obj)
+    {
+        if (obj instanceof Map)
+        {
+            return pprint_map((Map) obj);
+        }
+        else if (obj instanceof List)
+        {
+            return pprint_list((List) obj);
+        }
+        else if (obj instanceof String)
+        {
+            return pprint_string((String) obj);
+        }
+        else if (obj == null)
+        {
+            return "None";
+        }
+        else
+        {
+            return obj.toString();
+        }
+    }
+
+    private static String indent(String st)
+    {
+        return "  " + st.replace("\n", "\n  ");
+    }
+
+    private static String pprint_map(Map<Object,Object> map)
+    {
+        List<String> items = new ArrayList<String>();
+        for (Map.Entry me : map.entrySet())
+        {
+            items.add(String.format("%s: %s", pprint(me.getKey()),
+                                    pprint(me.getValue())));
+        }
+        Collections.sort(items);
+        return pprint_items("{", items, "}");
+    }
+
+    private static String pprint_list(List list)
+    {
+        List<String> items = new ArrayList<String>();
+        for (Object o : list)
+        {
+            items.add(pprint(o));
+        }
+        return pprint_items("[", items, "]");
+    }
+
+    private static String pprint_items(String start, List<String> items,
+                                       String end)
+    {
+        StringBuilder result = new StringBuilder();
+        for (String item : items)
+        {
+            if (result.length() > 0)
+            {
+                result.append(",\n");
+            }
+            result.append(indent(item));
+        }
+
+        if (result.length() > 0)
+        {
+            return String.format("%s\n%s\n%s", start, result, end);
+        }
+        else
+        {
+            return String.format("%s%s", start, end);
+        }
+    }
+
+    private static String pprint_string(String st)
+    {
+        StringBuilder result = new StringBuilder();
+        result.append('\'');
+        for (int i = 0; i < st.length(); i++)
+        {
+            char c = st.charAt(i);
+            switch (c)
+            {
+            case '\'':
+                result.append("\\'");
+                break;
+            case '\n':
+                result.append("\\n");
+                break;
+            default:
+                if (c >= 0x80)
+                {
+                    result.append(String.format("\\u%04x", (int)c));
+                }
+                else
+                {
+                    result.append(c);
+                }
+                break;
+            }
+        }
+        result.append('\'');
+        return result.toString();
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LexError.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LexError.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LexError.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LexError.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,37 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+
+/**
+ * LexError
+ *
+ */
+
+public class LexError extends RuntimeException
+{
+
+    public LexError(String msg)
+    {
+        super(msg);
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexer.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexer.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexer.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexer.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,84 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Lexer
+ *
+ */
+
+public class Lexer
+{
+
+    private List<Token.Type> types;
+    private Token.Type eof;
+    private Pattern rexp;
+
+    public Lexer(List<Token.Type> types, Token.Type eof, Pattern rexp)
+    {
+        this.types = types;
+        this.eof = eof;
+        this.rexp = rexp;
+    }
+
+    public List<Token> lex(final String st)
+    {
+        List<Token> tokens = new ArrayList<Token>();
+
+        int position = 0;
+        Matcher m = rexp.matcher(st);
+        OUTER: while (position < st.length())
+        {
+            m.region(position, st.length());
+            if (m.lookingAt())
+            {
+                for (int i = 1; i <= m.groupCount(); i++)
+                {
+                    String value = m.group(i);
+                    if (value != null)
+                    {
+                        tokens.add(new Token(types.get(i-1), value, st, m.start(i)));
+                        position = m.end(i);
+                        continue OUTER;
+                    }
+                }
+                throw new RuntimeException("no group matched");
+            }
+            else
+            {
+                throw new LexError("unrecognized characters line:" + LineInfo.get(st, position));
+            }
+        }
+
+        tokens.add(new Token(eof, null, st, position));
+
+        return tokens;
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexicon.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexicon.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexicon.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Lexicon.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+
+/**
+ * Lexicon
+ *
+ */
+
+public class Lexicon
+{
+
+    private List<Token.Type> types;
+    private Token.Type eof;
+
+    public Lexicon()
+    {
+        this.types = new ArrayList<Token.Type>();
+        this.eof = null;
+    }
+
+    public Token.Type define(String name, String pattern)
+    {
+        Token.Type t = new Token.Type(name, pattern);
+        types.add(t);
+        return t;
+    }
+
+    public Token.Type eof(String name)
+    {
+        Token.Type t = new Token.Type(name, null);
+        eof = t;
+        return t;
+    }
+
+    public Lexer compile()
+    {
+        String joined = "";
+        for (Token.Type t : types)
+        {
+            if (joined.length() > 0)
+            {
+                joined += "|";
+            }
+            joined += "(" + t.getPattern() + ")";
+        }
+        Pattern rexp = Pattern.compile(joined);
+        return new Lexer(new ArrayList<Token.Type>(types), eof, rexp);
+    }
+
+    public static final void main(String[] args)
+    {
+        String input = "";
+        for (String a : args)
+        {
+            if (input.length() > 0)
+            {
+                input += " ";
+            }
+
+            input += a;
+        }
+
+        Lexicon lxi = new Lexicon();
+        lxi.define("FOR", "for");
+        lxi.define("IF", "if");
+        lxi.define("LPAREN", "\\(");
+        lxi.define("RPAREN", "\\)");
+        lxi.define("ID", "[\\S]+");
+        lxi.define("WSPACE", "[\\s]+");
+        lxi.eof("EOF");
+        Lexer lx = lxi.compile();
+
+        for (Token t : lx.lex(input))
+        {
+            System.out.println(t);
+        }
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LineInfo.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LineInfo.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LineInfo.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/LineInfo.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,93 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+
+/**
+ * LineInfo
+ *
+ */
+
+public class LineInfo
+{
+
+    public static LineInfo get(String st, int position)
+    {
+        int idx = 0;
+        int line = 1;
+        int column = 0;
+        int line_pos = 0;
+        while (idx < position)
+        {
+            if (st.charAt(idx) == '\n')
+            {
+                line += 1;
+                column = 0;
+                line_pos = idx;
+            }
+
+            column += 1;
+            idx += 1;
+        }
+
+        int end = st.indexOf('\n', line_pos);
+        if (end < 0)
+        {
+            end = st.length();
+        }
+
+        String text = st.substring(line_pos, end);
+
+        return new LineInfo(line, column, text);
+    }
+
+    private int line;
+    private int column;
+    private String text;
+
+    public LineInfo(int line, int column, String text)
+    {
+        this.line = line;
+        this.column = column;
+        this.text = text;
+    }
+
+    public int getLine()
+    {
+        return line;
+    }
+
+    public int getColumn()
+    {
+        return column;
+    }
+
+    public String getText()
+    {
+        return text;
+    }
+
+    public String toString()
+    {
+        return String.format("%s,%s:%s", line, column, text);
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/ParseError.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/ParseError.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/ParseError.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/ParseError.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,58 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import org.apache.qpid.util.Strings;
+
+
+/**
+ * ParseError
+ *
+ */
+
+public class ParseError extends RuntimeException
+{
+
+    private static String msg(Token token, Token.Type ... expected)
+    {
+        LineInfo li = token.getLineInfo();
+        String exp = Strings.join(", ", expected);
+        if (expected.length > 1)
+        {
+            exp = String.format("(%s)", exp);
+        }
+
+        if (expected.length > 0)
+        {
+            return String.format("expecting %s, got %s line:%s", exp, token, li);
+        }
+        else
+        {
+            return String.format("unexpected token %s line:%s", token, li);
+        }
+    }
+
+    public ParseError(Token token, Token.Type ... expected)
+    {
+        super(msg(token, expected));
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Parser.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Parser.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Parser.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Parser.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,85 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Parser
+ *
+ */
+
+class Parser
+{
+
+    private List<Token> tokens;
+    private int idx = 0;
+
+    Parser(List<Token> tokens)
+    {
+        this.tokens = tokens;
+        this.idx = 0;
+    }
+
+    Token next()
+    {
+        return tokens.get(idx);
+    }
+
+    boolean matches(Token.Type ... types)
+    {
+        for (Token.Type t : types)
+        {
+            if (next().getType() == t)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Token eat(Token.Type ... types)
+    {
+        if (types.length > 0 && !matches(types))
+        {
+            throw new ParseError(next(), types);
+        }
+        else
+        {
+            Token t = next();
+            idx += 1;
+            return t;
+        }
+    }
+
+    List<Token> eat_until(Token.Type ... types)
+    {
+        List<Token> result = new ArrayList();
+        while (!matches(types))
+        {
+            result.add(eat());
+        }
+        return result;
+    }
+
+}

Added: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Token.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Token.java?rev=901268&view=auto
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Token.java (added)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/messaging/util/Token.java Wed Jan 20 16:38:18 2010
@@ -0,0 +1,106 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.messaging.util;
+
+
+/**
+ * Token
+ *
+ */
+
+public class Token
+{
+
+    public static class Type
+    {
+
+        private String name;
+        private String pattern;
+
+        Type(String name, String pattern)
+        {
+            this.name = name;
+            this.pattern = pattern;
+        }
+
+        public String getName()
+        {
+            return name;
+        }
+
+        public String getPattern()
+        {
+            return pattern;
+        }
+
+        public String toString()
+        {
+            return name;
+        }
+
+    }
+
+    private Type type;
+    private String value;
+    private String input;
+    private int position;
+
+    Token(Type type, String value, String input, int position)
+    {
+        this.type = type;
+        this.value = value;
+        this.input = input;
+        this.position = position;
+    }
+
+    public Type getType()
+    {
+        return type;
+    }
+
+    public String getValue()
+    {
+        return value;
+    }
+
+    public int getPosition()
+    {
+        return position;
+    }
+
+    public LineInfo getLineInfo()
+    {
+        return LineInfo.get(input, position);
+    }
+
+    public String toString()
+    {
+        if (value == null)
+        {
+            return type.toString();
+        }
+        else
+        {
+            return String.format("%s(%s)", type, value);
+        }
+    }
+
+}



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org