XCTLPrefixExpression.swift 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //
  2. // XCTLPrefixExpression.swift
  3. // XCTreeLang
  4. //
  5. // Created by 邢铖 on 2023/6/2.
  6. //
  7. import Foundation
  8. internal class XCTLPrefixExpression: XCTLStatement, XCTLExpression {
  9. var type: XCTLStatementType { .expressionPrefix }
  10. var holdingObject: XCTLRuntimeVariable { .void }
  11. var parent: XCTLStatement?
  12. var statements = [XCTLStatement]()
  13. func matchSelfStatement(lex: XCTLLexer) throws -> XCTLStatement? {
  14. fatalError("\(self.type.rawValue) can not parse automatically.")
  15. }
  16. func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?) throws {
  17. fatalError("\(self.type.rawValue) can not parse automatically.")
  18. }
  19. func parseStatement(fromLexerToSelf lex: XCTLLexer, fromParent: XCTLStatement?, terminatorType: XCTLTokenType) throws {
  20. self.parent = fromParent
  21. var stackValue = 0
  22. while try lex.peek().type != terminatorType {
  23. var stmt: XCTLStatement & XCTLExpressionPart
  24. let position = lex.position
  25. do {
  26. stmt = try self.parseNextStatement(forLexer: lex, prototypes: XCTLExpressionPrototypes) as! XCTLStatement & XCTLExpressionPart
  27. } catch _ as XCTLCompileTimeError {
  28. lex.position = position
  29. break
  30. }
  31. stackValue += stmt.expressionValue.rawValue
  32. if stackValue > 1 {
  33. lex.position = position
  34. break
  35. }
  36. self.statements.append(stmt)
  37. if stmt.type == .typeFunctionCall {
  38. break
  39. }
  40. }
  41. }
  42. func evaluate(inContext context: XCTLRuntimeAbstractContext) throws -> XCTLRuntimeVariable {
  43. let originalVariableStack = context.variableStack
  44. let variableStack = XCTLRuntimeVariableStackFrame()
  45. context.variableStack = variableStack
  46. for it in statements {
  47. _ = try it.evaluate(inContext: context)
  48. }
  49. guard let resultValue = variableStack.popVariable() else {
  50. throw XCTLRuntimeError.variableStackNoObject
  51. }
  52. if !variableStack.isEmpty {
  53. throw XCTLRuntimeError.variableStackNotEmptyAfterTerminator
  54. }
  55. context.variableStack = originalVariableStack
  56. return resultValue
  57. }
  58. }