FFL: Fine-grained Fault Localization for Student Programs via Syntactic and Semantic Reasoning