PageRenderTime 49ms CodeModel.GetById 40ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/RubyPlugin/src/org/jedit/ruby/parser/JRubyParser.java

#
Java | 159 lines | 126 code | 28 blank | 5 comment | 19 complexity | ee848568897a2830b941c3bc6ff9b47b MD5 | raw file
  1package org.jedit.ruby.parser;
  2
  3import org.jruby.ast.*;
  4import org.jruby.lexer.yacc.LexerSource;
  5import org.jruby.lexer.yacc.SyntaxException;
  6import org.jruby.lexer.yacc.ISourcePosition;
  7import org.jruby.parser.RubyParserConfiguration;
  8import org.jruby.parser.DefaultRubyParser;
  9import org.jruby.parser.RubyParserResult;
 10import org.jruby.common.NullWarnings;
 11import org.jruby.common.IRubyWarnings;
 12import org.jedit.ruby.ast.Member;
 13import org.jedit.ruby.RubyPlugin;
 14
 15import java.util.List;
 16import java.io.StringReader;
 17import java.io.Reader;
 18
 19/**
 20 * @author robmckinnon at users.sourceforge.net
 21 */
 22public final class JRubyParser {
 23
 24    private static final JRubyParser instance = new JRubyParser();
 25
 26    private static String found = "found";
 27    private static String expected = "expected";
 28    private static String nothing = "nothing";
 29
 30    private IRubyWarnings warnings;
 31
 32    /** singleton private constructor */
 33    private JRubyParser() {
 34    }
 35
 36    public static void setFoundLabel(String found) {
 37        JRubyParser.found = found;
 38    }
 39
 40    public static void setExpectedLabel(String expected) {
 41        JRubyParser.expected = expected;
 42    }
 43
 44    public static void setNothingLabel(String nothing) {
 45        JRubyParser.nothing = nothing;
 46    }
 47
 48    static List<Member> getMembers(String text, List<Member> methodMembers, List<RubyParser.WarningListener> listeners, String filePath, LineCounter lineCounter) {
 49        return instance.parse(text, listeners, methodMembers, filePath, lineCounter);
 50    }
 51
 52    private List<Member> parse(String text, List<RubyParser.WarningListener> listeners, List<Member> methodMembers, String filePath, LineCounter lineCounter) {
 53        this.warnings = new Warnings(listeners);
 54
 55        Reader content = new StringReader(text);
 56        RubyNodeVisitor visitor = new RubyNodeVisitor(lineCounter, methodMembers, listeners);
 57        List<Member> members;
 58
 59        try {
 60            Node node = parse(filePath, content, new RubyParserConfiguration());
 61            if (node != null) {
 62                node.accept(visitor);
 63            }
 64            members = visitor.getMembers();
 65        } catch (SyntaxException e) {
 66            for (RubyParser.WarningListener listener : listeners) {
 67                listener.error(e.getPosition(), e.getMessage());
 68            }
 69            String message = e.getPosition().getEndLine() + ": " + e.getMessage();
 70            RubyPlugin.log(message, getClass());
 71            members = null;
 72        }
 73
 74        return members;
 75    }
 76
 77    private Node parse(String name, Reader content, RubyParserConfiguration config) {
 78        DefaultRubyParser parser = new DefaultRubyParser() {
 79            /** Hack to ensure we get original error message */
 80            public void yyerror(String message, String[] expected, String found) {
 81                try {
 82                    super.yyerror(message, expected, found);
 83                } catch (SyntaxException e) {
 84                    String errorMessage = formatErrorMessage(message, expected, found);
 85                    throw new SyntaxException(e.getPosition(), errorMessage);
 86                }
 87            }
 88        };
 89
 90        parser.setWarnings(warnings);
 91        LexerSource lexerSource = LexerSource.getSource(name, content, 0, true);
 92        RubyParserResult result = parser.parse(config, lexerSource);
 93        return result.getAST();
 94    }
 95
 96    private static String formatErrorMessage(String message, String[] expectedValues, String found) {
 97        if (message.equals("syntax error")) {
 98            message = "";
 99        }
100
101        StringBuffer buffer = new StringBuffer(message);
102        if (found != null) {
103            buffer.append(JRubyParser.found).append(" ").append(reformatValue(found)).append("; ");
104            buffer.append(expected).append(" ");
105            if (expectedValues == null || expectedValues.length == 0) {
106                buffer.append(nothing);
107            } else {
108                for (String value : expectedValues) {
109                    value = reformatValue(value);
110                    buffer.append(value).append(", ");
111                }
112            }
113        }
114
115        return buffer.toString();
116    }
117
118    private static String reformatValue(String value) {
119        if (value.startsWith("k")) {
120            value = "'" + value.substring(1).toLowerCase() + "'";
121        } else if (value.startsWith("t")) {
122            value = value.substring(1).toLowerCase();
123        }
124        return value;
125    }
126
127    private static final class Warnings extends NullWarnings {
128        private final List<RubyParser.WarningListener> listeners;
129
130        public Warnings(List<RubyParser.WarningListener> listeners) {
131            this.listeners = listeners;
132        }
133
134        public final void warn(ISourcePosition position, String message) {
135            for (RubyParser.WarningListener listener : listeners) {
136                listener.warn(position, message);
137            }
138        }
139
140        public final void warn(String message) {
141            for (RubyParser.WarningListener listener : listeners) {
142                listener.warn(message);
143            }
144        }
145
146        public final void warning(ISourcePosition position, String message) {
147            for (RubyParser.WarningListener listener : listeners) {
148                listener.warning(position, message);
149            }
150        }
151
152        public final void warning(String message) {
153            for (RubyParser.WarningListener listener : listeners) {
154                listener.warning(message);
155            }
156        }
157    }
158
159}