PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/src/orc/compile/parse/OrcParsers.scala

https://github.com/laurenyew/cOrcS
Scala | 485 lines | 238 code | 80 blank | 167 comment | 1 complexity | 3aaa1c3c0ba0fadcbea8ef3ea5bd5ab1 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. //
  2. // OrcParsers.scala -- Scala objects Orc...Parser, and class OrcParsers
  3. // Project OrcScala
  4. //
  5. // $Id: OrcParsers.scala 3099 2012-07-21 02:33:18Z laurenyew $
  6. //
  7. // Created by dkitchin on May 10, 2010.
  8. //
  9. // Copyright (c) 2011 The University of Texas at Austin. All rights reserved.
  10. //
  11. // Use and redistribution of this file is governed by the license terms in
  12. // the LICENSE file found in the project's top-level directory and also found at
  13. // URL: http://orc.csres.utexas.edu/license.shtml .
  14. //
  15. package orc.compile.parse
  16. import scala.util.parsing.input.Reader
  17. import scala.util.parsing.combinator.syntactical._
  18. import scala.util.parsing.input.Position
  19. import java.io.IOException
  20. import orc.ast.AST
  21. import orc.OrcCompilationOptions
  22. import orc.OrcCompilerRequires
  23. import orc.ast.ext._
  24. /** Mix-in for result types from Orc parsers
  25. *
  26. * @author jthywiss
  27. */
  28. trait OrcParserResultTypes[T] {
  29. type ResultType = T
  30. type ParseResult = OrcParsers#ParseResult[T]
  31. type ParseResultT[U] = OrcParsers#ParseResult[U]
  32. type Success = OrcParsers#Success[T]
  33. type SuccessT[U] = OrcParsers#Success[U]
  34. type NoSuccess = OrcParsers#NoSuccess
  35. type Error = OrcParsers#Error
  36. type Failure = OrcParsers#Failure
  37. }
  38. /** An Orc parser that analyzes a given string as an Orc literal value.
  39. * The result of applying this function is an Expression Extended AST,
  40. * in particular a Constant, ListValue, or TupleValue.
  41. *
  42. * @see orc.ast.ext.Expression
  43. * @see orc.ast.ext.Constant
  44. * @see orc.ast.ext.ListValue
  45. * @see orc.ast.ext.TupleValue
  46. * @author jthywiss
  47. */
  48. object OrcLiteralParser extends (String => OrcParsers#ParseResult[Expression]) with OrcParserResultTypes[Expression] {
  49. def apply(s: String): ParseResult = {
  50. val parsers = new OrcParsers(null, null, null)
  51. val tokens = new parsers.lexical.Scanner(s)
  52. parsers.phrase(parsers.parseConstantListTuple)(tokens)
  53. }
  54. }
  55. /** An Orc parser that analyzes a given input as an Orc program.
  56. * The result of applying this function is an Expression Extended AST
  57. * representing the whole program and included files.
  58. *
  59. * @author jthywiss
  60. */
  61. object OrcProgramParser extends ((OrcInputContext, OrcCompilationOptions, OrcCompilerRequires) => OrcParsers#ParseResult[Expression]) with OrcParserResultTypes[Expression] {
  62. def apply(ic: OrcInputContext, options: OrcCompilationOptions, envServices: OrcCompilerRequires): ParseResult = {
  63. val parsers = new OrcParsers(ic, options, envServices)
  64. val tokens = new parsers.lexical.Scanner(ic.reader)
  65. parsers.phrase(parsers.parseProgram)(tokens)
  66. }
  67. }
  68. /** An Orc parser that analyzes a given input as an Orc include file.
  69. * The result of applying this function is an Include Extended AST
  70. * representing the include and sub-included files.
  71. *
  72. * @author jthywiss
  73. */
  74. object OrcIncludeParser extends ((OrcInputContext, OrcCompilationOptions, OrcCompilerRequires) => OrcParsers#ParseResult[Include]) with OrcParserResultTypes[Include] {
  75. def apply(ic: OrcInputContext, options: OrcCompilationOptions, envServices: OrcCompilerRequires): ParseResult = {
  76. val newParsers = new OrcParsers(ic, options, envServices)
  77. val parseInclude = newParsers.markLocation(newParsers.parseDeclarations ^^ { Include(ic.descr, _) })
  78. val tokens = new newParsers.lexical.Scanner(ic.reader)
  79. newParsers.phrase(parseInclude)(tokens)
  80. }
  81. }
  82. /** This is a container for the various Parsers that embody the Orc grammar
  83. * productions, and some parsing helper methods.
  84. * <p>
  85. * A fresh OrcParsers instance is needed for every parse.
  86. * (Limitation of scala.util.parsing.combinator.Parsers -- current parsing state kept in fields.)
  87. *
  88. * @author dkitchin, amshali, srosario, jthywiss
  89. */
  90. class OrcParsers(inputContext: OrcInputContext, options: OrcCompilationOptions, envServices: OrcCompilerRequires)
  91. extends StandardTokenParsers
  92. with CustomParserCombinators {
  93. import lexical.{ Keyword, Identifier, FloatingPointLit }
  94. override val lexical = new OrcLexical()
  95. /*---------------------------------------------------------
  96. For reference, here are Orc's operators sorted
  97. and grouped in order of decreasing precedence.
  98. When an operator's associativity is "both",
  99. the parser currently defaults to "left".
  100. Symbol Assoc Name
  101. ----------------------------------------------------
  102. [highest precedence]
  103. ----------------------------------------------------
  104. ? postfix dereference
  105. . postfix field projection
  106. () postfix application
  107. ----------------------------------------------------
  108. ~ prefix boolean not
  109. - prefix unary minus
  110. ----------------------------------------------------
  111. ** left exponent
  112. ----------------------------------------------------
  113. * left multiplication
  114. / left division
  115. % left modulus
  116. ----------------------------------------------------
  117. + left addition
  118. - left subtraction
  119. ----------------------------------------------------
  120. : right cons
  121. ----------------------------------------------------
  122. = none equal
  123. /= none not equal
  124. :> none greater
  125. > none greater
  126. >= none greater or equal
  127. <: none less
  128. < none less
  129. <= none less or equal
  130. ----------------------------------------------------
  131. || both boolean or
  132. && both boolean and
  133. ----------------------------------------------------
  134. := none ref assignment
  135. ----------------------------------------------------
  136. >> right sequence
  137. ----------------------------------------------------
  138. | both parallel
  139. ----------------------------------------------------
  140. << left where
  141. ----------------------------------------------------
  142. ; both semicolon
  143. ----------------------------------------------------
  144. :: left type information
  145. :!: left type override
  146. lambda right anonymous function
  147. if then else prefix conditional
  148. def
  149. import
  150. type
  151. include prefix declaration
  152. ----------------------------------------------------
  153. [lowest precedence]
  154. ----------------------------------------------------*/
  155. /*
  156. * Here are the productions of the Orc grammar,
  157. * given in the following order:
  158. *
  159. * Literals
  160. * Expressions
  161. * Patterns
  162. * Types
  163. * Declarations
  164. *
  165. */
  166. ////////
  167. // Literals
  168. ////////
  169. val floatLit: Parser[String] =
  170. elem("number", _.isInstanceOf[FloatingPointLit]) ^^ (_.chars)
  171. val parseValue: Parser[AnyRef] = (
  172. "true" ^^^ java.lang.Boolean.TRUE
  173. | "false" ^^^ java.lang.Boolean.FALSE
  174. | "signal" ^^^ orc.values.Signal
  175. | stringLit
  176. | numericLit ^^ { BigInt(_) }
  177. | floatLit ^^ { BigDecimal(_) }
  178. | "null" ^^^ null)
  179. val parseConstantListTuple: Parser[Expression] = (
  180. "-" ~> numericLit -> { s => Constant(-BigInt(s)) }
  181. | "-" ~> floatLit -> { s => Constant(-BigDecimal(s)) }
  182. | parseValue -> Constant
  183. | "(" ~> parseConstantListTuple <~ ")"
  184. | ListOf(parseConstantListTuple) -> ListExpr
  185. | TupleOf(parseConstantListTuple) -> TupleExpr)
  186. val parseSiteLocation = stringLit
  187. ////////
  188. // Expressions
  189. ////////
  190. val parseBaseExpressionTail: Parser[Option[List[Expression]]] = (
  191. "," ~> CommaSeparated1(parseExpression) <~ ")" ^^ { Some(_) }
  192. | ")" ^^^ None)
  193. val parseBaseExpression = (
  194. parseValue -> Constant
  195. | ident -> Variable
  196. | "stop" -> Stop
  197. | ListOf(parseExpression) -> ListExpr
  198. | RecordOf("=", parseExpression) -> RecordExpr
  199. | ("(" ~> parseExpression ~ parseBaseExpressionTail) -?->
  200. { (e: Expression, es: List[Expression]) => TupleExpr(e :: es) }
  201. | failExpecting("expression"))
  202. val parseArgumentGroup: Parser[ArgumentGroup] = (
  203. "." ~> ident -> FieldAccess
  204. | "?" -> Dereference
  205. | (("[" ~> CommaSeparated(parseType) <~ "]")?) ~ ("(" ~> CommaSeparated(parseExpression) <~ ")") -> Args)
  206. val parseCallExpression: Parser[Expression] = (
  207. parseBaseExpression ~ ((parseArgumentGroup+)?) -?-> Call)
  208. val parseUnaryExpr: Parser[Expression] = (
  209. // First see if it's a unary minus for a numeric literal
  210. "-" ~> numericLit -> { s => Constant(-BigInt(s)) }
  211. | "-" ~> floatLit -> { s => Constant(-BigDecimal(s)) }
  212. | ("-" | "~") ~ parseCallExpression -> PrefixOperator
  213. | parseCallExpression)
  214. val parseExpnExpr = parseUnaryExpr rightAssociativeInfix List("**")
  215. val parseMultExpr = parseExpnExpr leftAssociativeInfix List("*", "/", "%")
  216. val parseAdditionalExpr = parseMultExpr leftAssociativeInfix List("-", "+")
  217. val parseConsExpr = parseAdditionalExpr rightAssociativeInfix List(":")
  218. val parseRelationalExpr = parseConsExpr nonAssociativeInfix List("<:", ":>", "<=", ">=", "=", "/=")
  219. val parseLogicalExpr = parseRelationalExpr fullyAssociativeInfix List("||", "&&")
  220. val parseInfixOpExpression = parseLogicalExpr nonAssociativeInfix List(":=")
  221. val parseSequentialCombinator = ">" ~> (parsePattern?) <~ ">"
  222. val parsePruningCombinator = "<" ~> (parsePattern?) <~ "<"
  223. val parseSequentialExpression =
  224. parseInfixOpExpression rightInterleave parseSequentialCombinator apply Sequential
  225. val parseParallelExpression =
  226. rep1sep(parseSequentialExpression, "|") -> { _ reduceLeft Parallel }
  227. val parsePruningExpression =
  228. parseParallelExpression leftInterleave parsePruningCombinator apply Pruning
  229. val parseOtherwiseExpression =
  230. rep1sep(parsePruningExpression, ";") -> { _ reduceLeft Otherwise }
  231. val parseAscription = (
  232. ("::" ~ parseType)
  233. | (":!:" ~ parseType)
  234. | failUnexpectedIn("expression"))
  235. val parseTypedExpression =
  236. parseOtherwiseExpression ~ (parseAscription?) -?->
  237. {
  238. (_, _) match {
  239. case (e, "::" ~ t) => TypeAscription(e, t)
  240. case (e, ":!:" ~ t) => TypeAssertion(e, t)
  241. }
  242. }
  243. /**
  244. * parseSecurityLevelExpression
  245. * WHAT: more general parsing of SecurityLevels with Expressions
  246. * WHY: Named.scala does not take in patterns, and converts patterns to expressions
  247. * so to attach a SecurityLevel to a pattern, we must attach it to an expr
  248. * EX: (1+2)@A
  249. */
  250. val parseSecurityLevelExpression =
  251. parseTypedExpression ~ (("@" ~> parseSecurityLevel)?) -?-> SecurityLevelExpression
  252. val parseReturnType = "::" ~> parseType
  253. val parseGuard = "if" ~> "(" ~> parseExpression <~ ")"
  254. def parseExpression: Parser[Expression] = (
  255. parseSecurityLevelExpression
  256. | parseDeclaration ~ (parseExpression | failExpecting("after declaration, expression")) -> Declare
  257. | ("if" ~> parseExpression)
  258. ~ ("then" ~> parseExpression)
  259. ~ ("else" ~> parseExpression)
  260. -> Conditional
  261. | "lambda" ~> (ListOf(parseTypeVariable)?)
  262. ~ (TupleOf(parsePattern))
  263. ~ (parseReturnType?)
  264. ~ (parseGuard?)
  265. ~ ("=" ~> parseExpression)
  266. -> Lambda
  267. | failExpecting("expression"))
  268. ////////
  269. // Patterns
  270. ////////
  271. val parseBasePatternTail: Parser[Option[List[Pattern]]] = (
  272. "," ~> CommaSeparated(parsePattern) <~ ")" ^^ { Some(_) }
  273. | ")" ^^^ None)
  274. //? How do persistant names? like when I create a security level, I guess they're just Strings?
  275. //? How do Strings?
  276. val parseBasePattern = (
  277. parseValue -> ConstantPattern
  278. | "_" -> Wildcard
  279. | ident ~ TupleOf(parsePattern) -> CallPattern
  280. | ident -> VariablePattern
  281. | ("(" ~> parsePattern ~ parseBasePatternTail) -?->
  282. { (p: Pattern, ps: List[Pattern]) => TuplePattern(p :: ps) }
  283. | ListOf(parsePattern) -> ListPattern
  284. | RecordOf("=", parsePattern) -> RecordPattern
  285. | failExpecting("pattern"))
  286. val parseConsPattern = rep1sep(parseBasePattern, ":") -> (_ reduceRight ConsPattern)
  287. val parseAsPattern = (
  288. parseConsPattern ~ (("as" ~> ident)?) -?-> AsPattern)
  289. val parseTypedPattern = (
  290. parseAsPattern ~ (("::" ~> parseType)?) -?-> TypedPattern)
  291. //parsed pattern SL is attached to pattern (Ex: var x)
  292. //sends to extended as SecurityLevelPattern
  293. //if not a security pattern looks at parseTypedPattern
  294. //~ gets the pattern before
  295. val parseSecurityLevelPattern = (
  296. parseTypedPattern ~ (("@" ~> parseSecurityLevel)?) -?-> SecurityLevelPattern)
  297. val parsePattern: Parser[Pattern] = parseSecurityLevelPattern
  298. //Security Level
  299. val parseSecurityLevel: Parser[String] = ident
  300. ////////
  301. // Types
  302. ////////
  303. val parseTypeVariable: Parser[String] = ident
  304. val parseTypeTail: Parser[Option[List[Type]]] = (
  305. "," ~> CommaSeparated1(parseType) <~ ")" ^^ { Some(_) }
  306. | ")" ^^^ None)
  307. val parseType: Parser[Type] = (
  308. parseTypeVariable ~ (ListOf(parseType)?) ->
  309. {
  310. (_, _) match {
  311. case (id, None) => TypeVariable(id)
  312. case (id, Some(ts)) => TypeApplication(id, ts)
  313. }
  314. }
  315. | ("(" ~> parseType ~ parseTypeTail) -?->
  316. { (t: Type, ts: List[Type]) => TupleType(t :: ts) }
  317. | TupleOf(parseType) -> TupleType
  318. | RecordOf("::", parseType) -> RecordType
  319. | "lambda" ~> ((ListOf(parseTypeVariable)?) ^^ { _.getOrElse(Nil) }) ~ (TupleOf(parseType)) ~ parseReturnType -> LambdaType
  320. | failExpecting("type"))
  321. val parseConstructor: Parser[Constructor] = (
  322. ident ~ TupleOf(parseType ^^ (Some(_))) -> Constructor
  323. | ident ~ TupleOf("_" ^^^ None) -> Constructor)
  324. ////////
  325. // Declarations
  326. ////////
  327. val parseDefCore = (
  328. ident ~ (ListOf(parseTypeVariable)?) ~ (TupleOf(parsePattern)) ~ (parseReturnType?) ~ (parseGuard?) ~ ("=" ~> parseExpression))
  329. val parseDefCoreSL = (
  330. ident ~ ident ~ (ListOf(parseTypeVariable)?) ~ (TupleOf(parsePattern)) ~ (parseReturnType?) ~ (parseGuard?) ~ ("=" ~> parseExpression))
  331. val parseDefDeclaration: Parser[DefDeclaration] = (
  332. parseDefCore -> Def
  333. //site call
  334. | (Identifier("class") ~> parseDefCore) -> DefClass
  335. | ident ~ (ListOf(parseTypeVariable)?) ~ (TupleOf(parseType)) ~ parseReturnType -> DefSig)
  336. val parseDeclaration: Parser[Declaration] = (
  337. ("val" ~> parsePattern) ~ ("=" ~> parseExpression) -> Val
  338. | "def" ~> parseDefDeclaration
  339. | "import" ~> Identifier("site") ~> ident ~ ("=" ~> parseSiteLocation) -> SiteImport
  340. | "import" ~> Identifier("class") ~> ident ~ ("=" ~> parseSiteLocation) -> ClassImport
  341. | ("include" ~> stringLit).into(performInclude)
  342. | "import" ~> "type" ~> ident ~ ("=" ~> parseSiteLocation) -> TypeImport
  343. | "type" ~> parseTypeVariable ~ ((ListOf(parseTypeVariable))?) ~ ("=" ~> rep1sep(parseConstructor, "|"))
  344. -> ((x, ys, t) => Datatype(x, ys getOrElse Nil, t))
  345. | "type" ~> parseTypeVariable ~ ((ListOf(parseTypeVariable))?) ~ ("=" ~> parseType)
  346. -> ((x, ys, t) => TypeAlias(x, ys getOrElse Nil, t))
  347. //ident = name of SL
  348. //ListOf gives square braces
  349. //DeclSL A [B,C] []
  350. | "DeclSL" ~> ident ~ (ListOf(ident)) ~ (ListOf(ident)) -> SecurityLevelDeclaration
  351. | failExpecting("declaration (val, def, type, etc.)"))
  352. def performInclude(includeName: String): Parser[Include] = {
  353. val newInputContext = try {
  354. envServices.openInclude(includeName, inputContext, options)
  355. } catch {
  356. case e: IOException => return err(e.toString)
  357. }
  358. OrcIncludeParser(newInputContext, options, envServices) match {
  359. case r: OrcIncludeParser.SuccessT[_] => success(r.get)
  360. case n: OrcIncludeParser.NoSuccess => Parser { in => Error(n.msg, new Input { def first = null; def rest = this; def pos = n.next.pos; def atEnd = true }) }
  361. }
  362. }
  363. ////////
  364. // Include file
  365. ////////
  366. val parseDeclarations: Parser[List[Declaration]] = parseDeclaration*
  367. ////////
  368. // Orc program
  369. ////////
  370. val parseProgram: Parser[Expression] = parseExpression
  371. ////////
  372. // Helper functions
  373. ////////
  374. def CommaSeparated[T](P: => Parser[T]): Parser[List[T]] = repsep(P, ",")
  375. def CommaSeparated1[T](P: => Parser[T]): Parser[List[T]] = rep1sep(P, ",")
  376. def TupleOf[T](P: => Parser[T]): Parser[List[T]] = "(" ~> CommaSeparated(P) <~ ")"
  377. def ListOf[T](P: => Parser[T]): Parser[List[T]] = "[" ~> CommaSeparated(P) <~ "]"
  378. def RecordOf[T](separator: String, P: => Parser[T]): Parser[List[(String, T)]] = {
  379. def parseEntry: Parser[(String, T)] = {
  380. (ident <~ separator) ~ P ^^ { case x ~ e => (x, e) }
  381. }
  382. "{." ~> CommaSeparated(parseEntry) <~ ".}"
  383. }
  384. /* Override scala.util.parsing.combinator.Parsers.accept to clean up
  385. * bad interaction between lexical ErrorTokens containing an error
  386. * message and the higher-level parser error message */
  387. override implicit def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)(_ match {
  388. case et: lexical.ErrorToken => et.chars.stripPrefix("*** error: ")
  389. case in => "" + e + " expected, but " + in + " found"
  390. })
  391. def failExpecting(symbolName: String) = Parser { in =>
  392. in.first match {
  393. case et: lexical.ErrorToken => Failure(et.chars.stripPrefix("*** error: "), in)
  394. case t => Failure(symbolName + " expected, but " + t + " found", in)
  395. }
  396. }
  397. def failUnexpectedIn(symbolName: String) = Parser { in =>
  398. in.first match {
  399. case et: lexical.ErrorToken => Failure(et.chars.stripPrefix("*** error: "), in)
  400. case t => Failure("while parsing " + symbolName + ", found unexpected " + t, in)
  401. }
  402. }
  403. }