Refactoring: make Grammar an abstract class
This commit is contained in:
		
							parent
							
								
									c9c1454f90
								
							
						
					
					
						commit
						301eaaf98d
					
				
					 18 changed files with 395 additions and 163 deletions
				
			
		|  | @ -2,81 +2,17 @@ package com.albertoventurini.parsley.examples.graphml; | |||
| 
 | ||||
| import com.albertoventurini.parsley.grammar.Grammar; | ||||
| import com.albertoventurini.parsley.grammar.ParseTree; | ||||
| import com.albertoventurini.parsley.grammar.rules.Rule; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.nio.file.Files; | ||||
| import java.nio.file.Path; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.function.BiFunction; | ||||
| import java.util.function.Function; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import static com.albertoventurini.parsley.grammar.Grammar.*; | ||||
| 
 | ||||
| public class GrammarGraphMLParser implements GraphMLParser { | ||||
| 
 | ||||
|     private final Grammar grammar; | ||||
| 
 | ||||
|     public GrammarGraphMLParser() { | ||||
| 
 | ||||
|         final Rule comment = sequence(string("<!--"), until("-->")).as("comment"); | ||||
|         final Rule comments = zeroOrMore(comment).as("comments"); | ||||
| 
 | ||||
|         final Rule xmlHeader = string("<?xml version='1.0' ?>").as("header"); | ||||
| 
 | ||||
|         final Rule attribute = sequence( | ||||
|                 takeWhile(c -> c != '=' && c != '>'), | ||||
|                 character('='), | ||||
|                 character('\''), | ||||
|                 takeWhile(c -> c != '\''), | ||||
|                 character('\'')).as("attribute"); | ||||
| 
 | ||||
|         final Function<String, Rule> tagFunc = (s) -> sequence( | ||||
|                 character('<'), | ||||
|                 string(s).as("tagName"), | ||||
|                 zeroOrMore(attribute).as("attributes"), | ||||
|                 character('>')).as("tag:" + s); | ||||
| 
 | ||||
|         final Function<String, Rule> closingTagFunc = (s) -> sequence( | ||||
|                 string("</"), | ||||
|                 string(s), | ||||
|                 character('>')).as("closingTag:" + s); | ||||
| 
 | ||||
|         final BiFunction<String, Rule, Rule> elementFunc = (tagName, content) -> sequence( | ||||
|                 tagFunc.apply(tagName).as("tag:" + tagName), | ||||
|                 content.as("content"), | ||||
|                 closingTagFunc.apply(tagName).as("closingTag:" + tagName)); | ||||
| 
 | ||||
|         final Rule data = elementFunc.apply("data", takeWhile(c -> c != '<')).as("dataElem"); | ||||
| 
 | ||||
|         final Rule node = elementFunc.apply("node", zeroOrMore(data)).as("nodeElem"); | ||||
| 
 | ||||
|         final Rule edge = elementFunc.apply("edge", zeroOrMore(data)).as("edgeElem"); | ||||
| 
 | ||||
|         final Rule graph = sequence( | ||||
|                 tagFunc.apply("graph"), | ||||
|                 oneOrMore(node).as("nodes"), | ||||
|                 oneOrMore(edge).as("edges"), | ||||
|                 closingTagFunc.apply("graph")).as("graphElem"); | ||||
| 
 | ||||
|         final Rule key = sequence(tagFunc.apply("key"), closingTagFunc.apply("key")) | ||||
|                 .as("keyElem"); | ||||
| 
 | ||||
|         final Rule graphml = sequence( | ||||
|                 tagFunc.apply("graphml"), | ||||
|                 oneOrMore(key).as("keys"), | ||||
|                 graph, | ||||
|                 closingTagFunc.apply("graphml")).as("graphmlElem"); | ||||
| 
 | ||||
|         final Rule graphmlFile = sequence( | ||||
|                 xmlHeader, | ||||
|                 comments.discard(), | ||||
|                 graphml).as("graphmlFile"); | ||||
| 
 | ||||
|         grammar = new Grammar(graphmlFile, null); | ||||
|     } | ||||
|     private final Grammar grammar = new GraphMLGrammar(); | ||||
| 
 | ||||
|     @Override | ||||
|     public GraphMLParseResult parse(final String filePath) { | ||||
|  |  | |||
|  | @ -0,0 +1,76 @@ | |||
| package com.albertoventurini.parsley.examples.graphml; | ||||
| 
 | ||||
| import com.albertoventurini.parsley.grammar.Grammar; | ||||
| import com.albertoventurini.parsley.grammar.rules.Rule; | ||||
| 
 | ||||
| import java.util.function.BiFunction; | ||||
| import java.util.function.Function; | ||||
| 
 | ||||
| import static com.albertoventurini.parsley.grammar.rules.Rules.*; | ||||
| 
 | ||||
| public class GraphMLGrammar extends Grammar { | ||||
| 
 | ||||
|     private final Rule comment = sequence(string("<!--"), until("-->")).as("comment"); | ||||
|     private final Rule comments = zeroOrMore(comment).setComment(true).as("comments"); | ||||
| 
 | ||||
|     private final Rule xmlHeader = string("<?xml version='1.0' ?>").as("header"); | ||||
| 
 | ||||
|     private final Rule attribute = sequence( | ||||
|             takeWhile(c -> c != '=' && c != '>'), | ||||
|             character('='), | ||||
|             character('\''), | ||||
|             takeWhile(c -> c != '\''), | ||||
|             character('\'')).as("attribute"); | ||||
| 
 | ||||
|     private final Function<String, Rule> tagFunc = (s) -> sequence( | ||||
|             character('<'), | ||||
|             string(s).as("tagName"), | ||||
|             zeroOrMore(attribute).as("attributes"), | ||||
|             character('>')).as("tag:" + s); | ||||
| 
 | ||||
|     private final Function<String, Rule> closingTagFunc = (s) -> sequence( | ||||
|             string("</"), | ||||
|             string(s), | ||||
|             character('>')).as("closingTag:" + s); | ||||
| 
 | ||||
|     private final BiFunction<String, Rule, Rule> elementFunc = (tagName, content) -> sequence( | ||||
|             tagFunc.apply(tagName).as("tag:" + tagName), | ||||
|             content.as("content"), | ||||
|             closingTagFunc.apply(tagName).as("closingTag:" + tagName)); | ||||
| 
 | ||||
|     private final Rule data = elementFunc.apply("data", takeWhile(c -> c != '<')).as("dataElem"); | ||||
| 
 | ||||
|     private final Rule node = elementFunc.apply("node", zeroOrMore(data)).as("nodeElem"); | ||||
| 
 | ||||
|     private final Rule edge = elementFunc.apply("edge", zeroOrMore(data)).as("edgeElem"); | ||||
| 
 | ||||
|     private final Rule graph = sequence( | ||||
|             tagFunc.apply("graph"), | ||||
|             oneOrMore(node).as("nodes"), | ||||
|             oneOrMore(edge).as("edges"), | ||||
|             closingTagFunc.apply("graph")).as("graphElem"); | ||||
| 
 | ||||
|     private final Rule key = sequence(tagFunc.apply("key"), closingTagFunc.apply("key")) | ||||
|             .as("keyElem"); | ||||
| 
 | ||||
|     private final Rule graphml = sequence( | ||||
|             tagFunc.apply("graphml"), | ||||
|             oneOrMore(key).as("keys"), | ||||
|             graph, | ||||
|             closingTagFunc.apply("graphml")).as("graphmlElem"); | ||||
| 
 | ||||
|     private final Rule graphmlFile = sequence( | ||||
|             xmlHeader, | ||||
|             comments.discard(), | ||||
|             graphml).as("graphmlFile"); | ||||
| 
 | ||||
|     @Override | ||||
|     protected Rule startRule() { | ||||
|         return graphmlFile; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Rule commentRule() { | ||||
|         return comments; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| package com.albertoventurini.parsley.examples.markdown; | ||||
| 
 | ||||
| import com.albertoventurini.parsley.grammar.Grammar; | ||||
| import com.albertoventurini.parsley.grammar.rules.Rule; | ||||
| 
 | ||||
| import static com.albertoventurini.parsley.grammar.rules.Rules.*; | ||||
| 
 | ||||
| public class MarkdownGrammar extends Grammar { | ||||
| 
 | ||||
|     private final Rule h1 = sequence( | ||||
|             character('#'), | ||||
|             takeWhile(c -> c != '\n') | ||||
|     ); | ||||
| 
 | ||||
|     private final Rule paragraph = sequence( | ||||
|             character('\n'), | ||||
|             takeWhile(c -> c != '\n') | ||||
|     ); | ||||
| 
 | ||||
|     private final Rule element = oneOf(h1, paragraph); | ||||
| 
 | ||||
|     private final Rule elements = sequence(element); | ||||
| 
 | ||||
|     private final Rule document = zeroOrMore(elements); | ||||
| 
 | ||||
|     @Override | ||||
|     public Rule startRule() { | ||||
|         return document; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected Rule commentRule() { | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,4 @@ | |||
| package com.albertoventurini.parsley.examples.markdown; | ||||
| 
 | ||||
| public class MarkdownParseResult { | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| package com.albertoventurini.parsley.examples.markdown; | ||||
| 
 | ||||
| public interface MarkdownParser { | ||||
|     MarkdownParseResult parse(String filePath); | ||||
| } | ||||
|  | @ -1,6 +1,7 @@ | |||
| package com.albertoventurini.parsley.examples.graphml; | ||||
| 
 | ||||
| import com.albertoventurini.parsley.grammar.Grammar; | ||||
| import com.albertoventurini.parsley.grammar.GrammarFactory; | ||||
| import com.albertoventurini.parsley.grammar.rules.Rule; | ||||
| import org.junit.jupiter.api.Test; | ||||
| 
 | ||||
|  | @ -9,7 +10,7 @@ import java.nio.file.Path; | |||
| import java.util.function.BiFunction; | ||||
| import java.util.function.Function; | ||||
| 
 | ||||
| import static com.albertoventurini.parsley.grammar.Grammar.*; | ||||
| import static com.albertoventurini.parsley.grammar.rules.Rules.*; | ||||
| import static org.junit.jupiter.api.Assertions.assertTrue; | ||||
| 
 | ||||
| public class GraphMLGrammarTest { | ||||
|  | @ -69,7 +70,7 @@ public class GraphMLGrammarTest { | |||
| 
 | ||||
|         final Rule graphmlFile = sequence(xmlHeader, graphml).as("graphmlFile"); | ||||
| 
 | ||||
|         grammar = new Grammar(graphmlFile, comments); | ||||
|         grammar = GrammarFactory.newGrammar(graphmlFile, comments); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| package com.albertoventurini.parsley.examples.graphml; | ||||
| 
 | ||||
| import com.albertoventurini.parsley.examples.markdown.MarkdownGrammar; | ||||
| import org.junit.jupiter.api.Test; | ||||
| 
 | ||||
| public class MarkdownGrammarTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void markdownGrammar_withH1AndParagraph_shouldParse() { | ||||
|         final MarkdownGrammar grammar = new MarkdownGrammar(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										155
									
								
								parsley-examples/src/test/resources/markdown/markdown1.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								parsley-examples/src/test/resources/markdown/markdown1.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,155 @@ | |||
| # An h1 header | ||||
| 
 | ||||
| Paragraphs are separated by a blank line. | ||||
| 
 | ||||
| 2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists | ||||
| look like: | ||||
| 
 | ||||
| * this one | ||||
| * that one | ||||
| * the other one | ||||
| 
 | ||||
| Note that --- not considering the asterisk --- the actual text | ||||
| content starts at 4-columns in. | ||||
| 
 | ||||
| > Block quotes are | ||||
| > written like so. | ||||
| > | ||||
| > They can span multiple paragraphs, | ||||
| > if you like. | ||||
| 
 | ||||
| Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., "it's all | ||||
| in chapters 12--14"). Three dots ... will be converted to an ellipsis. | ||||
| Unicode is supported. ☺ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # An h2 header | ||||
| 
 | ||||
| Here's a numbered list: | ||||
| 
 | ||||
| 1. first item | ||||
| 2. second item | ||||
| 3. third item | ||||
| 
 | ||||
| Note again how the actual text starts at 4 columns in (4 characters | ||||
| from the left side). Here's a code sample: | ||||
| 
 | ||||
|     # Let me re-iterate ... | ||||
|     for i in 1 .. 10 { do-something(i) } | ||||
| 
 | ||||
| As you probably guessed, indented 4 spaces. By the way, instead of | ||||
| indenting the block, you can use delimited blocks, if you like: | ||||
| 
 | ||||
| ~~~ | ||||
| define foobar() { | ||||
|     print "Welcome to flavor country!"; | ||||
| } | ||||
| ~~~ | ||||
| 
 | ||||
| (which makes copying & pasting easier). You can optionally mark the | ||||
| delimited block for Pandoc to syntax highlight it: | ||||
| 
 | ||||
| ~~~python | ||||
| import time | ||||
| # Quick, count to ten! | ||||
| for i in range(10): | ||||
|     # (but not *too* quick) | ||||
|     time.sleep(0.5) | ||||
|     print i | ||||
| ~~~ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ### An h3 header | ||||
| 
 | ||||
| Now a nested list: | ||||
| 
 | ||||
| 1. First, get these ingredients: | ||||
| 
 | ||||
|     * carrots | ||||
|     * celery | ||||
|     * lentils | ||||
| 
 | ||||
| 2. Boil some water. | ||||
| 
 | ||||
| 3. Dump everything in the pot and follow | ||||
|    this algorithm: | ||||
| 
 | ||||
|        find wooden spoon | ||||
|        uncover pot | ||||
|        stir | ||||
|        cover pot | ||||
|        balance wooden spoon precariously on pot handle | ||||
|        wait 10 minutes | ||||
|        goto first step (or shut off burner when done) | ||||
| 
 | ||||
|    Do not bump wooden spoon or it will fall. | ||||
| 
 | ||||
| Notice again how text always lines up on 4-space indents (including | ||||
| that last line which continues item 3 above). | ||||
| 
 | ||||
| Here's a link to [a website](http://foo.bar), to a [local | ||||
| doc](local-doc.html), and to a [section heading in the current | ||||
| doc](#an-h2-header). Here's a footnote [^1]. | ||||
| 
 | ||||
| [^1]: Footnote text goes here. | ||||
| 
 | ||||
| Tables can look like this: | ||||
| 
 | ||||
| size  material      color | ||||
| ----  ------------  ------------ | ||||
| 9     leather       brown | ||||
| 10    hemp canvas   natural | ||||
| 11    glass         transparent | ||||
| 
 | ||||
| Table: Shoes, their sizes, and what they're made of | ||||
| 
 | ||||
| (The above is the caption for the table.) Pandoc also supports | ||||
| multi-line tables: | ||||
| 
 | ||||
| --------  ----------------------- | ||||
| keyword   text | ||||
| --------  ----------------------- | ||||
| red       Sunsets, apples, and | ||||
| other red or reddish | ||||
| things. | ||||
| 
 | ||||
| green     Leaves, grass, frogs | ||||
| and other things it's | ||||
| not easy being. | ||||
| --------  ----------------------- | ||||
| 
 | ||||
| A horizontal rule follows. | ||||
| 
 | ||||
| *** | ||||
| 
 | ||||
| Here's a definition list: | ||||
| 
 | ||||
| apples | ||||
| : Good for making applesauce. | ||||
| oranges | ||||
| : Citrus! | ||||
| tomatoes | ||||
| : There's no "e" in tomatoe. | ||||
| 
 | ||||
| Again, text is indented 4 spaces. (Put a blank line between each | ||||
| term/definition pair to spread things out more.) | ||||
| 
 | ||||
| Here's a "line block": | ||||
| 
 | ||||
| | Line one | ||||
| |   Line too | ||||
| | Line tree | ||||
| 
 | ||||
| and images can be specified like so: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| Inline math equations go in like so: $\omega = d\phi / dt$. Display | ||||
| math should get its own line and be put in in double-dollarsigns: | ||||
| 
 | ||||
| $$I = \int \rho R^{2} dV$$ | ||||
| 
 | ||||
| And note that you can backslash-escape any punctuation characters | ||||
| which you wish to be displayed literally, ex.: \`foo\`, \*bar\*, etc. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue