lv.ctco.scm.gradle.xamarin.SolutionParser.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-mobile-plugin Show documentation
Show all versions of gradle-mobile-plugin Show documentation
The C.T.Co Mobile Plugin for Gradle helps you to configure and build Xcode and Xamarin (iOS, Android) apps.
/*
* @(#)SolutionParser.groovy
*
* Copyright C.T.Co Ltd, 15/25 Jurkalnes Street, Riga LV-1046, Latvia. All rights reserved.
*/
package lv.ctco.scm.gradle.xamarin
import org.codehaus.jparsec.Parser
import org.codehaus.jparsec.Parsers
import org.codehaus.jparsec.Scanners
import org.codehaus.jparsec.functors.Map2
import org.codehaus.jparsec.functors.Pair
import org.codehaus.jparsec.pattern.Pattern
import org.codehaus.jparsec.pattern.Patterns
/**
*
* MS Visual Studion solution file parser. This parser is quite simple and is not error-proof in case of
* manual solution file editing. It implement parsing of only the basic configurations like Project and Global
* tags.
*
* Please have a look a the lv.ctco.scm.mobile.xamarin.SolutionParserTest for more information.
*
*/
public class SolutionParser {
protected File file
public SolutionParser(File file) {
this.file = file
}
/**
* Parses a solution file.
*
* @return Object representation of the parsed solution file.
*/
Solution parse() {
if (!file.exists()) {
throw new IOException("Solution file $file.absolutePath does not exist")
}
createSolutionParser().parse(file.text)
}
protected static final Parser STRING_PARSER =
Scanners.DOUBLE_QUOTE_STRING.map(
[
map: { String str -> str.length() > 2 ? str[1..str.length() - 2] : '' }
] as org.codehaus.jparsec.functors.Map
)
protected static Parser createProjectUnitParser() {
Scanners.string('Project').next(
Parsers.between(
Scanners.isChar('('.toCharacter()),
STRING_PARSER,
Scanners.isChar(')'.toCharacter()),
)
)
}
protected static Parser> createCommaSeparatedStringsParser() {
Parsers.sequence(
Scanners.WHITESPACES.optional(),
STRING_PARSER,
).sepBy(Scanners.isChar(','.toCharacter()))
}
protected static final Parser ASSIGNMENT = Parsers.sequence(
Scanners.WHITESPACES,
Scanners.isChar('='.toCharacter()),
Scanners.WHITESPACES
)
protected static Parser createProjectSectionParser() {
Parsers.sequence(createProjectUnitParser().followedBy(ASSIGNMENT), createCommaSeparatedStringsParser(), [
map: { String projectType, List values ->
new SlnProjectSection(values[0], projectType, values[1], values[2])
}
] as Map2, SlnProjectSection>).
followedBy(Scanners.WHITESPACES).
followedBy(Scanners.string('EndProject'))
}
protected static Parser> createProjectSectionListParser() {
Parsers.or(
createProjectSectionParser().followedBy(Scanners.WHITESPACES),
(Parser)Parsers.never()
).many()
}
protected static Parser> createPropertyParser() {
Pattern pattern = Patterns.regex('[^=&&[^\\r\\n\\f]]+')
Parser identifierParser = Scanners.pattern(pattern, 'identifier').source().map(
new org.codehaus.jparsec.functors.Map() {
String map(String from) {
return from.trim()
}
})
Parsers.tuple(identifierParser.followedBy(Scanners.isChar('='.toCharacter())), identifierParser)
}
protected static Parser createGlobalSectionUnitParser() {
Parser sectionNameParser = Scanners.pattern(Patterns.regex('[^)]+'), 'section name').source()
Scanners.string('GlobalSection(').
next(sectionNameParser).
followedBy(
Parsers.sequence(
Scanners.isChar(')'.toCharacter()),
Scanners.WHITESPACES,
Scanners.isChar('='.toCharacter()),
Scanners.WHITESPACES
)
).followedBy(
Parsers.or(
Scanners.string('preSolution'),
Scanners.string('postSolution')
)
)
}
protected static Parser createGlobalSectionParser() {
Parser>> propertyListParser =
Parsers.or(
createPropertyParser().followedBy(Scanners.WHITESPACES),
Parsers.never() as Parser>
).many()
Parsers.sequence(
createGlobalSectionUnitParser().followedBy(Scanners.WHITESPACES),
propertyListParser,
new Map2>, SlnGlobalSection>() {
SlnGlobalSection map(String sectionName, List> properties) {
SlnGlobalSection section = new SlnGlobalSection(sectionName)
properties.each { Pair property ->
section.putProperty(property.a, property.b)
}
return section
}
}
).followedBy(Scanners.string('EndGlobalSection'))
}
protected static Parser> createGlobalSectionListParser() {
Parsers.between(
Scanners.string('Global').followedBy(Scanners.WHITESPACES),
Parsers.or(createGlobalSectionParser().followedBy(Scanners.WHITESPACES),
(Parser)Parsers.never()).many(),
Scanners.string('EndGlobal')
)
}
protected static Parser createSolutionParser() {
Scanners.WHITESPACES.
followedBy(Scanners.string('Microsoft Visual Studio Solution File, Format Version 12.00')).optional().
followedBy(Scanners.WHITESPACES).
followedBy(Scanners.pattern(Patterns.regex('# Visual Studio .*'), 'Visual Studio version')).optional().
followedBy(Scanners.WHITESPACES).next(Parsers.sequence(
createProjectSectionListParser(),
createGlobalSectionListParser(),
new Map2, List, Solution>() {
Solution map(List projectSections, List globalSections) {
return new Solution(projectSections, globalSections)
}
}
)).followedBy(Scanners.WHITESPACES.optional())
}
}