XCTLParagraphStatement.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //
  2. // XCTLParagraph.swift
  3. // notebook
  4. //
  5. // Created by 邢铖 on 2023/5/25.
  6. //
  7. import Foundation
  8. internal class XCTLParagraphStatement: XCTLStatement, XCTLLateExecuteStatement {
  9. var type: XCTLStatementType { .typeParagraph }
  10. var holdingObject: XCTLRuntimeVariable { .void }
  11. var paragraphName = ""
  12. var argumentIdList = [String]()
  13. var runStatements = XCTLListStatement()
  14. weak var parent: XCTLStatement?
  15. var selectorAppendix = ""
  16. func matchSelfStatement(lex: XCTLLexer) throws -> XCTLStatement? {
  17. if try lex.next().type == .typeParagraph {
  18. return XCTLParagraphStatement()
  19. }
  20. return nil
  21. }
  22. func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
  23. self.parent = fromParent
  24. try lex.next()
  25. let nameToken = try lex.next()
  26. guard nameToken.type == .typeIdentifier else {
  27. throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIdentifier.rawValue, butGot: nameToken.rawValue)
  28. }
  29. self.paragraphName = nameToken.rawValue
  30. if try lex.peek().type == .typeOpenBracket {
  31. try lex.next()
  32. var firstArg = true
  33. while try lex.peek().type != .typeCloseBracket {
  34. let pos = lex.position
  35. if (try? lex.next().type) == .typeIdentifier,
  36. (try? lex.next().type) == .typeColon {
  37. lex.position = pos
  38. var flag = try lex.next().rawValue
  39. try lex.next()
  40. if firstArg {
  41. selectorAppendix.append("With")
  42. flag = flag.removeFirst().uppercased() + flag
  43. }
  44. selectorAppendix.append(flag)
  45. } else {
  46. lex.position = pos
  47. if !firstArg {
  48. selectorAppendix.append("_")
  49. }
  50. }
  51. selectorAppendix.append(":")
  52. let idToken = try lex.next()
  53. if idToken.type != .typeIdentifier {
  54. throw XCTLCompileTimeError.unexpectTokenInStatement(expect: XCTLTokenType.typeIdentifier.rawValue, butGot: idToken.rawValue)
  55. }
  56. self.argumentIdList.append(idToken.rawValue)
  57. firstArg = false
  58. }
  59. try lex.next()
  60. }
  61. self.paragraphName.append(self.selectorAppendix)
  62. self.runStatements.parent = self
  63. self.runStatements.paragraphHold = true
  64. try self.runStatements.parseStatement(fromLexerToSelf: lex, fromParent: self)
  65. if lex.paragraphTable[self.paragraphName] != nil {
  66. throw XCTLCompileTimeError.tooMuchParagraphDefinitionForName(name: self.paragraphName)
  67. }
  68. lex.paragraphTable[self.paragraphName] = self
  69. lex.lastStatement = self
  70. }
  71. func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
  72. return .void
  73. }
  74. func doRealEvaluate(inContext context: XCTLRuntimeAbstractContext,
  75. withArgs args: [XCTLRuntimeVariable]) throws -> XCTLRuntimeVariable {
  76. let subContext = context.makeSubContext()
  77. var argId = 0
  78. for argumentId in self.argumentIdList {
  79. if argId >= args.count {
  80. throw XCTLRuntimeError.paragraphArgsNotEnough(needCount: self.argumentIdList.count, butGot: args.count)
  81. }
  82. subContext.setValueIgnoreParent(args[argId], forName: argumentId)
  83. argId += 1
  84. }
  85. return try self.runStatements.evaluate(inContext: subContext)
  86. }
  87. }