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